Skip to content

Multiple FIX Versions

Richard Warburton edited this page Jul 28, 2021 · 8 revisions

Artio instances can support multiple versions of the FIX protocol concurrently within the same instance. This is supported both as an initiator (client) and for using Artio as a FIX acceptor (server).

Multiple concurrent FIX versions require changes to the way that you generate codecs and potentially to session customisation. Differences for initiator and acceptor configuration are detailed below.

Codec Generation

Artio has an interface for each FIX session message that it handles or operates on. These interfaces all have the prefix Abstract, for example AbstractLogonDecoder is the interface for the LogonDecoder implementation. The interface used to refer to a specific FIX dictionary version is called the FixDictionary and there is a FixDictionaryImpl generated for each dictionary version.

The CodecGenerationTool needs to be run for different FIX protocol version that you want to support. You must specify a parent package that the codecs will be generated in by using the fix.codecs.parent_package system property and these packages should be different to each other. You should ensure that all of the required codecs are on the runtime classpath for both the Artio Library and Engine.

The examples below show how to set this package to uk.co.real_logic.artio.fixt.

Commandline Example

java -Dfix.codecs.parent_package=uk.co.real_logic.artio.fixt -cp "artio-codecs/build/libs/artio-codecs-${ARTIO-VERSION}.jar" \
uk.co.real_logic.artio.dictionary.CodecGenerationTool  \
/path/to/generated-src/directory \ 
src/main/resources/your_fix_dictionary_file.xml

Maven Example

<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>
        <systemProperties>
            <systemProperty>
                <key>fix.codecs.parent_package</key>
                <value>uk.co.real_logic.artio.fixt</value>
            </systemProperty>
        </systemProperties>
    </configuration>
</plugin>

Gradle Example

task generateCodecs(type: JavaExec) {
    main = 'uk.co.real_logic.artio.dictionary.CodecGenerationTool'
    classpath = sourceSets.main.runtimeClasspath
    systemProperty("fix.codecs.parent_package", "uk.co.real_logic.artio.fixt")
    args = ['/path/to/generated-src/directory', 'src/main/resources/your_fix_dictionary_file.xml']
    outputs.dir '/path/to/generated-src/directory'
}

Programmatic Usage

It might be the case that you wish to generate codecs from existing JVM code, for example integrating into a wider tool pipeline that isn't just a FIX engine. In this case it is recommended to use the uk.co.real_logic.artio.dictionary.generation.CodecGenerator class and provide an instance of a uk.co.real_logic.artio.dictionary.generation.CodecConfiguration that can be used to configure the codec generation.

new CodecConfiguration().parentPackage("uk.co.real_logic.artio.fixt").outputPath("/path/to/generated-src/directory");

Initiating a Session.

In order to specify which fix dictionary version is used for a given session you should set the fixDictionary property of the SessionConfiguration used to initiate the connection with the FixDictionaryImpl class for that version. For example the following code would set use the dictionary generated into uk.co.real_logic.artio.fixt.

import uk.co.real_logic.artio.fixt.FixDictionaryImpl;

sessionConfiguration.fixDictionary(FixDictionaryImpl.class)

Accepting a Session

When a client connects to your FIX acceptor (server) Artio needs to decide which FIX version to use in order to interpret the messages that it receives from the client. Artio has a concept of a "default" acceptor fix dictionary. This defaults to uk.co.real_logic.artio.FixDictionaryImpl which is also the default package for a fix dictionary to be generated by the codec generation tool. So if you're just using a single FIX version then there is no need to configure this default. If you want to alter this default then set EngineConfiguration.acceptorfixDictionary.

If you want to support multiple different FIX versions as an acceptor then the easiest way of doing this is by setting overrides. Call EngineConfiguration.overrideAcceptorFixDictionary() with the extra FIX dictionary as an argument. These fix versions are overridden on the Begin String field. When Artio receives a Logon message it will look at the begin string field and pick the dictionary with the matching begin string. If it can't find an override it will use the default.

If you need a more flexible way of configuring the Fix dictionary than simply using begin string versions as an acceptor then you can configure an AuthenticationStrategy using EngineConfiguration.authenticationStrategy(). When a Logon message is received by Artio your authenticateAsync will be invoked for that logon message and you can call AuthenticationProxy.accept(Class<? extends FixDictionary> fixDictionaryClass) with the fix dictionary that you want to accept. This code can perform any business logic needed based upon the logon message in order to identify the correct fix dictionary to use.

SessionCustomisationStrategy

When implementing a SessionCustomisationStrategy that supports different FIX versions you will be passed the interfaces AbstractLogonEncoder and AbstractLogoutEncoder. The types of these interfaces can be compared using Java's instanceof keyword and downcasted appropriately in order to apply modifications that are relevant to a specific FIX dictionary version. For example the following customisation strategy only set the applVerID field if the Logon message is for a FIXT protocol version.

import uk.co.real_logic.artio.fixt.builder.LogonEncoder;
import uk.co.real_logic.artio.fixt.ApplVerID;

class FixTSessionCustomisationStrategy implements SessionCustomisationStrategy
{
    private final ApplVerID applVerID;

    FixTSessionCustomisationStrategy(final ApplVerID applVerID)
    {
        this.applVerID = applVerID;
    }

    public void configureLogon(final AbstractLogonEncoder abstractLogon, final long sessionId)
    {
        if (abstractLogon instanceof LogonEncoder)
        {
            final LogonEncoder logon = (LogonEncoder)abstractLogon;
            logon.defaultApplVerID(applVerID.representation());
        }
    }

    public void configureLogout(final AbstractLogoutEncoder logout, final long sessionId)
    {
    }
}