| = QuickFix Component |
| :doctitle: QuickFix |
| :shortname: quickfix |
| :artifactid: camel-quickfix |
| :description: Open a Financial Interchange (FIX) session using an embedded QuickFix/J engine. |
| :since: 2.1 |
| :supportlevel: Stable |
| :tabs-sync-option: |
| :component-header: Both producer and consumer are supported |
| |
| *Since Camel {since}* |
| |
| *{component-header}* |
| |
| The Quickfix component adapts the |
| http://www.quickfixj.org/[QuickFIX/J] FIX engine for using in Camel. |
| This component uses the standard http://www.fixprotocol.org/[Financial |
| Interchange (FIX) protocol] for message transport. |
| |
| |
| Maven users will need to add the following dependency to their `pom.xml` |
| for this component: |
| |
| [source,xml] |
| ---- |
| <dependency> |
| <groupId>org.apache.camel</groupId> |
| <artifactId>camel-quickfix</artifactId> |
| <version>x.x.x</version> |
| <!-- use the same version as your Camel core version --> |
| </dependency> |
| ---- |
| |
| == URI format |
| |
| ---- |
| quickfix:configFile[?sessionID=sessionID&lazyCreateEngine=true|false] |
| ---- |
| |
| The `configFile` is the name of the QuickFIX/J configuration to use for |
| the FIX engine (located as a resource found in your classpath). The |
| optional `sessionID` identifies a specific FIX session. The format of |
| the sessionID is: |
| |
| ---- |
| (BeginString):(SenderCompID)[/(SenderSubID)[/(SenderLocationID)]]->(TargetCompID)[/(TargetSubID)[/(TargetLocationID)]] |
| ---- |
| |
| The optional `lazyCreateEngine` parameter allows |
| creating QuickFIX/J engine on demand: |
| |
| * The value `true` means the engine is |
| started when the first message is sent or there's consumer configured in |
| route definition. |
| * When the value `false` is used, the engine is started at |
| the endpoint creation. |
| |
| When this parameter is missing, the value of |
| component's property `lazyCreateEngines` is being used. |
| |
| .Example URIs: |
| ---- |
| quickfix:config.cfg |
| |
| quickfix:config.cfg?sessionID=FIX.4.2:MyTradingCompany->SomeExchange |
| |
| quickfix:config.cfg?sessionID=FIX.4.2:MyTradingCompany->SomeExchange&lazyCreateEngine=true |
| ---- |
| |
| == Endpoints |
| |
| FIX sessions are endpoints for the quickfix component. An endpoint URI |
| may specify a single session or all sessions managed by a specific |
| QuickFIX/J engine. Typical applications will use only one FIX engine, but |
| advanced users may create multiple FIX engines by referencing different |
| configuration files in quickfix component endpoint URIs. |
| |
| When a consumer does not include a session ID in the endpoint URI, it |
| will receive exchanges for all sessions managed by the FIX engine |
| associated with the configuration file specified in the URI. If a |
| producer does not specify a session in the endpoint URI, then it must |
| include the session-related fields in the FIX message being sent. If a |
| session is specified in the URI, then the component will automatically |
| inject the session-related fields into the FIX message. |
| |
| // component options: START |
| include::partial$component-configure-options.adoc[] |
| include::partial$component-endpoint-options.adoc[] |
| include::partial$component-endpoint-headers.adoc[] |
| // component options: END |
| |
| == Usage |
| |
| The `DataDictionary` exchange property is useful if string messages are |
| being received and need to be parsed in a route. QuickFIX/J requires a |
| data dictionary to parse certain types of messages (with repeating |
| groups, for example). By setting the `DataDictionary` exchange property |
| (`QuickfixjEndpoint.DATA_DICTIONARY_KEY`) in the route after receiving a |
| message string, the FIX engine can properly parse the data. The property |
| can hold a `quickfix.DataDictionary` instance or the name of a data |
| dictionary resource, such as `FIX44.xml`. When the property is not set, |
| the data dictionary of the session identified by the `SessionID` header |
| is used, if that session exists. |
| |
| === QuickFIX/J Configuration Extensions |
| |
| When using QuickFIX/J directly, one typically writes code to create |
| instances of logging adapters, message stores, and communication |
| connectors. The quickfix component will automatically create instances |
| of these classes based on information in the configuration file. It also |
| provides defaults for many of the commonly required settings and adds |
| additional capabilities (like the ability to activate JMX support). |
| |
| The following sections describe how the quickfix component processes |
| the QuickFIX/J configuration. For comprehensive information about |
| QuickFIX/J configuration, see the |
| http://www.quickfixj.org/quickfixj/usermanual/usage/configuration.html[user manual]. |
| |
| ==== Communication Connectors |
| |
| When the component detects an initiator or acceptor session setting in |
| the QuickFIX/J configuration file, it will automatically create the |
| corresponding initiator and/or acceptor connector. These settings can be |
| in the default or in a specific session section of the configuration |
| file. |
| |
| [width="100%",cols="10%,90%",options="header",] |
| |========================================================= |
| |Session Setting |Component Action |
| |`ConnectionType=initiator` |Create an initiator connector |
| |`ConnectionType=acceptor` |Create an acceptor connector |
| |========================================================= |
| |
| The threading model for the QuickFIX/J session connectors can also be |
| specified. These settings affect all sessions in the configuration file |
| and must be placed in the settings default section. |
| |
| [width="100%",cols="10%,90%",options="header",] |
| |======================================================================= |
| |Default/Global Setting |Component Action |
| |`ThreadModel=ThreadPerConnector` |Use `SocketInitiator` or |
| `SocketAcceptor` (default) |
| |
| |`ThreadModel=ThreadPerSession` |Use `ThreadedSocketInitiator` or |
| `ThreadedSocketAcceptor` |
| |======================================================================= |
| |
| ==== Logging |
| |
| The QuickFIX/J logger implementation can be specified by including the |
| following settings in the default section of the configuration file. The |
| `ScreenLog` is the default if none of the following settings are present |
| in the configuration. It's an error to include settings that imply more |
| than one log implementation. The log factory implementation can also be |
| set directly on the Quickfix component. This will override any related |
| values in the QuickFIX/J settings file. |
| |
| [width="100%",cols="10%,90%",options="header",] |
| |======================================================================= |
| |Default/Global Setting |Component Action |
| |`ScreenLogShowEvents` |Use a `ScreenLog` |
| |
| |`ScreenLogShowIncoming` |Use a `ScreenLog` |
| |
| |`ScreenLogShowOutgoing` |Use a `ScreenLog` |
| |
| |`SLF4J*` |Use a `SLF4JLog`. Any of the SLF4J settings |
| will cause this log to be used. |
| |
| |`FileLogPath` |Use a `FileLog` |
| |
| |`JdbcDriver` |Use a `JdbcLog` |
| |======================================================================= |
| |
| ==== Message Store |
| |
| The QuickFIX/J message store implementation can be specified by |
| including the following settings in the default section of the |
| configuration file. The `MemoryStore` is the default if none of the |
| following settings are present in the configuration. It's an error to |
| include settings that imply more than one message store implementation. |
| The message store factory implementation can also be set directly on the |
| Quickfix component. This will override any related values in the |
| QuickFIX/J settings file. |
| |
| [width="100%",cols="10%,90%",options="header",] |
| |============================================= |
| |Default/Global Setting |Component Action |
| |`JdbcDriver` |Use a `JdbcStore` |
| |`FileStorePath` |Use a `FileStore` |
| |`SleepycatDatabaseDir` |Use a `SleepcatStore` |
| |============================================= |
| |
| ==== Message Factory |
| |
| A message factory is used to construct domain objects from raw FIX |
| messages. The default message factory is `DefaultMessageFactory`. |
| However, advanced applications may require a custom message factory. |
| This can be set on the QuickFIX/J component. |
| |
| ==== JMX |
| |
| [width="100%",cols="10%,90%",options="header",] |
| |============================================ |
| |Default/Global Setting |Component Action |
| |`UseJmx` |if `Y`, then enable QuickFIX/J JMX |
| |============================================ |
| |
| ==== Other Defaults |
| |
| The component provides some default settings for what are normally |
| required settings in QuickFIX/J configuration files. `SessionStartTime` |
| and `SessionEndTime` default to "00:00:00", meaning the session will not |
| be automatically started and stopped. The `HeartBtInt` (heartbeat |
| interval) defaults to 30 seconds. |
| |
| ==== Minimal Initiator Configuration Example |
| |
| ---- |
| [SESSION] |
| ConnectionType=initiator |
| BeginString=FIX.4.4 |
| SenderCompID=YOUR_SENDER |
| TargetCompID=YOUR_TARGET |
| ---- |
| |
| === Using the InOut Message Exchange Pattern |
| |
| Although the FIX protocol is event-driven and asynchronous, there are |
| specific pairs of messages |
| that represent a request-reply message exchange. To use an InOut |
| exchange pattern, there should |
| be a single request message and single reply message to the request. |
| Examples include an |
| OrderStatusRequest message and UserRequest. |
| |
| ==== Implementing InOut Exchanges for Consumers |
| |
| Add `exchangePattern=InOut` to the QuickFIX/J endpoint URI. The |
| `MessageOrderStatusService` in |
| the example below is a bean with a synchronous service method. The |
| method returns the response |
| to the request (an ExecutionReport in this case) which is then sent back |
| to the requestor session. |
| |
| [tabs] |
| ==== |
| Java:: |
| + |
| [source,java] |
| ---- |
| from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER&exchangePattern=InOut") |
| .filter(header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.ORDER_STATUS_REQUEST)) |
| .bean(new MarketOrderStatusService()); |
| ---- |
| |
| YAML:: |
| + |
| [source,yaml] |
| ---- |
| - route: |
| from: |
| uri: quickfix:examples/inprocess.qf.cfg |
| parameters: |
| sessionID: "FIX.4.2:MARKET->TRADER" |
| exchangePattern: InOut |
| steps: |
| - filter: |
| expression: |
| simple: |
| expression: "${header.MessageType} == 'H'" |
| steps: |
| - bean: |
| beanType: com.example.MarketOrderStatusService |
| ---- |
| ==== |
| |
| In YAML, the headers are written by name: `MessageType` is `QuickfixjEndpoint.MESSAGE_TYPE_KEY`, and the type of an |
| OrderStatusRequest is `H`. |
| |
| The reply is always sent on the session the request was received on. |
| Changing the `SessionID` header while routing does not change where the |
| reply goes. To send a message to another session, use a QuickFIX/J |
| producer endpoint with the `sessionID` option. |
| |
| ==== Implementing InOut Exchanges for Producers |
| |
| For producers, sending a message will block until a reply is received or |
| a timeout occurs. There |
| is no standard way to correlate reply messages in FIX. Therefore, a |
| correlation criteria must be |
| defined for each type of InOut exchange. The correlation criteria and |
| timeout can be specified |
| using `Exchange` properties. |
| |
| [width="100%",cols="60%,10%,20%,10%",options="header",] |
| |======================================================================= |
| |Description |Key String |Key Constant |Default |
| |Correlation Criteria |`CorrelationCriteria` |
| |`QuickfixjProducer.CORRELATION_CRITERIA_KEY` |None |
| |
| |Correlation Timeout in Milliseconds |`CorrelationTimeout` |
| |`QuickfixjProducer.CORRELATION_TIMEOUT_KEY` |1000 |
| |======================================================================= |
| |
| The correlation criteria is defined with a `MessagePredicate` object. |
| The following example will treat |
| a FIX `ExecutionReport` from the specified session where the transaction |
| type is STATUS and the Order ID |
| matches our request. The session ID should be for the __requestor__, the |
| sender and target CompID fields |
| will be reversed when looking for the reply. |
| |
| ._Java-only: programmatic correlation criteria setup using QuickFIX/J API_ |
| [source,java] |
| ---- |
| exchange.setProperty(QuickfixjProducer.CORRELATION_CRITERIA_KEY, |
| new MessagePredicate(new SessionID(sessionID), MsgType.EXECUTION_REPORT) |
| .withField(ExecTransType.FIELD, Integer.toString(ExecTransType.STATUS)) |
| .withField(OrderID.FIELD, request.getString(OrderID.FIELD))); |
| ---- |
| |
| === Spring Configuration |
| |
| The QuickFIX/J component includes a Spring `FactoryBean` for configuring |
| the session settings within a Spring context. A type converter for |
| QuickFIX/J session ID strings is also included. The following example |
| shows a simple configuration of an acceptor and initiator session with |
| default settings for both sessions. |
| |
| ._XML-only: Spring XML configuration with QuickFIX/J component and session settings_ |
| [source,xml] |
| ---- |
| <!-- camel route --> |
| <camelContext xmlns="http://camel.apache.org/schema/spring" id="quickfixjContext"> |
| <route> |
| <from uri="quickfix:example"/> |
| <filter> |
| <simple>${in.header.EventCategory} == 'AppMessageReceived'</simple> |
| <to uri="log:test"/> |
| </filter> |
| </route> |
| </camelContext> |
| <!-- quickfix component --> |
| <bean id="quickfix" class="org.apache.camel.component.quickfixj.QuickfixjComponent"> |
| <property name="engineSettings"> |
| <util:map> |
| <entry key="quickfix:example" value-ref="quickfixjSettings"/> |
| </util:map> |
| </property> |
| <property name="messageFactory"> |
| <bean class="org.apache.camel.component.quickfixj.QuickfixjSpringTest.CustomMessageFactory"/> |
| </property> |
| </bean> |
| <!-- quickfix settings --> |
| <bean id="quickfixjSettings" class="org.apache.camel.component.quickfixj.QuickfixjSettingsFactory"> |
| <property name="defaultSettings"> |
| <util:map> |
| <entry key="SocketConnectProtocol" value="VM_PIPE"/> |
| <entry key="SocketAcceptProtocol" value="VM_PIPE"/> |
| <entry key="UseDataDictionary" value="N"/> |
| </util:map> |
| </property> |
| <property name="sessionSettings"> |
| <util:map> |
| <entry key="FIX.4.2:INITIATOR->ACCEPTOR"> |
| <util:map> |
| <entry key="ConnectionType" value="initiator"/> |
| <entry key="SocketConnectHost" value="localhost"/> |
| <entry key="SocketConnectPort" value="5000"/> |
| </util:map> |
| </entry> |
| <entry key="FIX.4.2:ACCEPTOR->INITIATOR"> |
| <util:map> |
| <entry key="ConnectionType" value="acceptor"/> |
| <entry key="SocketAcceptPort" value="5000"/> |
| </util:map> |
| </entry> |
| </util:map> |
| </property> |
| </bean> |
| ---- |
| |
| The QuickFIX/J component includes a `QuickfixjConfiguration` class for |
| configuring the session settings. A type converter for QuickFIX/J |
| session ID strings is also included. The following example shows a |
| simple configuration of an acceptor and initiator session with default |
| settings for both sessions. |
| |
| [source,xml] |
| ---- |
| include::{examplesdir}/components/camel-quickfix/src/test/resources/org/apache/camel/component/quickfixj/QuickfixjSpringTest-context.xml[tags=e1] |
| ---- |
| |
| === Exception handling |
| |
| QuickFIX/J behavior can be modified if certain exceptions are thrown |
| during processing of a message. If a `RejectLogon` exception is thrown |
| while processing an incoming logon administrative message, then the |
| logon will be rejected. |
| |
| Normally, QuickFIX/J handles the logon process automatically. However, |
| sometimes an outgoing logon message must be modified to include |
| credentials required by a FIX counterparty. If the FIX logon message |
| body is modified when sending a logon message |
| (`EventCategory=AdminMessageSent` the modified message will be sent to |
| the counterparty. It is important that the outgoing logon message is |
| being processed __synchronously__. If it is processed asynchronously (on |
| another thread), the FIX engine will immediately send the unmodified |
| outgoing message when its callback method returns. |
| |
| === FIX Sequence Number Management |
| |
| If an application exception is thrown during _synchronous_ exchange |
| processing, this will cause QuickFIX/J to not increment incoming FIX |
| message sequence numbers and will cause a resend of the counterparty |
| message. This FIX protocol behavior is primarily intended to handle |
| _transport_ errors rather than application errors. There are risks |
| associated with using this mechanism to handle application errors. The |
| primary risk is that the message will repeatedly cause application |
| errors each time it's re-received. A better solution is to persist the |
| incoming message (database, JMS queue) immediately before processing it. |
| This also allows the application to process messages asynchronously |
| without losing messages when errors occur. |
| |
| Although it's possible to send messages to a FIX session before it's |
| logged on (the messages will be sent at logon time), it is usually a |
| better practice to wait until the session is logged on. This eliminates |
| the required sequence number resynchronization steps at logon. Waiting |
| for session logon can be done by setting up a route that processes the |
| `SessionLogon` event category and signals the application to start |
| sending messages. |
| |
| See the FIX protocol specifications and the QuickFIX/J documentation for |
| more details about FIX sequence number management. |
| |
| == Examples |
| |
| === Route Examples |
| |
| Several examples are included in the QuickFIX/J component source code |
| (test subdirectories). One of these examples implements a trivial trade |
| execution simulation. The example defines an application component that |
| uses the URI scheme "trade-executor". |
| |
| The following route receives messages for the trade executor session and |
| passes application messages to the trade executor component. |
| |
| [tabs] |
| ==== |
| Java:: |
| + |
| [source,java] |
| ---- |
| from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER"). |
| filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived)). |
| to("trade-executor:market"); |
| ---- |
| |
| YAML:: |
| + |
| [source,yaml] |
| ---- |
| - route: |
| from: |
| uri: quickfix:examples/inprocess.qf.cfg |
| parameters: |
| sessionID: "FIX.4.2:MARKET->TRADER" |
| steps: |
| - filter: |
| expression: |
| simple: |
| expression: "${header.EventCategory} == 'AppMessageReceived'" |
| steps: |
| - to: |
| uri: trade-executor:market |
| ---- |
| ==== |
| |
| The trade executor component generates messages that are routed back to |
| the trade session. The session ID must be set in the FIX message itself |
| since no session ID is specified in the endpoint URI. |
| |
| [tabs] |
| ==== |
| Java:: |
| + |
| [source,java] |
| ---- |
| from("trade-executor:market").to("quickfix:examples/inprocess.qf.cfg"); |
| ---- |
| |
| YAML:: |
| + |
| [source,yaml] |
| ---- |
| - route: |
| from: |
| uri: trade-executor:market |
| steps: |
| - to: |
| uri: quickfix:examples/inprocess.qf.cfg |
| ---- |
| ==== |
| |
| The trader session consumes execution report messages from the market |
| and processes them. |
| |
| [tabs] |
| ==== |
| Java:: |
| + |
| [source,java] |
| ---- |
| from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET"). |
| filter(header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.EXECUTION_REPORT)). |
| bean(new MyTradeExecutionProcessor()); |
| ---- |
| |
| YAML:: |
| + |
| [source,yaml] |
| ---- |
| - route: |
| from: |
| uri: quickfix:examples/inprocess.qf.cfg |
| parameters: |
| sessionID: "FIX.4.2:TRADER->MARKET" |
| steps: |
| - filter: |
| expression: |
| simple: |
| expression: "${header.MessageType} == '8'" |
| steps: |
| - bean: |
| beanType: com.example.MyTradeExecutionProcessor |
| ---- |
| ==== |
| |
| The type of an ExecutionReport is `8`. |
| |
| === Additional Examples |
| |
| The source code contains an example called `RequestReplyExample` that |
| demonstrates the InOut exchanges |
| for a consumer and producer. This example creates a simple HTTP server |
| endpoint that accepts order |
| status requests. The HTTP request is converted to a FIX |
| `OrderStatusRequestMessage`, is augmented with a |
| correlation criteria, and is then routed to a quickfix endpoint. The |
| response is then converted to a |
| JSON-formatted string and sent back to the HTTP server endpoint to be |
| provided as the web response. |