Skip to content

Commit d3e7eb7

Browse files
committed
chore(quickfixj): add examples
They are taken "as is" from core code base [1] since we're cleaning from there. The idea is to maintain these examples as utilities in the examples repo instead. [1] https://github.com/apache/camel/tree/24e3fdbd40e0edd66cb2115f0710bd2e5d1b29db/components/camel-quickfix/src/test/java/org/apache/camel/component/quickfixj/examples
1 parent 307227f commit d3e7eb7

21 files changed

Lines changed: 2156 additions & 0 deletions

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@
122122
<module>minio</module>
123123
<module>mongodb</module>
124124
<module>netty-custom-correlation</module>
125+
<module>quickfixj</module>
125126
<module>resume-api</module>
126127
<module>routeloader</module>
127128
<module>routetemplate</module>

quickfixj/pom.xml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Licensed to the Apache Software Foundation (ASF) under one or more
5+
contributor license agreements. See the NOTICE file distributed with
6+
this work for additional information regarding copyright ownership.
7+
The ASF licenses this file to You under the Apache License, Version 2.0
8+
(the "License"); you may not use this file except in compliance with
9+
the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
21+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
22+
<modelVersion>4.0.0</modelVersion>
23+
24+
<parent>
25+
<groupId>org.apache.camel.example</groupId>
26+
<artifactId>camel-examples</artifactId>
27+
<version>4.15.0-SNAPSHOT</version>
28+
</parent>
29+
30+
<artifactId>camel-example-quickfixj</artifactId>
31+
<packaging>jar</packaging>
32+
<name>Camel :: QuickFIX/J</name>
33+
<description>Camel QuickFIX/J support</description>
34+
35+
<properties>
36+
</properties>
37+
38+
<dependencyManagement>
39+
<dependencies>
40+
<!-- Add Camel BOM -->
41+
<dependency>
42+
<groupId>org.apache.camel</groupId>
43+
<artifactId>camel-bom</artifactId>
44+
<version>${camel.version}</version>
45+
<type>pom</type>
46+
<scope>import</scope>
47+
</dependency>
48+
</dependencies>
49+
</dependencyManagement>
50+
51+
<dependencies>
52+
<dependency>
53+
<groupId>org.apache.camel</groupId>
54+
<artifactId>camel-support</artifactId>
55+
</dependency>
56+
<dependency>
57+
<groupId>org.quickfixj</groupId>
58+
<artifactId>quickfixj-core</artifactId>
59+
<version>${quickfixj-version}</version>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.quickfixj</groupId>
63+
<artifactId>quickfixj-messages-all</artifactId>
64+
<version>${quickfixj-version}</version>
65+
</dependency>
66+
67+
<!-- test dependencies -->
68+
<dependency>
69+
<groupId>org.apache.camel</groupId>
70+
<artifactId>camel-test-spring-junit5</artifactId>
71+
<scope>test</scope>
72+
</dependency>
73+
<dependency>
74+
<groupId>org.apache.camel</groupId>
75+
<artifactId>camel-jetty</artifactId>
76+
<scope>test</scope>
77+
</dependency>
78+
<dependency>
79+
<groupId>org.apache.camel</groupId>
80+
<artifactId>camel-quickfix</artifactId>
81+
<scope>test</scope>
82+
</dependency>
83+
<dependency>
84+
<groupId>org.apache.mina</groupId>
85+
<artifactId>mina-core</artifactId>
86+
<version>${mina-version}</version>
87+
<scope>test</scope>
88+
</dependency>
89+
<dependency>
90+
<groupId>org.mockito</groupId>
91+
<artifactId>mockito-core</artifactId>
92+
<version>${mockito-version}</version>
93+
<scope>test</scope>
94+
</dependency>
95+
<dependency>
96+
<groupId>org.hamcrest</groupId>
97+
<artifactId>hamcrest</artifactId>
98+
<version>${hamcrest-version}</version>
99+
<scope>test</scope>
100+
</dependency>
101+
</dependencies>
102+
103+
<build>
104+
<plugins>
105+
<plugin>
106+
<groupId>org.apache.maven.plugins</groupId>
107+
<artifactId>maven-surefire-plugin</artifactId>
108+
<configuration>
109+
<!--
110+
These tests generate a lot of bogus output and the logging does not work.
111+
This forces the output to be stored in separate files in the target directory.
112+
-->
113+
<redirectTestOutputToFile>true</redirectTestOutputToFile>
114+
<systemPropertyVariables>
115+
<visibleassertions.silence>true</visibleassertions.silence>
116+
</systemPropertyVariables>
117+
</configuration>
118+
</plugin>
119+
</plugins>
120+
</build>
121+
122+
</project>
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.component.quickfixj;
18+
19+
import java.io.File;
20+
import java.io.FileOutputStream;
21+
import java.io.IOException;
22+
import java.util.Date;
23+
24+
import org.mockito.Mockito;
25+
import quickfix.Acceptor;
26+
import quickfix.Application;
27+
import quickfix.ConfigError;
28+
import quickfix.DefaultSessionFactory;
29+
import quickfix.LogFactory;
30+
import quickfix.MessageFactory;
31+
import quickfix.MessageStore;
32+
import quickfix.MessageStoreFactory;
33+
import quickfix.Session;
34+
import quickfix.SessionFactory;
35+
import quickfix.SessionID;
36+
import quickfix.SessionSettings;
37+
import quickfix.field.EmailThreadID;
38+
import quickfix.field.EmailType;
39+
import quickfix.field.Subject;
40+
import quickfix.field.Text;
41+
import quickfix.fix42.Email;
42+
43+
public final class TestSupport {
44+
private TestSupport() {
45+
// Utility class
46+
}
47+
48+
public static void writeSettings(SessionSettings settings, File settingsFile) throws IOException {
49+
FileOutputStream settingsOut = new FileOutputStream(settingsFile);
50+
try {
51+
settings.toStream(settingsOut);
52+
} finally {
53+
settingsOut.close();
54+
}
55+
}
56+
57+
public static void setSessionID(SessionSettings sessionSettings, SessionID sessionID) {
58+
sessionSettings.setString(sessionID, SessionSettings.BEGINSTRING, sessionID.getBeginString());
59+
sessionSettings.setString(sessionID, SessionSettings.SENDERCOMPID, sessionID.getSenderCompID());
60+
sessionSettings.setString(sessionID, SessionSettings.TARGETCOMPID, sessionID.getTargetCompID());
61+
}
62+
63+
public static Email createEmailMessage(String subject) {
64+
Email email = new Email(new EmailThreadID("ID"), new EmailType(EmailType.NEW), new Subject(subject));
65+
Email.LinesOfText text = new Email.LinesOfText();
66+
text.set(new Text("Content"));
67+
email.addGroup(text);
68+
return email;
69+
}
70+
71+
public static Session createSession(SessionID sessionID) throws ConfigError, IOException {
72+
MessageStoreFactory mockMessageStoreFactory = Mockito.mock(MessageStoreFactory.class);
73+
MessageStore mockMessageStore = Mockito.mock(MessageStore.class);
74+
Mockito.when(mockMessageStore.getCreationTime()).thenReturn(new Date());
75+
76+
Mockito.when(mockMessageStoreFactory.create(sessionID)).thenReturn(mockMessageStore);
77+
78+
DefaultSessionFactory factory = new DefaultSessionFactory(
79+
Mockito.mock(Application.class),
80+
mockMessageStoreFactory,
81+
Mockito.mock(LogFactory.class));
82+
83+
SessionSettings settings = new SessionSettings();
84+
settings.setLong(Session.SETTING_HEARTBTINT, 10);
85+
settings.setString(Session.SETTING_START_TIME, "00:00:00");
86+
settings.setString(Session.SETTING_END_TIME, "00:00:00");
87+
settings.setString(SessionFactory.SETTING_CONNECTION_TYPE, SessionFactory.ACCEPTOR_CONNECTION_TYPE);
88+
settings.setBool(Session.SETTING_USE_DATA_DICTIONARY, false);
89+
90+
return factory.create(sessionID, settings);
91+
}
92+
93+
public static QuickfixjEngine createEngine() throws Exception {
94+
return createEngine(false);
95+
}
96+
97+
public static QuickfixjEngine createEngine(boolean lazy) throws Exception {
98+
SessionID sessionID = new SessionID("FIX.4.4:SENDER->TARGET");
99+
100+
MessageStoreFactory mockMessageStoreFactory = Mockito.mock(MessageStoreFactory.class);
101+
MessageStore mockMessageStore = Mockito.mock(MessageStore.class);
102+
Mockito.when(mockMessageStore.getCreationTime()).thenReturn(new Date());
103+
Mockito.when(mockMessageStoreFactory.create(sessionID)).thenReturn(mockMessageStore);
104+
105+
SessionSettings settings = new SessionSettings();
106+
107+
settings.setLong(sessionID, Session.SETTING_HEARTBTINT, 10);
108+
settings.setString(sessionID, Session.SETTING_START_TIME, "00:00:00");
109+
settings.setString(sessionID, Session.SETTING_END_TIME, "00:00:00");
110+
settings.setString(sessionID, SessionFactory.SETTING_CONNECTION_TYPE, SessionFactory.ACCEPTOR_CONNECTION_TYPE);
111+
settings.setLong(sessionID, Acceptor.SETTING_SOCKET_ACCEPT_PORT, 8000);
112+
settings.setBool(sessionID, Session.SETTING_USE_DATA_DICTIONARY, false);
113+
114+
return new QuickfixjEngine(
115+
"", settings,
116+
mockMessageStoreFactory,
117+
Mockito.mock(LogFactory.class),
118+
Mockito.mock(MessageFactory.class), lazy);
119+
}
120+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.component.quickfixj.examples;
18+
19+
import java.util.concurrent.CountDownLatch;
20+
import java.util.concurrent.TimeUnit;
21+
22+
import org.apache.camel.CamelExchangeException;
23+
import org.apache.camel.Exchange;
24+
import org.apache.camel.builder.PredicateBuilder;
25+
import org.apache.camel.builder.RouteBuilder;
26+
import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
27+
import org.apache.camel.component.quickfixj.QuickfixjEventCategory;
28+
import org.apache.camel.component.quickfixj.examples.util.CountDownLatchDecrementer;
29+
import org.apache.camel.impl.DefaultCamelContext;
30+
import org.slf4j.Logger;
31+
import org.slf4j.LoggerFactory;
32+
import quickfix.FieldNotFound;
33+
import quickfix.Message;
34+
import quickfix.RejectLogon;
35+
import quickfix.field.MsgType;
36+
import quickfix.field.RawData;
37+
import quickfix.field.RawDataLength;
38+
39+
/**
40+
* This example demonstrates several features of the QuickFIX/J component. It uses QFJ session events to synchronize
41+
* application behavior (e.g., Session logon).
42+
*/
43+
public class AuthenticationExample {
44+
private static final Logger LOG = LoggerFactory.getLogger(AuthenticationExample.class);
45+
46+
public static void main(String[] args) throws Exception {
47+
new AuthenticationExample().run();
48+
}
49+
50+
public void run() throws Exception {
51+
DefaultCamelContext context = new DefaultCamelContext();
52+
53+
final CountDownLatch logoutLatch = new CountDownLatch(1);
54+
55+
RouteBuilder routes = new RouteBuilder() {
56+
@Override
57+
public void configure() {
58+
// Modify the outgoing logon message to add a password
59+
// The modified message will be sent from the FIX engine when the message exchange completes
60+
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET").filter(PredicateBuilder.and(
61+
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AdminMessageSent),
62+
header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.LOGON)))
63+
.bean(new CredentialInjector("PASSWORD"));
64+
65+
// Release latch when the trader received a logout message
66+
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET")
67+
.filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogoff))
68+
.bean(new CountDownLatchDecrementer("logout", logoutLatch));
69+
70+
// Reject all logons on market side
71+
// Demonstrates how to validate logons
72+
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER").filter(PredicateBuilder.and(
73+
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AdminMessageReceived),
74+
header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.LOGON))).bean(new LogonAuthenticator());
75+
}
76+
};
77+
78+
context.addRoutes(routes);
79+
80+
LOG.info("Starting Camel context");
81+
context.start();
82+
83+
if (!logoutLatch.await(5L, TimeUnit.SECONDS)) {
84+
throw new IllegalStateException("Logout was not received");
85+
}
86+
87+
context.stop();
88+
89+
LOG.info("Example complete");
90+
}
91+
92+
public static class LogonAuthenticator {
93+
public void authenticate(Exchange exchange) throws RejectLogon, CamelExchangeException, FieldNotFound {
94+
LOG.info("Acceptor is rejecting logon for {}", exchange.getIn().getHeader(QuickfixjEndpoint.SESSION_ID_KEY));
95+
Message message = exchange.getIn().getMandatoryBody(Message.class);
96+
if (message.isSetField(RawData.FIELD)) {
97+
LOG.info("Invalid password: {}", message.getString(RawData.FIELD));
98+
}
99+
throw new RejectLogon("Rejecting logon for test purposes");
100+
}
101+
}
102+
103+
public static class CredentialInjector {
104+
private final String password;
105+
106+
public CredentialInjector(String password) {
107+
this.password = password;
108+
}
109+
110+
public void inject(Exchange exchange) throws CamelExchangeException {
111+
LOG.info("Injecting password into outgoing logon message");
112+
Message message = exchange.getIn().getMandatoryBody(Message.class);
113+
message.setString(RawData.FIELD, password);
114+
message.setInt(RawDataLength.FIELD, password.length());
115+
}
116+
}
117+
}

0 commit comments

Comments
 (0)