11package qfjtutorial .begin ;
22
3- import java .util .Iterator ;
4- import java .util .concurrent .CountDownLatch ;
53import java .util .concurrent .TimeUnit ;
64
7- import org .slf4j .Logger ;
8- import org .slf4j .LoggerFactory ;
9-
10- import qfjtutorial .common .DefaultMessageCallback ;
11- import qfjtutorial .common .DefaultSessionStateListener ;
125import quickfix .Application ;
136import quickfix .DefaultMessageFactory ;
7+ import quickfix .FileLogFactory ;
148import quickfix .FileStoreFactory ;
159import quickfix .LogFactory ;
1610import quickfix .Message ;
11+ import quickfix .MessageFactory ;
1712import quickfix .MessageStoreFactory ;
18- import quickfix .SLF4JLogFactory ;
1913import quickfix .Session ;
20- import quickfix .SessionID ;
21- import quickfix .SessionNotFound ;
2214import quickfix .SessionSettings ;
2315import quickfix .SocketInitiator ;
2416
25- //the session has been setup at both client and server side, in related configuration files
26- //You could setup your own log4j2 file, e.g.-Dlog4j.configurationFile=qfjtutorial/ common/ConsoleOnly.log4j2.xml
17+ //This is a simplified version.
18+ //For production code, please read common.DefaultQFJSingleSessionInitiator.
2719public class FirstQFJClient {
2820
29- protected final static Logger log = LoggerFactory .getLogger (FirstQFJClient .class );
30-
31- private final String _appConfigInClasspath ;
32- private final SessionSettings _settings ;
33- private final MessageStoreFactory _storeFactory ;
34- private final LogFactory _logFactory ;
35- private final Application _msgCallback ;
36-
37- // Each configuration file could include multi session. In this example,
38- // only single session.
39- private final SessionID _sessionID ;
40-
41- private final SocketInitiator _initiator ;
42-
43- private final CountDownLatch _latchForLogonResponse ;
44-
45- public FirstQFJClient (String appConfigInClasspath , Application msgCallback ) throws Exception {
46-
47- _appConfigInClasspath = appConfigInClasspath ;
48- log .info ("qfj client begin initializing, with app configuration file in classpath:{}" , appConfigInClasspath );
49-
50- _msgCallback = msgCallback ;
51-
52- _settings = new SessionSettings (appConfigInClasspath );
53- log .info ("_settings.size(): {}" , _settings .size ());
54- if (_settings .size () != 1 ) {
55- String errorInfo = "For this simple app, expect 1 session definition in settings, but found "
56- + _settings .size ();
57- log .error (errorInfo );
58- throw new RuntimeException (errorInfo );
59- }
60- SessionID sessionID = null ;
61- for (final Iterator <SessionID > i = _settings .sectionIterator (); i .hasNext ();) {
62- sessionID = i .next ();
63- log .info ("session in the configuration : " + sessionID .toString ());
64- }
65- _sessionID = sessionID ;
66-
67- // Other store factory, e.g. quickfix.JdbcStoreFactory,
68- // quickfix.MemoryStoreFactory, quickfix.SleepycatStoreFactory. See QFJ
69- // Advanced.
70- _storeFactory = new FileStoreFactory (_settings );
71-
72- // Other log factory are supported, too , e.g.quickfix.ScreenLogFactory,
73- // quickfix.JdbcLogFactory, quickfix.CompositeLogFactory,
74- // quickfix.SLF4JLogFactory. See QFJ-Advanced.
75- // quickfix.FileLogFactory
76- _logFactory = new SLF4JLogFactory (_settings );
77-
78- // This is single thread. For multi-thread, see
79- // quickfix.ThreadedSocketInitiator, and QFJ-Advanced.
80- _initiator = new SocketInitiator (_msgCallback , _storeFactory , _settings , _logFactory ,
81- new DefaultMessageFactory ());
82-
83- _latchForLogonResponse = new CountDownLatch (1 );
21+ public static void main (String [] args ) throws Exception {
8422
85- log . info ( "qfj client initialized, with app configuration file in classpath:{}" , appConfigInClasspath ) ;
23+ String configurationFileInClasspath = "qfjtutorial/begin/FirstQFJClient.qfj.config.txt" ;
8624
87- }
25+ Application application = new FirstMessageCallback ();
8826
89- // start is NOT put in constructor deliberately, to let it pair with
90- // shutdown
91- public void start () throws Exception {
92-
93- log .info ("qfj client start, {}" , _appConfigInClasspath );
94-
95- _initiator .start ();
96-
97- //session is created during Connector.start();
98- Session session = Session .lookupSession (_sessionID );
99- session .addStateListener (new DefaultSessionStateListener (_sessionID ){
100- @ Override
101- public void onLogon () {
102- log .debug ("InternalSessionStateListener onLogon session:{}" , _sessionID .toString ());
103- _latchForLogonResponse .countDown ();
104- }
105- });
106- _latchForLogonResponse .await ();
107-
108- log .info ("qfj client started, {}" , _appConfigInClasspath );
109- }
27+ SessionSettings settings = new SessionSettings (configurationFileInClasspath );
28+ MessageStoreFactory storeFactory = new FileStoreFactory (settings );
29+ LogFactory logFactory = new FileLogFactory (settings );
30+ MessageFactory messageFactory = new DefaultMessageFactory ();
11031
111- public void stop () throws Exception {
32+ SocketInitiator initiator = new SocketInitiator (application , storeFactory , settings , logFactory ,
33+ messageFactory );
11234
113- log . info ( "qfj client stop, {}" , _appConfigInClasspath );
35+ initiator . start ( );
11436
115- _initiator .stop ();
37+ // after start, you have to wait several seconds before sending
38+ // messages.
39+ // in production code, you should check the response Logon message.
40+ // Refer: DefaultQFJSingSessionInitiator.java
41+ TimeUnit .SECONDS .sleep (3 );
11642
117- log . info ( "qfj client stopped, {}" , _appConfigInClasspath );
118- }
43+ Session . sendToTarget ( buildHarcodedNewOrderSingleForTest () );
44+ Session . sendToTarget ( buildHarcodedNewOrderSingleForTest ());
11945
120- // the 49 and 56 value of the message will be used to identify the FIX
121- // session
122- // if you don't know what's the tag 49 and 56, please read FIX session
123- // specification.
124- public void send (Message message ) throws SessionNotFound {
125- quickfix .Session .sendToTarget (message , _sessionID );
46+ TimeUnit .SECONDS .sleep (3 );
47+ initiator .stop ();
12648 }
12749
12850 private static Message buildHarcodedNewOrderSingleForTest () {
@@ -137,6 +59,12 @@ private static Message buildHarcodedNewOrderSingleForTest() {
13759 */
13860 // NewOrderSingle
13961 Message newOrderSingle = new Message ();
62+ // It is not required to set 8,49,56 if you know SessionID. See
63+ // DefaultSQFSingleSessionInitiator.java
64+ newOrderSingle .getHeader ().setString (8 , "FIXT.1.1" );
65+ newOrderSingle .getHeader ().setString (49 , "abcClientCompID" );
66+ newOrderSingle .getHeader ().setString (56 , "xyzServerCompID" );
67+
14068 newOrderSingle .getHeader ().setString (35 , "D" );
14169 newOrderSingle .setString (11 , "ClOrdID_" + System .currentTimeMillis ());
14270 newOrderSingle .setString (55 , "USDJPY" ); // non-repeating group
@@ -152,22 +80,4 @@ private static Message buildHarcodedNewOrderSingleForTest() {
15280
15381 }
15482
155- public static void main (String [] args ) throws Exception {
156-
157- Application msgCallback = new DefaultMessageCallback ();
158- String configurationFileInClasspath = "qfjtutorial/begin/FirstQFJClient.qfj.config.txt" ;
159- FirstQFJClient client = new FirstQFJClient (configurationFileInClasspath , msgCallback );
160- client .start ();
161-
162- TimeUnit .SECONDS .sleep (3 );
163-
164- for (int i = 0 ; i < 3 ; i ++) {
165-
166- Message newOrderSingle = buildHarcodedNewOrderSingleForTest ();
167- client .send (newOrderSingle );
168-
169- //TimeUnit.SECONDS.sleep(1);
170- TimeUnit .MILLISECONDS .sleep (10 );
171- }
172- }
17383}
0 commit comments