Skip to content

david-gibbs-ig/quickfixj-spring-boot-starter

 
 

Repository files navigation

Build Status codecov Maven Central Apache 2 QuickFIX/J 2.3.1 Codacy code quality

Spring Boot Starter for QuickFIX/J (Spring Boot 2)

This project is a Spring Boot Starter for QuickFIX/J messaging engine for the FIX protocol. It simplifies the configuration required to create and start an Initiator or Acceptor, and handles the lifecycle of the Connector.

Getting started

To use the QuickFIX/J Server or QuickFIX/J Client you have to add the QuickFIX/J Spring Boot Starter dependency in your project.

<dependency>
    <groupId>io.allune</groupId>
    <artifactId>quickfixj-spring-boot-starter</artifactId>
    <version>2.10.1</version>
</dependency>

To enable the actuator endpoints you will also have to add the QuickFIX/J Spring Boot Actuator dependency.

<dependency>
    <groupId>io.allune</groupId>
    <artifactId>quickfixj-spring-boot-actuator</artifactId>
    <version>2.10.1</version>
</dependency>

QuickFIX/J Spring Boot Starter - Server (Acceptor)

The @EnableQuickFixJServer will auto configure a QuickFIX/J Server:

@EnableQuickFixJServer
@SpringBootApplication
public class AppServer {

    public static void main(String[] args) {
        SpringApplication.run(AppServer.class, args);
    }
}

The configuration can be done in the application.properties / application.yml.

quickfixj.server.config=classpath:quickfixj-server.cfg
quickfixj:
  server:
    config: classpath:quickfixj-server.cfg

Additionally you need to add a quickfixj-server.cfg file to configure the FIX sessions. The configuration is resolved using the following approach:

  • By a QuickFIX/J acceptor configuration string defined by the quickfixj.server.configString property

  • By the presence of a quickfix.SessionSettings bean named serverSessionSettings

  • By a configuration file defined by the quickfixj.server.config property

  • By the presence of the quickfixj.server.config system property

  • By a quickfixj-server.cfg in the working directory or at the root of the classpath

QuickFIX/J Server properties

quickfixj.server.config=classpath:quickfixj-server.cfg              # location of the quickfixj acceptor configuration file
quickfixj.server.auto-startup=true                                  # whether to auto-connect to the remote endpoint at start up (default: `true`)
quickfixj.server.force-disconnect=false                             # whether logged on sessions should be disconnected forcibly when the connector is stopped (default: `false`)
quickfixj.server.phase=0                                            # phase in which this connection manager should be started and stopped (default: `Integer.MAX_VALUE`)
quickfixj.server.jmx-enabled=true                                   # whether to register the jmx mbeans for the acceptor (default: `false`)
quickfixj.server.message-store-factory=memory                       # [cachedfile,file,jdbc,memory,noop,sleepycat] (default: `memory`)
quickfixj.server.log-factory=screen                                 # [compositelog,file,jdbc,slf4j,screen] (default: `screen`)

