您的位置:首页 > 产品设计 > UI/UE

QuickFIX/J常见问题汇总

2013-10-02 13:54 555 查看
最近在搞QuickFIX/J,网上的资料不算很多,遇到一些简单的问题都需要google一阵才能找到解决方法,因此做点记录:

错误:Rejecting invalid message: quickfix.UnsupportedMessageType

这个异常的产生,有两个条件:

1) UseDataDictionary = N

2) 没有覆盖对应的onMessage方法

具体说来,如果没有将UseDataDictionary设为N,几时没有覆盖对应的onMessage方法,也不会产生这个异常。

至于没有覆盖对应的onMessage方法,是指覆盖的onMessage方法,参数必须是接收的信息的类型:

//Will throws error
@Override
public void onMessage(Message message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue{
  super.onMessage(message, sessionID);
  System.out.println("--crack--");
}

//Correct!
@Override
public void onMessage(ExecutionReport message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
  System.out.println("--crack ER--");
}


如果接收的信息35=8(ExecutionReport),则需用第二个onMessage方法,而非第一个。

在FIX信息中,自定义域(Add new field)

在QuickFIX/J中新增自定义域,最简单的就是修改对应版本的xml文件,在xml文件里增加自定义域,然后在配置文件中设置如下:

UseDataDictionary=Y
DataDictionary=config/FIX42.xml

用这种方法去指定自定义的DataDictionary文件。

但此方法有两个缺点:

1) 接收信息,解析自定义域数据时,只能使用类型不安全的解析

@Override
public void onMessage(ExecutionReport message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {
System.out.println("--crack ER--");
StringField field = new StringField(10041);
System.out.println(message.getField(field).toString());
}


假设新增了10041这个域(FIX Tag),由于QuickFIX/J包里默认没有这个域对应的对象,这能使用这种方法取得这个域的值,而这种方法在官方文档里描述为类型不安全,并不推荐。

2) 当自定义域的信息含有Repeating Group时,会抛出Out of order repeating group members这个错误。暂时还未找到解决方法

最好的解决方法,是修改xml文件,新增自定义域(Field)和消息类型(Message Type)后,重新build一个自定义的.jar文件。

使用这种方法需要注意的是,如果自定义域和自定义消息类型只针对某一个版本的FIX,例如只修改了FIX42.xml,而QuickFIX/J默认是将所有的Field放在“quickfix.field”这个包里,并非如消息类型那样分开不同版本的包放,因此自定义的Field有可能会被其它版本(如FIX43/44)覆盖。

看来这个类quickfix.codegen.MessageCodeGenerator.java:

public static void main(String[] args) {
MessageCodeGenerator codeGenerator = new MessageCodeGenerator();
try {
if (args.length != 3) {
String classname = MessageCodeGenerator.class.getName();
System.err.println("usage: " + classname + " specDir xformDir outputBaseDir");
return;
}

boolean overwrite = getOption(OVERWRITE_OPTION, true);
boolean orderedFields = getOption(ORDERED_FIELDS_OPTION, false);
boolean useDecimal = getOption(BIGDECIMAL_TYPE_OPTION, false);

long start = System.currentTimeMillis();
//            final String[] vers = new String[] { "FIXT 1.1", "FIX 5.0", "FIX 4.4", "FIX 4.3", "FIX 4.2",
//                    "FIX 4.1", "FIX 4.0" };
final String[] vers = new String[] {"FIXT 1.1","FIX 4.2"};
for (int i = 0; i < vers.length; ++i) {
Task task = new Task();
task.setName(vers[i]);
final String temp = stripSpaces(vers[i]);
task.setSpecification(args[0] + "/" + temp + ".xml");
task.setTransformDirectory(args[1]);
task.setMessagePackage("quickfix." + temp.toLowerCase());
task.setOutputBaseDirectory(args[2]);
task.setFieldPackage("quickfix.field");
task.setOverwrite(overwrite);
task.setOrderedFields(orderedFields);
task.setDecimalGenerated(useDecimal);
codeGenerator.generate(task);
}
double duration = System.currentTimeMillis() - start;
DecimalFormat durationFormat = new DecimalFormat("#.###");
codeGenerator.log.info("Time for generation: "
+ durationFormat.format(duration / 1000L) + " seconds");
} catch (Exception e) {
codeGenerator.log.error("error during code generation", e);
System.exit(1);
}
}


留意注释部分是默认的实现。可以看到setMessagePackage和setFieldPackage之间的不同。

成功build了以后,就可以这样解析10041(name=BoInstrumentCode2)这个自定义域:

public void onMessage(quickfix.fix42.ExecutionReport message,
SessionID sessionID) throws FieldNotFound {

System.out.println(message.getBoInstrumentCode2().toString());
}


简单清晰,面向对象

参考:

http://www.quickfixj.org/confluence/display/qfj/User+FAQ

http://www.quickfixj.org/quickfixj/usermanual/1.5.3/usage/configuration.html#Sample Settings File
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: