Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<module>minio</module>
<module>mongodb</module>
<module>netty-custom-correlation</module>
<module>quickfixj</module>
<module>resume-api</module>
<module>routeloader</module>
<module>routetemplate</module>
Expand Down
122 changes: 122 additions & 0 deletions quickfixj/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.apache.camel.example</groupId>
<artifactId>camel-examples</artifactId>
<version>4.15.0-SNAPSHOT</version>
</parent>

<artifactId>camel-example-quickfixj</artifactId>
<packaging>jar</packaging>
<name>Camel :: QuickFIX/J</name>
<description>Camel QuickFIX/J support</description>

<properties>
</properties>

<dependencyManagement>
<dependencies>
<!-- Add Camel BOM -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-bom</artifactId>
<version>${camel.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-support</artifactId>
</dependency>
<dependency>
<groupId>org.quickfixj</groupId>
<artifactId>quickfixj-core</artifactId>
<version>${quickfixj-version}</version>
</dependency>
<dependency>
<groupId>org.quickfixj</groupId>
<artifactId>quickfixj-messages-all</artifactId>
<version>${quickfixj-version}</version>
</dependency>

<!-- test dependencies -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test-spring-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jetty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-quickfix</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
<version>${mina-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<version>${hamcrest-version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!--
These tests generate a lot of bogus output and the logging does not work.
This forces the output to be stored in separate files in the target directory.
-->
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<systemPropertyVariables>
<visibleassertions.silence>true</visibleassertions.silence>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.quickfixj;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

import org.mockito.Mockito;
import quickfix.Acceptor;
import quickfix.Application;
import quickfix.ConfigError;
import quickfix.DefaultSessionFactory;
import quickfix.LogFactory;
import quickfix.MessageFactory;
import quickfix.MessageStore;
import quickfix.MessageStoreFactory;
import quickfix.Session;
import quickfix.SessionFactory;
import quickfix.SessionID;
import quickfix.SessionSettings;
import quickfix.field.EmailThreadID;
import quickfix.field.EmailType;
import quickfix.field.Subject;
import quickfix.field.Text;
import quickfix.fix42.Email;

public final class TestSupport {
private TestSupport() {
// Utility class
}

public static void writeSettings(SessionSettings settings, File settingsFile) throws IOException {
FileOutputStream settingsOut = new FileOutputStream(settingsFile);
try {
settings.toStream(settingsOut);
} finally {
settingsOut.close();
}
}

public static void setSessionID(SessionSettings sessionSettings, SessionID sessionID) {
sessionSettings.setString(sessionID, SessionSettings.BEGINSTRING, sessionID.getBeginString());
sessionSettings.setString(sessionID, SessionSettings.SENDERCOMPID, sessionID.getSenderCompID());
sessionSettings.setString(sessionID, SessionSettings.TARGETCOMPID, sessionID.getTargetCompID());
}

public static Email createEmailMessage(String subject) {
Email email = new Email(new EmailThreadID("ID"), new EmailType(EmailType.NEW), new Subject(subject));
Email.LinesOfText text = new Email.LinesOfText();
text.set(new Text("Content"));
email.addGroup(text);
return email;
}

public static Session createSession(SessionID sessionID) throws ConfigError, IOException {
MessageStoreFactory mockMessageStoreFactory = Mockito.mock(MessageStoreFactory.class);
MessageStore mockMessageStore = Mockito.mock(MessageStore.class);
Mockito.when(mockMessageStore.getCreationTime()).thenReturn(new Date());

Mockito.when(mockMessageStoreFactory.create(sessionID)).thenReturn(mockMessageStore);

DefaultSessionFactory factory = new DefaultSessionFactory(
Mockito.mock(Application.class),
mockMessageStoreFactory,
Mockito.mock(LogFactory.class));

SessionSettings settings = new SessionSettings();
settings.setLong(Session.SETTING_HEARTBTINT, 10);
settings.setString(Session.SETTING_START_TIME, "00:00:00");
settings.setString(Session.SETTING_END_TIME, "00:00:00");
settings.setString(SessionFactory.SETTING_CONNECTION_TYPE, SessionFactory.ACCEPTOR_CONNECTION_TYPE);
settings.setBool(Session.SETTING_USE_DATA_DICTIONARY, false);

return factory.create(sessionID, settings);
}

public static QuickfixjEngine createEngine() throws Exception {
return createEngine(false);
}

public static QuickfixjEngine createEngine(boolean lazy) throws Exception {
SessionID sessionID = new SessionID("FIX.4.4:SENDER->TARGET");

MessageStoreFactory mockMessageStoreFactory = Mockito.mock(MessageStoreFactory.class);
MessageStore mockMessageStore = Mockito.mock(MessageStore.class);
Mockito.when(mockMessageStore.getCreationTime()).thenReturn(new Date());
Mockito.when(mockMessageStoreFactory.create(sessionID)).thenReturn(mockMessageStore);

SessionSettings settings = new SessionSettings();

settings.setLong(sessionID, Session.SETTING_HEARTBTINT, 10);
settings.setString(sessionID, Session.SETTING_START_TIME, "00:00:00");
settings.setString(sessionID, Session.SETTING_END_TIME, "00:00:00");
settings.setString(sessionID, SessionFactory.SETTING_CONNECTION_TYPE, SessionFactory.ACCEPTOR_CONNECTION_TYPE);
settings.setLong(sessionID, Acceptor.SETTING_SOCKET_ACCEPT_PORT, 8000);
settings.setBool(sessionID, Session.SETTING_USE_DATA_DICTIONARY, false);

return new QuickfixjEngine(
"", settings,
mockMessageStoreFactory,
Mockito.mock(LogFactory.class),
Mockito.mock(MessageFactory.class), lazy);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.component.quickfixj.examples;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.camel.CamelExchangeException;
import org.apache.camel.Exchange;
import org.apache.camel.builder.PredicateBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
import org.apache.camel.component.quickfixj.QuickfixjEventCategory;
import org.apache.camel.component.quickfixj.examples.util.CountDownLatchDecrementer;
import org.apache.camel.impl.DefaultCamelContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import quickfix.FieldNotFound;
import quickfix.Message;
import quickfix.RejectLogon;
import quickfix.field.MsgType;
import quickfix.field.RawData;
import quickfix.field.RawDataLength;

/**
* This example demonstrates several features of the QuickFIX/J component. It uses QFJ session events to synchronize
* application behavior (e.g., Session logon).
*/
public class AuthenticationExample {
private static final Logger LOG = LoggerFactory.getLogger(AuthenticationExample.class);

public static void main(String[] args) throws Exception {
new AuthenticationExample().run();
}

public void run() throws Exception {
DefaultCamelContext context = new DefaultCamelContext();

final CountDownLatch logoutLatch = new CountDownLatch(1);

RouteBuilder routes = new RouteBuilder() {
@Override
public void configure() {
// Modify the outgoing logon message to add a password
// The modified message will be sent from the FIX engine when the message exchange completes
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET").filter(PredicateBuilder.and(
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AdminMessageSent),
header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.LOGON)))
.bean(new CredentialInjector("PASSWORD"));

// Release latch when the trader received a logout message
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET")
.filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogoff))
.bean(new CountDownLatchDecrementer("logout", logoutLatch));

// Reject all logons on market side
// Demonstrates how to validate logons
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER").filter(PredicateBuilder.and(
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AdminMessageReceived),
header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.LOGON))).bean(new LogonAuthenticator());
}
};

context.addRoutes(routes);

LOG.info("Starting Camel context");
context.start();

if (!logoutLatch.await(5L, TimeUnit.SECONDS)) {
throw new IllegalStateException("Logout was not received");
}

context.stop();

LOG.info("Example complete");
}

public static class LogonAuthenticator {
public void authenticate(Exchange exchange) throws RejectLogon, CamelExchangeException, FieldNotFound {
LOG.info("Acceptor is rejecting logon for {}", exchange.getIn().getHeader(QuickfixjEndpoint.SESSION_ID_KEY));
Message message = exchange.getIn().getMandatoryBody(Message.class);
if (message.isSetField(RawData.FIELD)) {
LOG.info("Invalid password: {}", message.getString(RawData.FIELD));
}
throw new RejectLogon("Rejecting logon for test purposes");
}
}

public static class CredentialInjector {
private final String password;

public CredentialInjector(String password) {
this.password = password;
}

public void inject(Exchange exchange) throws CamelExchangeException {
LOG.info("Injecting password into outgoing logon message");
Message message = exchange.getIn().getMandatoryBody(Message.class);
message.setString(RawData.FIELD, password);
message.setInt(RawDataLength.FIELD, password.length());
}
}
}
Loading