quickfixj.server.concurrent.enabled=true                            # whether to use a simple SocketAcceptor or a ThreadedSocketAcceptor (default: `false` - uses `SocketAcceptor`)
quickfixj.server.concurrent.useDefaultExecutorFactory=true          # whether to use a default ExecutorFactory to create the SocketAcceptor (default: `false`)
quickfixj.server.concurrent.queueCapacity=Integer.MAX_VALUE         # when using the default ExecutorFactory, the Executor's queue capacity (default: `Integer.MAX_VALUE`)
quickfixj.server.concurrent.corePoolSize=8                          # when using the default ExecutorFactory, the Executor's core pool size (default: `8`)
quickfixj.server.concurrent.maxPoolSize=Integer.MAX_VALUE           # when using the default ExecutorFactory, the Executor's max pool size (default: `Integer.MAX_VALUE`)
quickfixj.server.concurrent.allowCoreThreadTimeOut=true             # when using the default ExecutorFactory, whether to allow core thread timeout on the Executor (default: `true`)
quickfixj.server.concurrent.keepAliveSeconds=60                     # when using the default ExecutorFactory, the Executor's keep alive in seconds (default: `60`)
quickfixj.server.concurrent.waitForTasksToCompleteOnShutdown=false  # when using the default ExecutorFactory, whether to wait for tasks to complete on shutdown on the Executor (default: `false`)
quickfixj.server.concurrent.awaitTerminationSeconds=0                # when using the default ExecutorFactory, the Executor's await termination in seconds (default: `0`)
quickfixj.server.concurrent.threadNamePrefix="QuickFixJ Spring Boot Starter thread-" # when using the default ExecutorFactory, the Executor's thread name prefix (default: `QuickFixJ Spring Boot Starter thread-`)
quickfixj:
  server:
    config: classpath:quickfixj-server.cfg
    auto-startup: true
    force-disconnect: false
    phase: 0
    jmx-enabled: true
    concurrent:
      enabled: true
      useDefaultExecutorFactory: true
      queueCapacity: Integer.MAX_VALUE
      corePoolSize: 8
      maxPoolSize: Integer.MAX_VALUE
      allowCoreThreadTimeOut: true
      keepAliveSeconds: 60
      waitForTasksToCompleteOnShutdown: false
      awaitTerminationMillis: 0
      threadNamePrefix: "QuickFixJ Spring Boot Starter thread-"
    message-store-factory: memory
    log-factory: screen

QuickFIX/J acceptor configuration file in properties and yaml files

Using the quickfixj.server.configString property:

quickfixj.server.configString=[default]  \r\n\
                              FileStorePath=target/data/executor  \r\n\
                              ConnectionType=acceptor  \r\n\
                              StartTime=00:00:00  \r\n\
                              EndTime=00:00:00  \r\n\
                              HeartBtInt=30  \r\n\
                              ValidOrderTypes=1,2,F  \r\n\
                              SenderCompID=EXEC  \r\n\
                              TargetCompID=BANZAI  \r\n\
                              UseDataDictionary=Y  \r\n\
                              DefaultMarketPrice=12.30  \r\n\
                              FileLogPath=logs-server  \r\n\
                              \r\n\
                              [session]  \r\n\
                              BeginString=FIX.4.0  \r\n\
                              SocketAcceptPort=9876  \r\n\
                              \r\n\
                              [session]  \r\n\
                              BeginString=FIX.4.1  \r\n\
                              SocketAcceptPort=9877  \r\n\
                              \r\n\
                              [session]  \r\n\
                              BeginString=FIX.4.2  \r\n\
                              SocketAcceptPort=9878  \r\n\
                              \r\n\
                              [session]  \r\n\
                              BeginString=FIX.4.3  \r\n\
                              SocketAcceptPort=9879  \r\n\
                              \r\n\
                              [session]  \r\n\
                              BeginString=FIX.4.4  \r\n\
                              SocketAcceptPort=9880  \r\n\
                              \r\n\
                              [session]  \r\n\
                              BeginString=FIXT.1.1  \r\n\
                              DefaultApplVerID=FIX.5.0SP2  \r\n\
                              SocketAcceptPort=9881
quickfixj:
  server:
    configString: |
      [default]
      FileStorePath=target/data/executor
      ConnectionType=acceptor
      StartTime=00:00:00
      EndTime=00:00:00
      HeartBtInt=30
      ValidOrderTypes=1,2,F
      SenderCompID=EXEC
      TargetCompID=BANZAI
      UseDataDictionary=Y
      DefaultMarketPrice=12.30
      FileLogPath=logs-server

      [session]
      BeginString=FIX.4.0
      SocketAcceptPort=9876

      [session]
      BeginString=FIX.4.1
      SocketAcceptPort=9877

      [session]
      BeginString=FIX.4.2
      SocketAcceptPort=9878

      [session]
      BeginString=FIX.4.3
      SocketAcceptPort=9879

      [session]
      BeginString=FIX.4.4
      SocketAcceptPort=9880

      [session]
      BeginString=FIXT.1.1
      DefaultApplVerID=FIX.5.0SP2
      SocketAcceptPort=9881

QuickFIX/J Server Actuator properties

