A file system is used to log messages for FIX Antenna recovery.
Log files are created in the directory specified in the configurations parameters (the "storageDirectory" property).
Files with the *.properties extension (properties files) contain basic session information.
Incoming messages are stored to files with the .in extension.
Outgoing messages are stored to files with the .out extension.
Files related to the same session have the same basic part of name (the one before a point).
The fixaj.log file storing information about FE operation is also created in the log directory.
Log files are used during an automatic session reestablishment. Thus, to ensure a "clean" run of FIX Antenna, it is necessary to remove all the files from the log directory (the "storageDirectory" property).
Yes, it is possible to create many instances of FIX Antenna Java as soon as they use different listening ports. FIX Server instances are pretty lightweight, so there is no limit on the number of servers but rather on the number of simultaneous sessions.
Yes. However it is recommended to set different logging files. Otherwise different instances will put logging data to the same file and it will be difficult to distinguish records made by different instances.
Yes. FIX Antenna Java loads all session information at session creation time.
It is enough just to clean the logging directory before creating a new instance of FIX Antenna Java.
User Defined Fields (the tag numbers 5000 to 9999) are handled like ordinary fields.
Example: 8=FIX.4.3 | 9=285 | 35=X | 49=FIXERBRIDGETRD1 | 34=1 | 57=B2BTEST1 | 52=99990909-17:17:17 | 268=4 | 269=2 | 270=9539.500000 | 271=1 | 272=20041208 | 273=13:34:10.000 | 290=1 | 269=4 | 27 0 =9539.500000 | 271=4294967295 | 272=20041208 | 273=13:34:10.000 | 290=1 | 269=Z | 270=9528.000000 | 271=401 | 290=1 | 269=Y | 270=0.000000 | 271=0 | 290=1 | 10=019 | [ERROR] Repeating group fields out of order [RefSeqNum: 1, RefTagID: 269, RefMsgType: X]
Solution: The reason of this problem cannot be detected easily. The required fields of both FIX message itself and the group (AdditionalFields) must be filled out with corresponding values and any gap or change in the tag order leads to the error (it is true for both standard and custom messages). Therefore, both standard and additional group fields must be checked for validity and then processed again. Extra attention must be paid to the order of fields in the repeating FIX group. For this particular example: The tag 290 is placed before the tag 269 (wrong tag order). To solve the problem: place the tag 290 and its value after the tag 269 and process the message again.
The FIX session has 2 parameters for FIX version control: FixVersion and AppVersion. FixVersion resents data, which will be put to BeginString(8) tag of each message. AppVersion is used only if FixVersion contains a marker for FIX Session Protocol FIXT11). In this case the AppVersion parameter will contain the ApplVerID(1128) tag value. If you want to create a FIX 5.0 session, add the following strings to your code:
SessionParameters details = new SessionParameters();
details.setFixVersion(FIXVersion.FIXT11);
details.setAppVersion(FIXVersion.FIX50);
Unfortunately, FIXAJ does not have this function so far. But we plan to include it in future releases. Anyway you can implement it in your code:
class MyServerListener implements FIXServerListener { @Override public void newFIXSession(FIXSession session) { try { //... SessionParameters sessionParameters = session.getSessionParameters(); sessionParameters.setOutgoingSequenceNumber(1); //reset outgoint sequnce number to 1 sessionParameters.setIncomingSequenceNumber(1); //reset outgoint sequnce number to 1 //send this flag to other side to notificate tat thay should reset sequence too. sessionParameters.addOutgoingLoginField(new FIXField(FIXT11.Logon.ResetSeqNumFlag, "Y")); //... session.connect(); } catch (IOException e) { e.printStackTrace(); } } }
To send login/password via Logon message, use SessionParameters.addOutgoingLoginField to set additional tags before session connect:
details.addOutgoingLoginField(new FIXField(FIXT11.Logon.Username, "user")); details.addOutgoingLoginField(new FIXField(FIXT11.Logon.Password, "pass"));
To verify login/password on server side:
@Override public void newFIXSession(FIXSession session) { SessionParameters parameters = session.getSessionParameters(); //get username(553) and password(554) tags from incomming login String username = parameters.getIncomingLoginFixFieldList().getTagStringValue(FIXT11.Logon.Username); String password = parameters.getIncomingLoginFixFieldList().getTagStringValue(FIXT11.Logon.Password); //check that this user has access to the system if (!isAuthorized(username, password)) { // terminate session session.dispose(); } else { try { //accept this session session.setFIXSessionListener(new MyFIXSessionListener(session)); session.connect(); } catch (IOException e) { e.printStackTrace(); } } }
FIX specification allows shutting down the connection without sending Logout here: "If authentication fails, the session acceptor should shut down the connection after optionally sending a Logout message to indicate the reason of failure. Sending Logout in this case is not required because doing so would consume a sequence number for that session, which in some cases may be problematic."
But if a Logout message is required in your environment, you need to write a custom handler with authorization for Logon messages. It is possible to send a Logout message without Logon from the handler.
Java Antenna receives all required information about FIX version from FIX dictionaries. They contain meta-data in the XML format, which helps FIX Anttenna validate messages. Dictionaries for standard FIX versions (from fixprotocol.org) can be found in lib/fixprotocol-fix-X.Y.Z.jar. You can easily customize any standard dictionary from lib/fixprotocol-fix-X.Y.Z.jar or send your requirements for customization to sales@btobits.com and we will prepare a custom dictionary for you.
There are several ways to customize FIX Antenna behaviour:
SessionParameters details = new SessionParameters(); //replace standard FIX 4.4 dictionary with custom for concrete session //if you want to load dictionary from classpath use "classpath:custom/fixdic44.xml" FIXVersionContainer fixVersion = new FIXVersionContainer("CustomFIX44", FIXVersion.FIX44, "custom/fixdic44.xml"); details.setFixVersion(fixVersion); ... final FIXSession session = details.createNewFIXSession();
//replace standard FIX 4.4 dictionary with custom ValidationEngine.preloadDictionary(FIXVersion.FIX44, "custom/fixdic44.xml", true);
FIXVersionContainer fix44Version = FIXVersionContainer.getFIXVersionContainer(FIXVersion.FIX44); FIXVersionContainer customFix44Version = new FIXVersionContainer("CustomFIX44", fix44Version, "classpath:additional44.xml"); details.setFixVersion(customFix44Version);
validation.FIX44.additionalDictionaryFileName=custom/additional44.xml
FIX Antenna provided generation tool for customization (since v 2.4.12). Please see documentation in the generate-tools directory of your installation.
Yes. Several other fields (body length, sequence number, sending time, checksum) will also be updated.
This error means that you have some problem with a license file. Possible cases:
Make sure that the license file (fixaj2-license.bin) can be accessed by FIX Engine. Typicaly engine searches for license in such a way:
If the license is located in the right place, send logs and the license file to sales@btobits.com. May be you license has become invalid or corrupted.
Make sure that this port is not in use by some other application. Try
netstat -a
to get the list of used ports.
In order to create an SSL enabled FIX server instead of
FIXServer server = new FIXServer(); // create server that will listen for TCP/IP connections server.setPort(777); // setting port it will listen to server.setListener(new SimpleServer()); // setting listener for new connections server.start(); // this will start new thread and listen for incoming connections
simply use
FIXServer server = new SSLFIXServer(); // create server that will listen for TCP/IP connections server.setPort(778); // setting port it will listen to, make sure it is different from regular FIXServer or if it the same that FIXServer isn't running server.setListener(new SimpleServer()); // setting listener for new connections server.start(); // this will start new thread and listen for incoming connections
To enable SSL support for initiator sessions set the configurations parameter
enableSSL=true
It could be set either per session
SessionParameters.getConfiguration().setProperty("enableSSL", "true");
or globally for all sessions. Use the fixengine.properties file.
FIXEngine requires additional JVM parameters to initiaize a proper keystore
-Djavax.net.ssl.trustStore=/path/to/keystore -Djavax.net.ssl.trustStorePassword=YOUR_PASSWORD
Key and Certificate Management
Keytool utility can be used to perform key and certificate management. This utility is a part of a standard JDK package.
Please refer to: http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html and http://java.sun.com/javase/6/docs/technotes/tools/windows/keytool.html for additional information.
You can create a keystore with a self-signed certificate for testing purposes using the keytool command:
%JAVA_HOME%/bin/keytool -keystore mySrvKeystore -keypasswd 123456 -genkey -keyalg RSA -alias mycert
Encritpion configuration:
Key management:
To enable encryption for FIX messages mechanism it needs to configure your Java Runtime Environment, as described below, and allows the usage of external Cryptix encryption provider.
Configuration of JRE:
# # List of providers and their preference orders (see above): # # security.provider.1=sun.security.provider.Sun security.provider.2=sun.security.rsa.SunRsaSign security.provider.3=com.sun.net.ssl.internal.ssl.Provider security.provider.4=com.sun.crypto.provider.SunJCE security.provider.5=cryptix.jce.provider.CryptixCrypto security.provider.6=cryptix.openpgp.provider.CryptixOpenPGP security.provider.7=sun.security.jgss.SunProvider security.provider.8=com.sun.security.sasl.Provider
encryptionConfig=${fixaj.home}/encryption/encryption.cfg
desKey.[TargetCompId]=12345678
encryptionConfig=${fixaj.home}/encryption/encryption.cfg
pubKeyFile=${fixaj.home}/encryption/pubring.keystore secKeyFile=${fixaj.home}/encryption/secring.keystore
pgpKey.[SenderCompID]=123456
The encrypted session may be created in this way:
SessionParameters details = new SessionParameters(); details.setFixVersion(FIXVersion.FIX44); details.setHost("localhost"); details.setHeartbeatInterval(30); details.setPort(3000); details.setSenderCompId("senderId"); details.setTargetCompId("targetId"); details.setEncryptionType(EncryptionType.Des); final FIXSession session = details.createNewFIXSession(); ... session.connect();
But, FIXAJ ofcourse supports pre-configured encryption for all fix sessions:
encryptionMode=Des
The PGP Tool hides intenal PGP implementation and provides a set of simple functions to make PGP use in user applications easy. It could perform several groups of tasks. 1) Generate both public and private (secret) keys and add them to keyring file 2) Import ASCII armoured key to the keyring file. 3) Export key ASCII armoured. 4) List keys in keyring file.
pubring=./pubring.pgp secring=./secring.pgp
Enter ID for PGP JAVA_PRIVATE pair generation: SenderCompID
Select JAVA_PRIVATE length. Enter '1' to choose JAVA_PRIVATE length 2048 bytes '2' to choose JAVA_PRIVATE length 1024 bytes '3' to choose JAVA_PRIVATE length 512 bytes
Enter PassPhrase for PGP JAVA_PRIVATE pair generation (more than 6 characters)**********
Do you want to generate another pair? (Y/N)):N
Enter User ID for export:senderId
Export JAVA_PRIVATE(s) to file: senderId_public.asc
CME secure logon provides an ability to logon using SHA256 digital signature technique. This logon feature has been introduced by CME and provides highest security.
It needs to obtain security keys file from CME in order to use it. Once it is available, FIX Antenna can be configured to use secure logon for connecting to CME.
The session that connects using CME secure feature may be created in the code:
SessionParameters details = new SessionParameters(); details.setFixVersion(FIXVersion.FIX42); details.setHost("localhost"); details.setHeartbeatInterval(30); details.setPort(3000); details.setSenderCompId("senderId"); details.setTargetCompId("targetId"); details.setSenderSubId("senderSubId"); details.setTargetSubId("targetSubId"); details.setSenderLocationId("senderLocationId"); //the following three parameters are required for the feature. details.getConfiguration().setProperty(Configuration.INCLUDE_LAST_PROCESSED, "YES"); details.getConfiguration().setProperty(Configuration.CME_SECURE_KEYS_FILE, "cmeKeys.txt"); //Defines name of keys file. It should be located in classpath, root directory of running java application or home directory. details.getConfiguration().setProperty(Configuration.LOGON_CUSTOMIZATION_STRATEGY, Configuration.CME_SECURE_LOGON_STRATEGY); final FIXSession session = details.createNewFIXSession(); ... session.connect();
It can also be created using properties:
sessionIDs=client1 sessions.default.host=69.50.112.139 sessions.default.port=24920 sessions.default.fixVersion=FIX.4.2 sessions.default.heartbeatInterval=30 sessions.default.validation=false sessions.default.storageFactory=com.epam.fixengine.storage.InMemoryStorageFactory sessions.default.cmeSecureKeysFile=cmeKeys.txt sessions.default.logonCustomizationStrategy=com.epam.fixengine.session.impl.CmeSecureLogonStrategy sessions.default.includeLastProcessed=true sessions.client1.senderCompID=U89004N sessions.client1.targetCompID=CME sessions.client1.targetSubID=G sessions.client1.senderSubID=0J4L sessions.client1.senderLocationID=US
and applied using the following code:
SessionParameters details = SessionParametersBuilder.buildSessionParameters("initiators.properties", "client1"); // create session we intend to work with final FIXSession session = details.createInitiatorSession(); ... session.connect();
Note: tags SenderSubID, TargetSubID, SenderLocationID are required for the feature.