-
Notifications
You must be signed in to change notification settings - Fork 121
Codecs
If you want to use the encoders and decoders from Artio in order to parse or generate FIX then you should use the CodecGenerationTool
. It takes two arguments. The first is the output directory, and the second is the path to the XML dictionary to use to define the variant in use.
java -cp "fix-gateway-samples/build/libs/artio-samples.jar-${ARTIO-VERSION}-all.jar" \
uk.co.real_logic.artio.dictionary.CodecGenerationTool \
/path/to/generated-src/directory \
src/main/resources/your_fix_dictionary_file.xml
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
<phase>generate-sources</phase>
</execution>
</executions>
<configuration>
<mainClass>uk.co.real_logic.artio.dictionary.CodecGenerationTool</mainClass>
<arguments>
<argument>${project.build.directory}/generated-sources/java</argument>
<argument>src/main/resources/your_fix_dictionary_file.xml</argument>
</arguments>
</configuration>
</plugin>
task generateCodecs(type: JavaExec) {
main = 'uk.co.real_logic.artio.dictionary.CodecGenerationTool'
classpath = sourceSets.main.runtimeClasspath
args = ['/path/to/generated-src/directory', 'src/main/resources/your_fix_dictionary_file.xml']
outputs.dir '/path/to/generated-src/directory'
}
Artio's core is compiled against a minimal set of FIX codecs that are placed into the artio-session-codecs
and artio-session-fixt-codecs
projects. Once you've generated the correct set of FIX codecs from your FIX XML dictionary then you should exclude the default ones that are shipped with Artio - you don't want them both on your classpath at the same time.
In gradle you can use a configurations based exclude - this should be placed in the same scope as the dependencies section that uses artio.
configurations.all {
exclude module: 'artio-session-codecs'
exclude module: 'artio-session-fixt-codecs'
}
In maven you should add the exclusion to your dependency block:
<dependency>
<groupId>uk.co.real-logic</groupId>
<artifactId>artio-core</artifactId>
<version>LATEST_ARTIO_VERSION</version>
<exclusions>
<exclusion>
<groupId>uk.co.real-logic</groupId>
<artifactId>artio-session-codecs</artifactId>
</exclusion>
<exclusion>
<groupId>uk.co.real-logic</groupId>
<artifactId>artio-session-fixt-codecs</artifactId>
</exclusion>
</exclusions>
</dependency>
The generated Codecs are objects that are designed to be re-used over multiple messages in order to minimise the amount of garbage generated during steady-state usage.
The decoders parse into internal buffers that are re-used over multiple parses. If the input data is longer than the existing buffer size then the buffer will grow. Allocation only happens when you grow the buffer. Since messages never have infinitely increasing message sizes you will eventually hit the max size of the buffer.
Internally for parsing String values we convert into a char[] and length for the field. This means that if you retrieve the char[] value you always need to be aware that it is only the first length
number of characters that are relevant values. There is also an easy AsString
variant of each method that will allocate you a String if you prefer an easier programming model and are less latency sensitive.
Each of the generated methods follows a common naming scheme, to take the String username
field of a LogonDecoder
as an example:
-
username()
- Thechar[]
value getter. -
usernameLength()
- Theint
getter for the length of the char[] value. -
usernameAsString()
- The higher overhead, but easier to use variant that returnsjava.lang.String
values.
Codec validation can be switched on or off at runtime by setting the Java system property fix.codecs.no_validation
to either true
or false
. Validation checks syntactic issues around FIX messages. For example:
- Whether they only contain fields that are defined for that message.
- Whether all the required fields are present.
- Whether enum types only contain valid values.
In order to validate a FIX message that you have received and parsed, call validate()
on your decoder. Its boolean return value denotes whether the message is valid or not. If it's invalid then you can call decoder.invalidTagId()
to see which tag caused the validation to fail and decoder.rejectReason()
to see the reason why it failed.
If you've received a message and plan to parse another message then you should call reset()
on the decoder to ensure that no fields that were set from the previous message are still in use.