management.endpoint.quickfixjserver.enabled=true # whether the endpoint is enabled or not
management.endpoints.web.exposure.include=quickfixjserver # whether the endpoint will be exposed
management:
  endpoint:
    quickfixjserver:
      enabled: true
  endpoints:
    web:
      exposure:
        include: quickfixjserver

Example usage:

http://localhost:8081/actuator/quickfixjserver
{
  "FIX.4.2:EXEC->BANZAI": {
    "SenderCompID": "EXEC",
    "StartTime": "00:00:00",
    "DefaultMarketPrice": "12.30",
    "ValidOrderTypes": "1,2,F",
    "ConnectionType": "acceptor",
    "EndTime": "00:00:00",
    "BeginString": "FIX.4.2",
    "SocketAcceptPort": "9878",
    "TargetCompID": "BANZAI",
    "SenderCompID": "EXEC",
    "HeartBtInt": "30",
    "BeginString": "FIX.4.2",
    "TargetCompID": "BANZAI",
    "FileStorePath": "target/data/executor",
    "UseDataDictionary": "Y"
  },
  "FIX.4.1:EXEC->BANZAI": {
    "SenderCompID": "EXEC",
    "StartTime": "00:00:00",
    "DefaultMarketPrice": "12.30",
    "ValidOrderTypes": "1,2,F",
    "ConnectionType": "acceptor",
    "EndTime": "00:00:00",
    "BeginString": "FIX.4.1",
    "SocketAcceptPort": "9877",
    "TargetCompID": "BANZAI",
    "SenderCompID": "EXEC",
    "HeartBtInt": "30",
    "BeginString": "FIX.4.1",
    "TargetCompID": "BANZAI",
    "FileStorePath": "target/data/executor",
    "UseDataDictionary": "Y"
  }
}

QuickFIX/J Spring Boot Starter - Client (Initiator)

The @EnableQuickFixJClient will auto configure a QuickFIX/J Client:

@EnableQuickFixJClient
@SpringBootApplication
public class AppClient {

    public static void main(String[] args) {
        SpringApplication.run(AppClient.class, args);
    }
}

The configuration can be done in the application.properties / application.yml.

quickfixj.client.config=classpath:quickfixj-client.cfg
quickfixj:
  client:
    config: classpath:quickfixj-client.cfg

Additionally you need to add a quickfixj-client.cfg file to configure the FIX sessions. The configuration is resolved using the following approach:

  • By a QuickFIX/J initiator configuration string defined by the quickfixj.client.configString property

  • By the presence of a quickfix.SessionSettings bean named clientSessionSettings

  • By a configuration file defined by the quickfixj.client.config property

  • By the presence of the quickfixj.client.config system property

  • By a quickfixj-client.cfg in the working directory or at the root of the classpath

QuickFIX/J Client properties

quickfixj.client.config=classpath:quickfixj-client.cfg              # location of the quickfixj initiator
quickfixj.client.auto-startup=true                                  # whether to auto-connect to the remote endpoint at start up (default: `true`)
quickfixj.client.phase=0                                            # phase in which this connection manager should be started and stopped (default: `Integer.MAX_VALUE`)
quickfixj.client.jmx-enabled=true                                   # whether to register the jmx mbeans for the initiator (default: `false`)
quickfixj.client.message-store-factory=memory                       # [cachedfile,file,jdbc,memory,noop,sleepycat] (default: `memory`)
quickfixj.client.log-factory=screen                                 # [compositelog,file,jdbc,slf4j,screen] (default: `screen`)

