mrbela mrbela - 7 months ago 47
Java Question

QuickFIX/J mixing two different versions

I am writing an application that uses QuickFIX/J as FIX framework.
My counterpart sends me an

ExecutionReport
message of FIX version 4.4
But only some fields (the
Parties
component) are of version 5.0

Now I am trying to implement that I can read this component.

This one

@Override
public void onMessage(quickfix.fix44.ExecutionReport message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {

quickfix.fix50.component.Parties parties = new Parties();
message.get(parties);
// ...
}


doesn't work! Message is from version 4.4 and thats why
message.get(...)
only wants a
quickfix.fix44.component.Parties
, not one of version 5.0

If I try this

@Override
public void onMessage(quickfix.fix50.ExecutionReport message, SessionID sessionID)
throws FieldNotFound, UnsupportedMessageType, IncorrectTagValue {

// ...
}


I get the following error:

Exception in thread "pool-2-thread-1" java.lang.VerifyError: Bad type on operand stack
Exception Details:
Location:
quickfix/fix44/ExecutionReport.get(Lquickfix/field/SettlType;)Lquickfix/field/SettlType; @2: invokevirtual
Reason:
Type 'quickfix/field/SettlType' (current frame, stack[1]) is not assignable to 'quickfix/CharField'
Current Frame:
bci: @2
flags: { }
locals: { 'quickfix/fix44/ExecutionReport', 'quickfix/field/SettlType' }
stack: { 'quickfix/fix44/ExecutionReport', 'quickfix/field/SettlType' }
Bytecode:
0000000: 2a2b b600 5657 2bb0

at quickfix.fix44.MessageFactory.create(MessageFactory.java:195)
at quickfix.DefaultMessageFactory.create(DefaultMessageFactory.java:133)
at quickfix.MessageUtils.parse(MessageUtils.java:145)
at quickfix.mina.AbstractIoHandler.messageReceived(AbstractIoHandler.java:118)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.messageReceived(DefaultIoFilterChain.java:854)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:542)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:943)
at org.apache.mina.filter.codec.ProtocolCodecFilter$ProtocolDecoderOutputImpl.flush(ProtocolCodecFilter.java:405)
at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecFilter.java:235)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:542)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1300(DefaultIoFilterChain.java:48)
at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.messageReceived(DefaultIoFilterChain.java:943)
at org.apache.mina.core.filterchain.IoFilterAdapter.messageReceived(IoFilterAdapter.java:109)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextMessageReceived(DefaultIoFilterChain.java:542)
at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireMessageReceived(DefaultIoFilterChain.java:535)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.read(AbstractPollingIoProcessor.java:714)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:668)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.process(AbstractPollingIoProcessor.java:657)
at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$600(AbstractPollingIoProcessor.java:67)
at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:1121)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)


This is because I am getting 4.4 fields, but want to treat them like 4.4 versions.. Look here

Maybe anyone can help me...

Thanks for your effort!!

TT. TT.
Answer

One way to do this is to customize the Data Dictionary FIX4.4.xml and replace the fields in it that can sometimes be in FIX 5.0 format. Eg by copying them from FIX5.0.xml and placing them in the proper messages in FIX4.4.xml.

From the QuickFIX/J user manual:

The simplest customization is to just modify one or more data dictionaries (e.g., FIX44.xml) and rebuild QFJ. This allows you to add custom fields, define new messages not included in the specification, change whether fields are required or optional, and so on.

Afterwards rebuild QuickFIX/J to reflect these changes.

EDIT: Following is for version 1.5.x

Check the QuickFIX/J user FAQ on how to rebuild QuickFIX/J (EDIT: version 1.5.x):

You'll need ant installed.

QF/J generates the source from the DDs in core/src/main/resources. Make a back up of the one you're going to alter, and then alter it however you need to.

Then rebuild as follows:

  1. ant jar
  2. You will be prompted for a release number; this just determines the suffix given to the jar names. Enter whatever you want.
  3. Wait for build to finish
  4. Find your brand-new QF/J jars in core/target/

A little further in the FAQ (how do I rebuild QF/J) the call to ANT is more specific:

The version argument is just a filename suffix. The skip.jalopy argument is optional and will skip some time-consuming doc generation.

ant version=SOME_STRING -Dskip.jalopy=true clean jar

EDIT: Following is for version 1.6.x

For version 1.6.0 building is done with Maven.

If you are building the code from the command line you'll need to download and install Maven (version 3.2.5 or newer). If you are building from an IDE, Maven is usually included. Building from source requires Java 6+.

  1. Check out the code from GitHub. See the instructions at GitHub for more details on cloning the repository.
  2. Change directory to the top-level directory of the checked out code. You should see a pom.xml file.
  3. Run mvn package to build the QuickFIX/J and examples jar files. This will also generate all the FIX message-related code for the various FIX versions.
  4. There is an option for the code generator to use BigDecimal instead of double for fields like price and quantity. To enable this feature pass a -Dgenerator.decimal option on the command line when running the generate.code target.

There are various command-line switches you can pass to ant to modify the produced behavior:

Switch                  Description                             Default
-Dgenerator.decimal     Generate BigDecimal vs doubles fields   false
-DskipAT=true           Skip running of acceptance test suite.  false

For example, in order to generate fields with BigDecimals and skip acceptance tests:

mvn test -Dgenerator.decimal=true -DskipAT=true