QuickFIX/J常见问题汇总

最近在搞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

 

 

你可能感兴趣的:(常见问题)