quickfixj.client.concurrent.enabled=true                            # whether to use a simple SocketInitiator or a ThreadedSocketInitiator (default: `false` - uses `SocketInitiator`)
quickfixj.client.concurrent.useDefaultExecutorFactory=true          # whether to use a default ExecutorFactory to create the SocketInitiator (default: `false`)
quickfixj.client.concurrent.queueCapacity=Integer.MAX_VALUE         # when using the default ExecutorFactory, the Executor's queue capacity (default: `Integer.MAX_VALUE`)
quickfixj.client.concurrent.corePoolSize=8                          # when using the default ExecutorFactory, the Executor's core pool size (default: `8`)
quickfixj.client.concurrent.maxPoolSize=Integer.MAX_VALUE           # when using the default ExecutorFactory, the Executor's max pool size (default: `Integer.MAX_VALUE`)
quickfixj.client.concurrent.allowCoreThreadTimeOut=true             # when using the default ExecutorFactory, whether to allow core thread timeout on the Executor (default: `true`)
quickfixj.client.concurrent.keepAliveSeconds=60                     # when using the default ExecutorFactory, the Executor's keep alive in seconds (default: `60`)
quickfixj.client.concurrent.waitForTasksToCompleteOnShutdown=false  # when using the default ExecutorFactory, whether to wait for tasks to complete on shutdown on the Executor (default: `false`)
quickfixj.client.concurrent.awaitTerminationSeconds=0                # when using the default ExecutorFactory, the Executor's await termination in seconds (default: `0`)
quickfixj.client.concurrent.threadNamePrefix="QuickFixJ Spring Boot Starter thread-" # when using the default ExecutorFactory, the Executor's thread name prefix (default: `QuickFixJ Spring Boot Starter thread-`)
quickfixj:
  client:
    config: classpath:quickfixj-server.cfg
    auto-startup: true
    force-disconnect: false
    phase: 0
    jmx-enabled: true
    concurrent:
      enabled: true
      useDefaultExecutorFactory: true
      queueCapacity: Integer.MAX_VALUE
      corePoolSize: 8
      maxPoolSize: Integer.MAX_VALUE
      allowCoreThreadTimeOut: true
      keepAliveSeconds: 60
      waitForTasksToCompleteOnShutdown: false
      awaitTerminationMillis: 0
      threadNamePrefix: "QuickFixJ Spring Boot Starter thread-"
    message-store-factory: memory
    log-factory: screen

QuickFIX/J initiator configuration file in properties and yaml files

Using the quickfixj.client.configString property:

quickfixj.client.configString=[default] \r\n\
                              FileStorePath=target/data/banzai \r\n\
                              ConnectionType=initiator \r\n\
                              SenderCompID=BANZAI \r\n\
                              TargetCompID=EXEC \r\n\
                              SocketConnectHost=localhost \r\n\
                              StartTime=00:00:00 \r\n\
                              EndTime=00:00:00 \r\n\
                              HeartBtInt=30 \r\n\
                              ReconnectInterval=5 \r\n\
                              FileLogPath=logs-client \r\n\
                              \r\n\
                              [session] \r\n\
                              BeginString=FIX.4.0 \r\n\
                              SocketConnectPort=9876 \r\n\
                              \r\n\
                              [session] \r\n\
                              BeginString=FIX.4.1 \r\n\
                              SocketConnectPort=9877 \r\n\
                              \r\n\
                              [session] \r\n\
                              BeginString=FIX.4.2 \r\n\
                              SocketConnectPort=9878 \r\n\
                              \r\n\
                              [session] \r\n\
                              BeginString=FIX.4.3 \r\n\
                              SocketConnectPort=9879 \r\n\
                              \r\n\
                              [session] \r\n\
                              BeginString=FIX.4.4 \r\n\
                              SocketConnectPort=9880 \r\n\
                              \r\n\
                              [session] \r\n\
                              BeginString=FIXT.1.1 \r\n\
                              DefaultApplVerID=FIX.5.0SP2 \r\n\
                              SocketConnectPort=9881
quickfixj:
  client:
    configString: |
      [default]
      FileStorePath=target/data/banzai
      ConnectionType=initiator
      SenderCompID=BANZAI
      TargetCompID=EXEC
      SocketConnectHost=localhost
      StartTime=00:00:00
      EndTime=00:00:00
      HeartBtInt=30
      ReconnectInterval=5
      FileLogPath=logs-client

      [session]
      BeginString=FIX.4.0
      SocketConnectPort=9876

      [session]
      BeginString=FIX.4.1
      SocketConnectPort=9877

      [session]
      BeginString=FIX.4.2
      SocketConnectPort=9878

      [session]
      BeginString=FIX.4.3
      SocketConnectPort=9879

      [session]
      BeginString=FIX.4.4
      SocketConnectPort=9880

      [session]
      BeginString=FIXT.1.1
      DefaultApplVerID=FIX.5.0SP2
      SocketConnectPort=9881

QuickFIX/J Client Actuator properties

management.endpoint.quickfixjclient.enabled=true # whether the endpoint is enabled or not
management.endpoints.web.exposure.include=quickfixjclient # whether the endpoint will be exposed
management:
  endpoint:
    quickfixjclient:
      enabled: true
  endpoints:
    web:
      exposure:
        include: quickfixjclient

Example usage:

http://localhost:8080/actuator/quickfixjclient
{
  "FIXT.1.1:BANZAI->EXEC": {
    "SenderCompID": "BANZAI",
    "StartTime": "00:00:00",
    "ConnectionType": "initiator",
    "EndTime": "00:00:00",
    "BeginString": "FIXT.1.1",
    "ReconnectInterval": "5",
    "TargetCompID": "EXEC",
    "DefaultApplVerID": "FIX.5.0",
    "SocketConnectHost": "localhost",
    "SenderCompID": "BANZAI",
    "HeartBtInt": "30",
    "BeginString": "FIXT.1.1",
    "TargetCompID": "EXEC",
    "FileStorePath": "target/data/banzai",
    "SocketConnectPort": "9881"
  },
  "FIX.4.2:BANZAI->EXEC": {
    "SenderCompID": "BANZAI",
    "StartTime": "00:00:00",
    "ConnectionType": "initiator",
    "EndTime": "00:00:00",
    "BeginString": "FIX.4.2",
    "ReconnectInterval": "5",
    "TargetCompID": "EXEC",
    "SocketConnectHost": "localhost",
    "SenderCompID": "BANZAI",
    "HeartBtInt": "30",
    "BeginString": "FIX.4.2",
    "TargetCompID": "EXEC",
    "FileStorePath": "target/data/banzai",
    "SocketConnectPort": "9878"
  }
}

Listening on quickfixj.Application messages

The QuickFIX/J Spring Boot Starter provides a default implementation for the quickfixj.Application interface which publishes the messages received by the Server (Acceptor) and the Client (Initiator) as `ApplicationEvent`s.

If your application is only processing a subset of message types (i.e. toAdmin, toApp, onCreate, etc.) you will need to register an EventListener for these, with the appropriate message type as the only parameter for the listener method:

@EventListener
public void listenFromAdmin(FromAdmin fromAdmin) {
	...
}

@EventListener
public void listenFromApp(FromApp fromApp) {
	...
}

@EventListener
public void listenOnCreate(Create create) {
	...
}

@EventListener
public void listenOnLogon(Logon logon) {
	...
}

@EventListener
public void listenOnLogout(Logout logout) {
	...
}

@EventListener
public void listenToAdmin(ToAdmin toAdmin) {
	...
}

@EventListener
public void listenToApp(ToApp toApp) {
	...
}

In case the EventListener method throws an exception, this exception will be propagated up the quickfix.Session#next() method. Depending on the value of RejectMessageOnUnhandledException in the quickfixj configuration file, the message will be redelivered or dismissed.

QuickFixJTemplate

The QuickFixJTemplate provides a synchronous client to perform requests, exposing a simple, template method API over the QuickFIX/J client.

The QuickFIX/J Spring Boot Starter provides a quickFixJTemplate bean than can be Autowired in the application.

@Autowire
private QuickFixJTemplate quickFixJTemplate;

...

SessionID sessionID = serverAcceptor.getSessions().stream()
        .filter(sessId ->
                sessId.getBeginString().equals(fixVersion) &&
                        sessId.getTargetCompID().equals(targetId))
        .findFirst()
        .orElseThrow(RuntimeException::new);

OrderCancelRequest message = new OrderCancelRequest(
        new OrigClOrdID("123"),
        new ClOrdID("321"),
        new Symbol("LNUX"),
        new Side(Side.BUY));

quickFixJTemplate.send(message, sessionID);

Examples Projects

License and Acknowledgement

The QuickFIX/J Spring Boot Starter is released under version 2.0 of the Apache License.

This code includes software developed by quickfixengine.org.

About

Spring Boot Starter for QuickFIX/J

Resources

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE
Unknown
licence-header.txt

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%