This is an automated email from the ASF dual-hosted git repository.

pcongiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-examples.git


The following commit(s) were added to refs/heads/main by this push:
     new d3e7eb7e chore(quickfixj): add examples
d3e7eb7e is described below

commit d3e7eb7eb19c0aa62bd7fc7e12c20bdd11fd55a5
Author: Pasquale Congiusti <[email protected]>
AuthorDate: Thu Oct 9 10:42:27 2025 +0200

    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
---
 pom.xml                                            |   1 +
 quickfixj/pom.xml                                  | 122 ++++++
 .../camel/component/quickfixj/TestSupport.java     | 120 ++++++
 .../quickfixj/examples/AuthenticationExample.java  | 117 ++++++
 .../quickfixj/examples/DynamicRoutingExample.java  | 117 ++++++
 .../quickfixj/examples/RequestReplyExample.java    | 178 ++++++++
 .../quickfixj/examples/RestartRouteExample.java    | 104 +++++
 .../quickfixj/examples/SimpleMessagingExample.java | 104 +++++
 .../examples/routing/FixMessageRouter.java         | 107 +++++
 .../examples/trading/MarketQuoteProvider.java      |  27 ++
 .../examples/trading/QuickfixjMessageListener.java |  24 ++
 .../quickfixj/examples/trading/TradeExecutor.java  | 457 +++++++++++++++++++++
 .../examples/trading/TradeExecutorComponent.java   | 167 ++++++++
 .../examples/trading/TradeExecutorExample.java     | 136 ++++++
 .../transform/QuickfixjEventJsonTransformer.java   |  54 +++
 .../transform/QuickfixjMessageJsonPrinter.java     |  36 ++
 .../transform/QuickfixjMessageJsonTransformer.java | 110 +++++
 .../examples/util/CountDownLatchDecrementer.java   |  42 ++
 .../src/test/resources/examples/gateway.qf.cfg     |  59 +++
 .../src/test/resources/examples/inprocess.qf.cfg   |  46 +++
 quickfixj/src/test/resources/log4j2.properties     |  28 ++
 21 files changed, 2156 insertions(+)

diff --git a/pom.xml b/pom.xml
index 51e1ecda..7f7416fb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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>
diff --git a/quickfixj/pom.xml b/quickfixj/pom.xml
new file mode 100644
index 00000000..cec2e21c
--- /dev/null
+++ b/quickfixj/pom.xml
@@ -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>
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/TestSupport.java 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/TestSupport.java
new file mode 100644
index 00000000..fd56a4e1
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/TestSupport.java
@@ -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);
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/AuthenticationExample.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/AuthenticationExample.java
new file mode 100644
index 00000000..80300c47
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/AuthenticationExample.java
@@ -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());
+        }
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/DynamicRoutingExample.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/DynamicRoutingExample.java
new file mode 100644
index 00000000..2a3e72ee
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/DynamicRoutingExample.java
@@ -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.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Producer;
+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.TestSupport;
+import org.apache.camel.component.quickfixj.examples.routing.FixMessageRouter;
+import 
org.apache.camel.component.quickfixj.examples.transform.QuickfixjMessageJsonPrinter;
+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.field.DeliverToCompID;
+import quickfix.field.MsgType;
+import quickfix.fix42.Email;
+
+public class DynamicRoutingExample {
+    private static final Logger LOG = 
LoggerFactory.getLogger(DynamicRoutingExample.class);
+
+    public static void main(String[] args) throws Exception {
+        new DynamicRoutingExample().sendMessage();
+    }
+
+    public void sendMessage() throws Exception {
+        DefaultCamelContext context = new DefaultCamelContext();
+
+        final CountDownLatch logonLatch = new CountDownLatch(4);
+        final CountDownLatch receivedMessageLatch = new CountDownLatch(1);
+
+        RouteBuilder routes = new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Release latch when session logon events are received
+                // We expect four logon events (four sessions)
+                from("quickfix:examples/gateway.qf.cfg")
+                        
.filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogon))
+                        .bean(new CountDownLatchDecrementer("logon", 
logonLatch));
+
+                // Dynamic router -- Uses FIX DeliverTo tags
+                from("quickfix:examples/gateway.qf.cfg")
+                        .filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY)
+                                
.isEqualTo(QuickfixjEventCategory.AppMessageReceived))
+                        .recipientList(method(new 
FixMessageRouter("quickfix:examples/gateway.qf.cfg")));
+
+                // Logger app messages as JSON
+                
from("quickfix:examples/gateway.qf.cfg").filter(PredicateBuilder.or(
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived),
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageSent)))
+                        .bean(new QuickfixjMessageJsonPrinter());
+
+                // If the trader@2 session receives an email then release the 
latch
+                
from("quickfix:examples/gateway.qf.cfg?sessionID=FIX.4.2:TRADER@2->GATEWAY").filter(PredicateBuilder.and(
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived),
+                        
header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.EMAIL)))
+                        .bean(new CountDownLatchDecrementer("message", 
receivedMessageLatch));
+            }
+        };
+
+        context.addRoutes(routes);
+
+        LOG.info("Starting Camel context");
+        context.start();
+
+        // This is not strictly necessary, but it prevents the need for session
+        // synchronization due to app messages being sent before being logged 
on
+        if (!logonLatch.await(5, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Logon did not complete");
+        }
+
+        String gatewayUri = 
"quickfix:examples/gateway.qf.cfg?sessionID=FIX.4.2:TRADER@1->GATEWAY";
+        Endpoint gatewayEndpoint = context.getEndpoint(gatewayUri);
+        Producer producer = gatewayEndpoint.createProducer();
+
+        Email email = TestSupport.createEmailMessage("Dynamic Routing 
Example");
+        email.getHeader().setString(DeliverToCompID.FIELD, "TRADER@2");
+
+        LOG.info("Sending routed message");
+
+        Exchange exchange = 
producer.getEndpoint().createExchange(ExchangePattern.InOnly);
+        exchange.getIn().setBody(email);
+        producer.process(exchange);
+
+        if (!receivedMessageLatch.await(5, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Message did not reach target");
+        }
+
+        LOG.info("Message received, shutting down Camel context");
+
+        context.stop();
+
+        LOG.info("Dynamic routing example complete");
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/RequestReplyExample.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/RequestReplyExample.java
new file mode 100644
index 00000000..95239c65
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/RequestReplyExample.java
@@ -0,0 +1,178 @@
+/*
+ * 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.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.Header;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.quickfixj.MessagePredicate;
+import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
+import org.apache.camel.component.quickfixj.QuickfixjEventCategory;
+import org.apache.camel.component.quickfixj.QuickfixjProducer;
+import 
org.apache.camel.component.quickfixj.examples.transform.QuickfixjMessageJsonPrinter;
+import 
org.apache.camel.component.quickfixj.examples.transform.QuickfixjMessageJsonTransformer;
+import 
org.apache.camel.component.quickfixj.examples.util.CountDownLatchDecrementer;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.util.IOHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import quickfix.FieldNotFound;
+import quickfix.SessionID;
+import quickfix.field.AvgPx;
+import quickfix.field.ClOrdID;
+import quickfix.field.CumQty;
+import quickfix.field.ExecID;
+import quickfix.field.ExecTransType;
+import quickfix.field.ExecType;
+import quickfix.field.LeavesQty;
+import quickfix.field.MsgType;
+import quickfix.field.OrdStatus;
+import quickfix.field.OrderID;
+import quickfix.field.Side;
+import quickfix.field.Symbol;
+import quickfix.fix42.ExecutionReport;
+import quickfix.fix42.OrderStatusRequest;
+
+public class RequestReplyExample {
+    private static final Logger LOG = 
LoggerFactory.getLogger(RequestReplyExample.class);
+
+    public static void main(String[] args) throws Exception {
+        new RequestReplyExample().run();
+    }
+
+    public void run() throws Exception {
+        final CamelContext context = new DefaultCamelContext();
+        final CountDownLatch logonLatch = new CountDownLatch(1);
+        final String orderStatusServiceUrl = 
"http://localhost:9123/order/status";;
+
+        RouteBuilder routes = new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Synchronize the logon so we don't start sending status 
requests too early
+                
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET")
+                        
.filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogon))
+                        .bean(new CountDownLatchDecrementer("logon", 
logonLatch));
+
+                // Incoming status requests are passed to the order status 
service and afterwards we print out that
+                // order status being delivered using the json printer.
+                
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))
+                        
.to("log://OrderStatusRequestLog?showAll=true&multiline=true")
+                        .bean(new MarketOrderStatusService())
+                        .bean(new QuickfixjMessageJsonPrinter());
+
+                from("jetty:" + orderStatusServiceUrl)
+                        .bean(new OrderStatusRequestTransformer())
+                        .routingSlip(method(FixSessionRouter.class, "route"))
+                        .bean(new QuickfixjMessageJsonTransformer(), 
"transform(${body})");
+            }
+        };
+
+        context.addRoutes(routes);
+
+        LOG.info("Starting Camel context");
+        context.start();
+
+        if (!logonLatch.await(5L, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Logon did not succeed");
+        }
+
+        // Send a request to the order status web service.
+        // Verify that the response is a JSON response.
+
+        URL orderStatusUrl = new URL(orderStatusServiceUrl + 
"?sessionID=FIX.4.2:TRADER->MARKET&orderID=abc");
+        URLConnection connection = orderStatusUrl.openConnection();
+        BufferedReader orderStatusReply = IOHelper.buffered(new 
InputStreamReader(connection.getInputStream()));
+        String line = orderStatusReply.readLine();
+        if (!line.equals("\"message\": {")) {
+            throw new Exception("Don't appear to be a JSON response");
+        } else {
+            StringBuilder sb = new StringBuilder();
+            while (line != null) {
+                sb.append(line);
+                sb.append('\n');
+                line = orderStatusReply.readLine();
+            }
+            LOG.info("Web reply:\n{}", sb);
+        }
+        orderStatusReply.close();
+
+        LOG.info("Shutting down Camel context");
+        context.stop();
+
+        LOG.info("Example complete");
+    }
+
+    public static class OrderStatusRequestTransformer {
+        private static final Logger LOG = 
LoggerFactory.getLogger(OrderStatusRequestTransformer.class);
+
+        public void transform(Exchange exchange) throws FieldNotFound {
+            // For the reply take the reverse sessionID into the account, see 
org.apache.camel.component.quickfixj.MessagePredicate
+            String requestSessionID = exchange.getIn().getHeader("sessionID", 
String.class);
+            String replySessionID = "FIX.4.2:MARKET->TRADER";
+            LOG.info("Given the requestSessionID '{}' calculated the 
replySessionID as '{}'", requestSessionID, replySessionID);
+
+            String orderID = exchange.getIn().getHeader("orderID", 
String.class);
+
+            OrderStatusRequest request = new OrderStatusRequest(new 
ClOrdID("XYZ"), new Symbol("GOOG"), new Side(Side.BUY));
+            request.set(new OrderID(orderID));
+
+            // Look for a reply execution report back to the requester session
+            // and having the requested OrderID. This is a loose correlation 
but the best
+            // we can do with FIX 4.2. Newer versions of FIX have an optional 
explicit correlation field.
+            exchange.setProperty(QuickfixjProducer.CORRELATION_CRITERIA_KEY, 
new MessagePredicate(
+                    new SessionID(replySessionID), 
MsgType.EXECUTION_REPORT).withField(OrderID.FIELD,
+                            request.getString(OrderID.FIELD)));
+
+            exchange.getIn().setBody(request);
+        }
+    }
+
+    public static class MarketOrderStatusService {
+        private static final Logger LOG = 
LoggerFactory.getLogger(MarketOrderStatusService.class);
+
+        public ExecutionReport getOrderStatus(OrderStatusRequest request) 
throws FieldNotFound {
+            LOG.info("Received order status request for orderId={}", 
request.getOrderID().getValue());
+            return new ExecutionReport(
+                    request.getOrderID(),
+                    new ExecID(UUID.randomUUID().toString()),
+                    new ExecTransType(ExecTransType.STATUS),
+                    new ExecType(ExecType.REJECTED),
+                    new OrdStatus(OrdStatus.REJECTED),
+                    new Symbol("GOOG"),
+                    new Side(Side.BUY),
+                    new LeavesQty(100),
+                    new CumQty(0),
+                    new AvgPx(0));
+        }
+    }
+
+    public static class FixSessionRouter {
+        public String route(@Header("sessionID") String sessionID) {
+            return 
String.format("quickfix:examples/inprocess.qf.cfg?sessionID=%s", sessionID);
+        }
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/RestartRouteExample.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/RestartRouteExample.java
new file mode 100644
index 00000000..2ec16991
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/RestartRouteExample.java
@@ -0,0 +1,104 @@
+/*
+ * 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.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Producer;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
+import org.apache.camel.component.quickfixj.TestSupport;
+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.field.MsgType;
+import quickfix.fix42.Email;
+
+/**
+ * Stopping a route should stop engine if no longer in use. And starting the 
route should start engine again.
+ */
+public class RestartRouteExample {
+    private static final Logger LOG = 
LoggerFactory.getLogger(RestartRouteExample.class);
+
+    public static void main(String[] args) throws Exception {
+        new RestartRouteExample().sendMessage();
+    }
+
+    public void sendMessage() throws Exception {
+        DefaultCamelContext context = new DefaultCamelContext();
+
+        final CountDownLatch receivedMessageLatch = new CountDownLatch(2);
+
+        RouteBuilder routes = new RouteBuilder() {
+            @Override
+            public void configure() {
+                
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER").routeId("foo")
+                        
.filter(header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.EMAIL))
+                        .bean(new CountDownLatchDecrementer("message", 
receivedMessageLatch));
+            }
+        };
+
+        context.addRoutes(routes);
+
+        LOG.info("Starting Camel context");
+        context.start();
+
+        String marketUri = 
"quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET";
+        Producer producer = context.getEndpoint(marketUri).createProducer();
+
+        Email email = TestSupport.createEmailMessage("Example");
+        Exchange exchange = 
producer.getEndpoint().createExchange(ExchangePattern.InOnly);
+        exchange.getIn().setBody(email);
+        producer.process(exchange);
+
+        // wait a little before stopping
+        Thread.sleep(5000);
+
+        // stop route
+        context.getRouteController().stopRoute("foo");
+
+        // wait a little before starting
+        Thread.sleep(5000);
+
+        // start route again
+        context.getRouteController().startRoute("foo");
+
+        // wait a little before sending
+        Thread.sleep(5000);
+
+        // send another email
+        producer = context.getEndpoint(marketUri).createProducer();
+        email = TestSupport.createEmailMessage("Example2");
+        exchange = 
producer.getEndpoint().createExchange(ExchangePattern.InOnly);
+        exchange.getIn().setBody(email);
+        producer.process(exchange);
+
+        if (!receivedMessageLatch.await(30L, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Message did not reach market");
+        }
+
+        LOG.info("Message received, shutting down Camel context");
+
+        context.stop();
+
+        LOG.info("Example complete");
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/SimpleMessagingExample.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/SimpleMessagingExample.java
new file mode 100644
index 00000000..45f2a766
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/SimpleMessagingExample.java
@@ -0,0 +1,104 @@
+/*
+ * 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.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Producer;
+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.TestSupport;
+import 
org.apache.camel.component.quickfixj.examples.transform.QuickfixjMessageJsonPrinter;
+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.field.MsgType;
+import quickfix.fix42.Email;
+
+/**
+ * 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 SimpleMessagingExample {
+    private static final Logger LOG = 
LoggerFactory.getLogger(SimpleMessagingExample.class);
+
+    public static void main(String[] args) throws Exception {
+        new SimpleMessagingExample().sendMessage();
+    }
+
+    public void sendMessage() throws Exception {
+        DefaultCamelContext context = new DefaultCamelContext();
+
+        final CountDownLatch logonLatch = new CountDownLatch(2);
+        final CountDownLatch receivedMessageLatch = new CountDownLatch(1);
+
+        RouteBuilder routes = new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Release latch when session logon events are received
+                // We expect two events, one for the trader session and one 
for the market session
+                from("quickfix:examples/inprocess.qf.cfg")
+                        
.filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogon))
+                        .bean(new CountDownLatchDecrementer("logon", 
logonLatch));
+
+                // For all received messages, print the JSON-formatted message 
to stdout
+                
from("quickfix:examples/inprocess.qf.cfg").filter(PredicateBuilder.or(
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AdminMessageReceived),
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived)))
+                        .bean(new QuickfixjMessageJsonPrinter());
+
+                // If the market session receives an email then release the 
latch
+                
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:MARKET->TRADER")
+                        
.filter(header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.EMAIL))
+                        .bean(new CountDownLatchDecrementer("message", 
receivedMessageLatch));
+            }
+        };
+
+        context.addRoutes(routes);
+
+        LOG.info("Starting Camel context");
+        context.start();
+
+        if (!logonLatch.await(5L, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Logon did not succeed");
+        }
+
+        String marketUri = 
"quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET";
+        Producer producer = context.getEndpoint(marketUri).createProducer();
+
+        Email email = TestSupport.createEmailMessage("Example");
+        Exchange exchange = 
producer.getEndpoint().createExchange(ExchangePattern.InOnly);
+        exchange.getIn().setBody(email);
+        producer.process(exchange);
+
+        if (!receivedMessageLatch.await(5L, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Message did not reach market");
+        }
+
+        LOG.info("Message received, shutting down Camel context");
+
+        context.stop();
+
+        LOG.info("Example complete");
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/routing/FixMessageRouter.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/routing/FixMessageRouter.java
new file mode 100644
index 00000000..a14f37ed
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/routing/FixMessageRouter.java
@@ -0,0 +1,107 @@
+/*
+ * 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.routing;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import quickfix.FieldMap;
+import quickfix.Message;
+import quickfix.Message.Header;
+import quickfix.SessionID;
+import quickfix.field.BeginString;
+import quickfix.field.DeliverToCompID;
+import quickfix.field.DeliverToLocationID;
+import quickfix.field.DeliverToSubID;
+import quickfix.field.OnBehalfOfCompID;
+import quickfix.field.OnBehalfOfLocationID;
+import quickfix.field.OnBehalfOfSubID;
+import quickfix.field.SenderCompID;
+import quickfix.field.SenderLocationID;
+import quickfix.field.SenderSubID;
+import quickfix.field.TargetCompID;
+import quickfix.field.TargetLocationID;
+import quickfix.field.TargetSubID;
+
+/**
+ * Routes exchanges based on FIX-specific routing fields in the message.
+ */
+public class FixMessageRouter {
+    private static final Logger LOG = 
LoggerFactory.getLogger(FixMessageRouter.class);
+
+    private final String engineUri;
+
+    public FixMessageRouter(String engineUri) {
+        this.engineUri = engineUri;
+    }
+
+    public String route(Exchange exchange) {
+        Message message = exchange.getIn().getBody(Message.class);
+        if (message != null) {
+            SessionID destinationSession = getDestinationSessionID(message);
+            if (destinationSession != null) {
+                String destinationUri = String.format("%s?sessionID=%s", 
engineUri, destinationSession);
+                LOG.debug("Routing destination: {}", destinationUri);
+                return destinationUri;
+            }
+        }
+        return null;
+    }
+
+    private SessionID getDestinationSessionID(Message message) {
+        Header header = message.getHeader();
+        String fixVersion = getField(header, BeginString.FIELD);
+        String destinationCompId = getField(header, DeliverToCompID.FIELD);
+        if (destinationCompId != null) {
+            String destinationSubId = getField(header, DeliverToSubID.FIELD);
+            String destinationLocationId = getField(header, 
DeliverToLocationID.FIELD);
+
+            header.removeField(DeliverToCompID.FIELD);
+            header.removeField(DeliverToSubID.FIELD);
+            header.removeField(DeliverToLocationID.FIELD);
+
+            String gatewayCompId = getField(header, TargetCompID.FIELD);
+            String gatewaySubId = getField(header, TargetSubID.FIELD);
+            String gatewayLocationId = getField(header, 
TargetLocationID.FIELD);
+
+            header.setString(OnBehalfOfCompID.FIELD, getField(header, 
SenderCompID.FIELD));
+            if (header.isSetField(SenderSubID.FIELD)) {
+                header.setString(OnBehalfOfSubID.FIELD, getField(header, 
SenderSubID.FIELD));
+            }
+            if (header.isSetField(SenderLocationID.FIELD)) {
+                header.setString(OnBehalfOfLocationID.FIELD, getField(header, 
SenderLocationID.FIELD));
+            }
+
+            return new SessionID(
+                    fixVersion, gatewayCompId, gatewaySubId, gatewayLocationId,
+                    destinationCompId, destinationSubId, 
destinationLocationId, null);
+        }
+        return null;
+    }
+
+    private String getField(FieldMap fieldMap, int tag) {
+        if (fieldMap.isSetField(tag)) {
+            try {
+                return fieldMap.getString(tag);
+            } catch (Exception e) {
+                throw RuntimeCamelException.wrapRuntimeCamelException(e);
+            }
+        }
+        return null;
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/MarketQuoteProvider.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/MarketQuoteProvider.java
new file mode 100644
index 00000000..121d5ee0
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/MarketQuoteProvider.java
@@ -0,0 +1,27 @@
+/*
+ * 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.trading;
+
+/**
+ * Trivial market data provider interface to allow plugins for alternative 
market data sources.
+ *
+ */
+public interface MarketQuoteProvider {
+    double getBid(String symbol);
+
+    double getAsk(String symbol);
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/QuickfixjMessageListener.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/QuickfixjMessageListener.java
new file mode 100644
index 00000000..b69579fd
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/QuickfixjMessageListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.trading;
+
+import quickfix.Message;
+import quickfix.SessionID;
+
+public interface QuickfixjMessageListener {
+    void onMessage(SessionID sessionID, Message message) throws Exception;
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutor.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutor.java
new file mode 100644
index 00000000..0cefd2c2
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutor.java
@@ -0,0 +1,457 @@
+/*
+ * 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.trading;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.camel.RuntimeCamelException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import quickfix.DataDictionary;
+import quickfix.DataDictionaryProvider;
+import quickfix.FieldNotFound;
+import quickfix.FixVersions;
+import quickfix.IncorrectTagValue;
+import quickfix.LogUtil;
+import quickfix.Message;
+import quickfix.MessageUtils;
+import quickfix.Session;
+import quickfix.SessionID;
+import quickfix.SessionNotFound;
+import quickfix.field.ApplVerID;
+import quickfix.field.AvgPx;
+import quickfix.field.CumQty;
+import quickfix.field.ExecID;
+import quickfix.field.ExecTransType;
+import quickfix.field.ExecType;
+import quickfix.field.LastPx;
+import quickfix.field.LastQty;
+import quickfix.field.LastShares;
+import quickfix.field.LeavesQty;
+import quickfix.field.OrdStatus;
+import quickfix.field.OrdType;
+import quickfix.field.OrderID;
+import quickfix.field.OrderQty;
+import quickfix.field.Price;
+import quickfix.field.Side;
+import quickfix.field.Symbol;
+
+/**
+ * Trade executor based on QFJ example "executor" (No Camel dependencies)
+ */
+public class TradeExecutor {
+    private static final Logger LOG = 
LoggerFactory.getLogger(TradeExecutor.class);
+
+    private boolean alwaysFillLimitOrders;
+    private Set<String> validOrderTypes = new HashSet<>();
+    private MarketQuoteProvider marketQuoteProvider;
+
+    private List<QuickfixjMessageListener> listeners = new 
CopyOnWriteArrayList<>();
+
+    private int orderID;
+    private int execID;
+
+    public TradeExecutor() {
+        setAlwaysFillLimitOrders(true);
+
+        Set<String> validOrderTypes = new HashSet<>();
+        validOrderTypes.add(OrdType.LIMIT + "");
+        validOrderTypes.add(OrdType.MARKET + "");
+        setValidOrderTypes(validOrderTypes);
+
+        setMarketQuoteProvider(new DefaultMarketQuoteProvider(10.00));
+    }
+
+    public void setAlwaysFillLimitOrders(boolean alwaysFillLimitOrders) {
+        this.alwaysFillLimitOrders = alwaysFillLimitOrders;
+    }
+
+    public void setMarketQuoteProvider(MarketQuoteProvider 
marketQuoteProvider) {
+        this.marketQuoteProvider = marketQuoteProvider;
+    }
+
+    public void setValidOrderTypes(String validOrderTypes) {
+        setValidOrderTypes(new 
HashSet<>(Arrays.asList(validOrderTypes.split("\\s*,\\s*"))));
+    }
+
+    public void setValidOrderTypes(Set<String> validOrderTypes) {
+        this.validOrderTypes = validOrderTypes;
+    }
+
+    public void addListener(QuickfixjMessageListener listener) {
+        listeners.add(listener);
+    }
+
+    public void removeListener(QuickfixjMessageListener listener) {
+        listeners.remove(listener);
+    }
+
+    public void execute(final Message message) {
+        final SessionID sessionID = MessageUtils.getSessionID(message);
+
+        try {
+            if (message instanceof quickfix.fix40.NewOrderSingle) {
+                onMessage((quickfix.fix40.NewOrderSingle) message, sessionID);
+            } else if (message instanceof quickfix.fix41.NewOrderSingle) {
+                onMessage((quickfix.fix41.NewOrderSingle) message, sessionID);
+            } else if (message instanceof quickfix.fix42.NewOrderSingle) {
+                onMessage((quickfix.fix42.NewOrderSingle) message, sessionID);
+            } else if (message instanceof quickfix.fix43.NewOrderSingle) {
+                onMessage((quickfix.fix43.NewOrderSingle) message, sessionID);
+            } else if (message instanceof quickfix.fix44.NewOrderSingle) {
+                onMessage((quickfix.fix44.NewOrderSingle) message, sessionID);
+            } else if (message instanceof quickfix.fix50.NewOrderSingle) {
+                onMessage((quickfix.fix50.NewOrderSingle) message, sessionID);
+            }
+        } catch (Exception e) {
+            LOG.error("Error submitting execution task", e);
+        }
+    }
+
+    private void onMessage(quickfix.fix40.NewOrderSingle order, SessionID 
sessionID)
+            throws FieldNotFound, IncorrectTagValue {
+        try {
+            validateOrder(order);
+
+            OrderQty orderQty = order.getOrderQty();
+
+            Price price = getPrice(order);
+
+            quickfix.fix40.ExecutionReport accept = new 
quickfix.fix40.ExecutionReport(
+                    genOrderID(), genExecID(),
+                    new ExecTransType(ExecTransType.NEW), new 
OrdStatus(OrdStatus.NEW), order.getSymbol(), order.getSide(),
+                    orderQty, new LastShares(0), new LastPx(0), new CumQty(0), 
new AvgPx(0));
+
+            accept.set(order.getClOrdID());
+            sendMessage(sessionID, accept);
+
+            if (isOrderExecutable(order, price)) {
+                quickfix.fix40.ExecutionReport fill = new 
quickfix.fix40.ExecutionReport(
+                        genOrderID(), genExecID(),
+                        new ExecTransType(ExecTransType.NEW), new 
OrdStatus(OrdStatus.FILLED), order.getSymbol(), order
+                                .getSide(),
+                        orderQty, new LastShares(orderQty.getValue()), new 
LastPx(price.getValue()),
+                        new CumQty(orderQty.getValue()), new 
AvgPx(price.getValue()));
+
+                fill.set(order.getClOrdID());
+
+                sendMessage(sessionID, fill);
+            }
+        } catch (RuntimeException e) {
+            LogUtil.logThrowable(sessionID, e.getMessage(), e);
+        }
+    }
+
+    private boolean isOrderExecutable(Message order, Price price) throws 
FieldNotFound {
+        if (order.getChar(OrdType.FIELD) == OrdType.LIMIT) {
+            BigDecimal limitPrice = new 
BigDecimal(order.getString(Price.FIELD));
+            char side = order.getChar(Side.FIELD);
+            BigDecimal thePrice = new BigDecimal(price.getValue());
+
+            return side == Side.BUY && thePrice.compareTo(limitPrice) <= 0
+                    || (side == Side.SELL || side == Side.SELL_SHORT) && 
thePrice.compareTo(limitPrice) >= 0;
+        }
+        return true;
+    }
+
+    private Price getPrice(Message message) throws FieldNotFound {
+        Price price;
+        if (message.getChar(OrdType.FIELD) == OrdType.LIMIT && 
alwaysFillLimitOrders) {
+            price = new Price(message.getDouble(Price.FIELD));
+        } else {
+            if (marketQuoteProvider == null) {
+                throw new RuntimeCamelException("No market data provider 
specified for market order");
+            }
+            char side = message.getChar(Side.FIELD);
+            if (side == Side.BUY) {
+                price = new 
Price(marketQuoteProvider.getAsk(message.getString(Symbol.FIELD)));
+            } else if (side == Side.SELL || side == Side.SELL_SHORT) {
+                price = new 
Price(marketQuoteProvider.getBid(message.getString(Symbol.FIELD)));
+            } else {
+                throw new RuntimeCamelException("Invalid order side: " + side);
+            }
+        }
+        return price;
+    }
+
+    private void sendMessage(SessionID sessionID, Message message) {
+        try {
+            Session session = Session.lookupSession(sessionID);
+            if (session == null) {
+                throw new SessionNotFound(sessionID.toString());
+            }
+
+            DataDictionaryProvider provider = 
session.getDataDictionaryProvider();
+            if (provider != null) {
+                try {
+                    ApplVerID applVerID = getApplVerID(session, message);
+                    DataDictionary appDataDictionary = 
provider.getApplicationDataDictionary(applVerID);
+                    appDataDictionary.validate(message, true);
+                } catch (Exception e) {
+                    LogUtil.logThrowable(sessionID, "Outgoing message failed 
validation: "
+                                                    + e.getMessage(),
+                            e);
+                    return;
+                }
+            }
+
+            for (QuickfixjMessageListener listener : listeners) {
+                try {
+                    listener.onMessage(sessionID, message);
+                } catch (Throwable e) {
+                    LogUtil.logThrowable(sessionID, "Error while dispatching 
message", e);
+                }
+            }
+
+        } catch (SessionNotFound e) {
+            LOG.error(e.getMessage(), e);
+        }
+    }
+
+    private ApplVerID getApplVerID(Session session, Message message) {
+        String beginString = session.getSessionID().getBeginString();
+        if (FixVersions.BEGINSTRING_FIXT11.equals(beginString)) {
+            return new ApplVerID(ApplVerID.FIX50);
+        } else {
+            return MessageUtils.toApplVerID(beginString);
+        }
+    }
+
+    private void onMessage(quickfix.fix41.NewOrderSingle order, SessionID 
sessionID)
+            throws FieldNotFound, IncorrectTagValue {
+        try {
+            validateOrder(order);
+
+            OrderQty orderQty = order.getOrderQty();
+            Price price = getPrice(order);
+
+            quickfix.fix41.ExecutionReport accept = new 
quickfix.fix41.ExecutionReport(
+                    genOrderID(), genExecID(),
+                    new ExecTransType(ExecTransType.NEW), new 
ExecType(ExecType.NEW), new OrdStatus(OrdStatus.NEW), order
+                            .getSymbol(),
+                    order.getSide(), orderQty, new LastShares(0), new 
LastPx(0), new LeavesQty(0),
+                    new CumQty(0), new AvgPx(0));
+
+            accept.set(order.getClOrdID());
+            sendMessage(sessionID, accept);
+
+            if (isOrderExecutable(order, price)) {
+                quickfix.fix41.ExecutionReport executionReport = new 
quickfix.fix41.ExecutionReport(
+                        genOrderID(),
+                        genExecID(), new ExecTransType(ExecTransType.NEW), new 
ExecType(ExecType.FILL), new OrdStatus(
+                                OrdStatus.FILLED),
+                        order.getSymbol(), order.getSide(), orderQty, new 
LastShares(
+                                orderQty
+                                        .getValue()),
+                        new LastPx(price.getValue()), new LeavesQty(0), new 
CumQty(
+                                orderQty
+                                        .getValue()),
+                        new AvgPx(price.getValue()));
+
+                executionReport.set(order.getClOrdID());
+
+                sendMessage(sessionID, executionReport);
+            }
+        } catch (RuntimeException e) {
+            LogUtil.logThrowable(sessionID, e.getMessage(), e);
+        }
+    }
+
+    private void onMessage(quickfix.fix42.NewOrderSingle order, SessionID 
sessionID)
+            throws FieldNotFound, IncorrectTagValue {
+        try {
+            validateOrder(order);
+
+            OrderQty orderQty = order.getOrderQty();
+            Price price = getPrice(order);
+
+            quickfix.fix42.ExecutionReport accept = new 
quickfix.fix42.ExecutionReport(
+                    genOrderID(), genExecID(),
+                    new ExecTransType(ExecTransType.NEW), new 
ExecType(ExecType.NEW), new OrdStatus(OrdStatus.NEW), order
+                            .getSymbol(),
+                    order.getSide(), new LeavesQty(0), new CumQty(0), new 
AvgPx(0));
+
+            accept.set(order.getClOrdID());
+            sendMessage(sessionID, accept);
+
+            if (isOrderExecutable(order, price)) {
+                quickfix.fix42.ExecutionReport executionReport = new 
quickfix.fix42.ExecutionReport(
+                        genOrderID(),
+                        genExecID(), new ExecTransType(ExecTransType.NEW), new 
ExecType(ExecType.FILL),
+                        new OrdStatus(OrdStatus.FILLED), order.getSymbol(), 
order.getSide(), new LeavesQty(0),
+                        new CumQty(orderQty.getValue()), new 
AvgPx(price.getValue()));
+
+                executionReport.set(order.getClOrdID());
+                executionReport.set(orderQty);
+                executionReport.set(new LastShares(orderQty.getValue()));
+                executionReport.set(new LastPx(price.getValue()));
+
+                sendMessage(sessionID, executionReport);
+            }
+        } catch (RuntimeException e) {
+            LogUtil.logThrowable(sessionID, e.getMessage(), e);
+        }
+    }
+
+    private void validateOrder(Message order) throws IncorrectTagValue, 
FieldNotFound {
+        OrdType ordType = new OrdType(order.getChar(OrdType.FIELD));
+        if (!validOrderTypes.contains(Character.toString(ordType.getValue()))) 
{
+            LOG.error("Order type not in ValidOrderTypes setting");
+            throw new IncorrectTagValue(ordType.getField());
+        }
+        if (ordType.getValue() == OrdType.MARKET && marketQuoteProvider == 
null) {
+            LOG.error("DefaultMarketPrice setting not specified for market 
order");
+            throw new IncorrectTagValue(ordType.getField());
+        }
+    }
+
+    private void onMessage(quickfix.fix43.NewOrderSingle order, SessionID 
sessionID)
+            throws FieldNotFound, IncorrectTagValue {
+        try {
+            validateOrder(order);
+
+            OrderQty orderQty = order.getOrderQty();
+            Price price = getPrice(order);
+
+            quickfix.fix43.ExecutionReport accept = new 
quickfix.fix43.ExecutionReport(
+                    genOrderID(), genExecID(), new ExecType(ExecType.NEW), new 
OrdStatus(OrdStatus.NEW),
+                    order.getSide(), new 
LeavesQty(order.getOrderQty().getValue()), new CumQty(0), new AvgPx(0));
+
+            accept.set(order.getClOrdID());
+            accept.set(order.getSymbol());
+            sendMessage(sessionID, accept);
+
+            if (isOrderExecutable(order, price)) {
+                quickfix.fix43.ExecutionReport executionReport = new 
quickfix.fix43.ExecutionReport(
+                        genOrderID(),
+                        genExecID(), new ExecType(ExecType.FILL), new 
OrdStatus(OrdStatus.FILLED), order.getSide(),
+                        new LeavesQty(0), new CumQty(orderQty.getValue()), new 
AvgPx(price.getValue()));
+
+                executionReport.set(order.getClOrdID());
+                executionReport.set(order.getSymbol());
+                executionReport.set(orderQty);
+                executionReport.set(new LastQty(orderQty.getValue()));
+                executionReport.set(new LastPx(price.getValue()));
+
+                sendMessage(sessionID, executionReport);
+            }
+        } catch (RuntimeException e) {
+            LogUtil.logThrowable(sessionID, e.getMessage(), e);
+        }
+    }
+
+    private void onMessage(quickfix.fix44.NewOrderSingle order, SessionID 
sessionID)
+            throws FieldNotFound, IncorrectTagValue {
+        try {
+            validateOrder(order);
+
+            OrderQty orderQty = order.getOrderQty();
+            Price price = getPrice(order);
+
+            quickfix.fix44.ExecutionReport accept = new 
quickfix.fix44.ExecutionReport(
+                    genOrderID(), genExecID(), new ExecType(ExecType.NEW), new 
OrdStatus(OrdStatus.NEW),
+                    order.getSide(), new 
LeavesQty(order.getOrderQty().getValue()), new CumQty(0), new AvgPx(0));
+
+            accept.set(order.getClOrdID());
+            accept.set(order.getSymbol());
+            sendMessage(sessionID, accept);
+
+            if (isOrderExecutable(order, price)) {
+                quickfix.fix44.ExecutionReport executionReport = new 
quickfix.fix44.ExecutionReport(
+                        genOrderID(),
+                        genExecID(), new ExecType(ExecType.FILL), new 
OrdStatus(OrdStatus.FILLED), order.getSide(),
+                        new LeavesQty(0), new CumQty(orderQty.getValue()), new 
AvgPx(price.getValue()));
+
+                executionReport.set(order.getClOrdID());
+                executionReport.set(order.getSymbol());
+                executionReport.set(orderQty);
+                executionReport.set(new LastQty(orderQty.getValue()));
+                executionReport.set(new LastPx(price.getValue()));
+
+                sendMessage(sessionID, executionReport);
+            }
+        } catch (RuntimeException e) {
+            LogUtil.logThrowable(sessionID, e.getMessage(), e);
+        }
+    }
+
+    private void onMessage(quickfix.fix50.NewOrderSingle order, SessionID 
sessionID)
+            throws FieldNotFound, IncorrectTagValue {
+        try {
+            validateOrder(order);
+
+            OrderQty orderQty = order.getOrderQty();
+            Price price = getPrice(order);
+
+            quickfix.fix50.ExecutionReport accept = new 
quickfix.fix50.ExecutionReport(
+                    genOrderID(), genExecID(), new ExecType(ExecType.NEW), new 
OrdStatus(OrdStatus.NEW),
+                    order.getSide(), new 
LeavesQty(order.getOrderQty().getValue()), new CumQty(0));
+
+            accept.set(order.getClOrdID());
+            accept.set(order.getSymbol());
+            sendMessage(sessionID, accept);
+
+            if (isOrderExecutable(order, price)) {
+                quickfix.fix50.ExecutionReport executionReport = new 
quickfix.fix50.ExecutionReport(
+                        genOrderID(), genExecID(), new 
ExecType(ExecType.FILL), new OrdStatus(OrdStatus.FILLED),
+                        order.getSide(), new LeavesQty(0), new 
CumQty(orderQty.getValue()));
+
+                executionReport.set(order.getClOrdID());
+                executionReport.set(order.getSymbol());
+                executionReport.set(orderQty);
+                executionReport.set(new LastQty(orderQty.getValue()));
+                executionReport.set(new LastPx(price.getValue()));
+                executionReport.set(new AvgPx(price.getValue()));
+
+                sendMessage(sessionID, executionReport);
+            }
+        } catch (RuntimeException e) {
+            LogUtil.logThrowable(sessionID, e.getMessage(), e);
+        }
+    }
+
+    public OrderID genOrderID() {
+        return new OrderID(Integer.valueOf(++orderID).toString());
+    }
+
+    public ExecID genExecID() {
+        return new ExecID(Integer.valueOf(++execID).toString());
+    }
+
+    private static class DefaultMarketQuoteProvider implements 
MarketQuoteProvider {
+        private double defaultMarketPrice;
+
+        DefaultMarketQuoteProvider(double defaultMarketPrice) {
+            this.defaultMarketPrice = defaultMarketPrice;
+        }
+
+        @Override
+        public double getAsk(String symbol) {
+            return defaultMarketPrice;
+        }
+
+        @Override
+        public double getBid(String symbol) {
+            return defaultMarketPrice;
+        }
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java
new file mode 100644
index 00000000..b1076248
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorComponent.java
@@ -0,0 +1,167 @@
+/*
+ * 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.trading;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.component.quickfixj.QuickfixjEventCategory;
+import org.apache.camel.component.quickfixj.converter.QuickfixjConverters;
+import org.apache.camel.support.DefaultComponent;
+import org.apache.camel.support.DefaultConsumer;
+import org.apache.camel.support.DefaultEndpoint;
+import org.apache.camel.support.DefaultProducer;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import quickfix.Message;
+import quickfix.Message.Header;
+import quickfix.SessionID;
+import quickfix.field.SenderCompID;
+import quickfix.field.SenderLocationID;
+import quickfix.field.SenderSubID;
+import quickfix.field.TargetCompID;
+import quickfix.field.TargetLocationID;
+import quickfix.field.TargetSubID;
+
+/**
+ * Adapts the TradeExecutor for use as a Camel endpoint.
+ *
+ * @see TradeExecutor
+ */
+public class TradeExecutorComponent extends DefaultComponent {
+    private static final Logger LOG = 
LoggerFactory.getLogger(TradeExecutorComponent.class);
+
+    private Map<String, TradeExecutorEndpoint> endpoints = new HashMap<>();
+    private final Executor executor;
+
+    public TradeExecutorComponent() {
+        this(Executors.newCachedThreadPool(new TradeExecutorThreadFactory()));
+    }
+
+    private static class TradeExecutorThreadFactory implements ThreadFactory {
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread thread = new Thread(r, "Trade Executor");
+            thread.setDaemon(true);
+            return thread;
+        }
+    }
+
+    public TradeExecutorComponent(Executor executor) {
+        this.executor = executor;
+    }
+
+    @Override
+    protected Endpoint createEndpoint(String uri, String remaining, 
Map<String, Object> parameters) throws Exception {
+        synchronized (endpoints) {
+            Endpoint endpoint = endpoints.get(uri);
+            if (endpoint == null) {
+                endpoint = new TradeExecutorEndpoint(uri, new TradeExecutor());
+                endpoints.put(uri, (TradeExecutorEndpoint) endpoint);
+                LOG.info("Created trade executor: {}", uri);
+            }
+            return endpoint;
+        }
+    }
+
+    private class TradeExecutorEndpoint extends DefaultEndpoint {
+        private final TradeExecutor tradeExecutor;
+        private List<Processor> processors = new CopyOnWriteArrayList<>();
+
+        TradeExecutorEndpoint(String uri, TradeExecutor tradeExecutor) {
+            super(uri, TradeExecutorComponent.this);
+            this.tradeExecutor = tradeExecutor;
+            tradeExecutor.addListener(new QuickfixjMessageListener() {
+                @Override
+                public void onMessage(SessionID sessionID, Message message) 
throws Exception {
+                    // Inject session ID into message so producer will know 
where to send it
+                    Header header = message.getHeader();
+                    setOptionalField(header, sessionID, SenderCompID.FIELD, 
sessionID.getTargetCompID());
+                    setOptionalField(header, sessionID, SenderSubID.FIELD, 
sessionID.getTargetSubID());
+                    setOptionalField(header, sessionID, 
SenderLocationID.FIELD, sessionID.getTargetLocationID());
+                    setOptionalField(header, sessionID, TargetCompID.FIELD, 
sessionID.getSenderCompID());
+                    setOptionalField(header, sessionID, TargetSubID.FIELD, 
sessionID.getSenderSubID());
+                    setOptionalField(header, sessionID, 
TargetLocationID.FIELD, sessionID.getSenderLocationID());
+
+                    Exchange exchange = QuickfixjConverters.toExchange(
+                            TradeExecutorEndpoint.this, sessionID, message,
+                            QuickfixjEventCategory.AppMessageReceived);
+
+                    for (Processor processor : processors) {
+                        processor.process(exchange);
+                    }
+                }
+
+                private void setOptionalField(Header header, SessionID 
sessionID, int tag, String value) {
+                    if (!ObjectHelper.isEmpty(value)) {
+                        header.setString(tag, value);
+                    }
+                }
+            });
+        }
+
+        @Override
+        public Producer createProducer() {
+            return new DefaultProducer(this) {
+                @Override
+                public void process(final Exchange exchange) {
+                    executor.execute(new Runnable() {
+                        @Override
+                        public void run() {
+                            try {
+                                
tradeExecutor.execute(exchange.getIn().getMandatoryBody(Message.class));
+                            } catch (Exception e) {
+                                LOG.error("Error during trade execution", e);
+                            }
+                        }
+                    });
+                }
+            };
+        }
+
+        @Override
+        public Consumer createConsumer(Processor processor) {
+            return new DefaultConsumer(this, processor) {
+                @Override
+                protected void doStart() {
+                    processors.add(getProcessor());
+                }
+
+                @Override
+                protected void doStop() {
+                    processors.remove(getProcessor());
+                }
+            };
+        }
+
+        @Override
+        public boolean isSingleton() {
+            return false;
+        }
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java
new file mode 100644
index 00000000..03f682d0
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/trading/TradeExecutorExample.java
@@ -0,0 +1,136 @@
+/*
+ * 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.trading;
+
+import java.time.LocalDateTime;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Producer;
+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.transform.QuickfixjMessageJsonPrinter;
+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.field.ClOrdID;
+import quickfix.field.HandlInst;
+import quickfix.field.MsgType;
+import quickfix.field.OrdType;
+import quickfix.field.OrderQty;
+import quickfix.field.Price;
+import quickfix.field.Side;
+import quickfix.field.Symbol;
+import quickfix.field.TransactTime;
+import quickfix.fix42.NewOrderSingle;
+
+public class TradeExecutorExample {
+    private static final Logger LOG = 
LoggerFactory.getLogger(TradeExecutorExample.class);
+
+    public static void main(String[] args) throws Exception {
+        new TradeExecutorExample().sendMessage();
+    }
+
+    public void sendMessage() throws Exception {
+        DefaultCamelContext context = new DefaultCamelContext();
+        context.addComponent("trade-executor", new TradeExecutorComponent());
+
+        final CountDownLatch logonLatch = new CountDownLatch(2);
+        final CountDownLatch executionReportLatch = new CountDownLatch(2);
+
+        RouteBuilder routes = new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                // Release latch when session logon events are received
+                from("quickfix:examples/inprocess.qf.cfg")
+                        
.filter(header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.SessionLogon))
+                        .bean(new CountDownLatchDecrementer("logon", 
logonLatch));
+
+                
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");
+
+                
from("trade-executor:market").to("quickfix:examples/inprocess.qf.cfg");
+
+                // Logger app messages as JSON
+                
from("quickfix:examples/inprocess.qf.cfg").filter(PredicateBuilder.or(
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived),
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageSent)))
+                        .bean(new QuickfixjMessageJsonPrinter());
+
+                // Release latch when trader receives execution report
+                
from("quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET").filter(PredicateBuilder.and(
+                        
header(QuickfixjEndpoint.EVENT_CATEGORY_KEY).isEqualTo(QuickfixjEventCategory.AppMessageReceived),
+                        
header(QuickfixjEndpoint.MESSAGE_TYPE_KEY).isEqualTo(MsgType.EXECUTION_REPORT)))
+                        .bean(new CountDownLatchDecrementer("execution 
report", executionReportLatch));
+            }
+        };
+
+        context.addRoutes(routes);
+
+        LOG.info("Starting Camel context");
+        context.start();
+
+        // This is not strictly necessary, but it prevents the need for session
+        // synchronization due to app messages being sent before being logged 
on
+        if (!logonLatch.await(5, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Logon did not complete");
+        }
+
+        String gatewayUri = 
"quickfix:examples/inprocess.qf.cfg?sessionID=FIX.4.2:TRADER->MARKET";
+        Endpoint gatewayEndpoint = context.getEndpoint(gatewayUri);
+        Producer producer = gatewayEndpoint.createProducer();
+
+        LOG.info("Sending order");
+
+        NewOrderSingle order = createNewOrderMessage();
+        Exchange exchange = 
producer.getEndpoint().createExchange(ExchangePattern.InOnly);
+        exchange.getIn().setBody(order);
+        producer.process(exchange);
+
+        if (!executionReportLatch.await(5, TimeUnit.SECONDS)) {
+            throw new IllegalStateException("Did not receive execution 
reports");
+        }
+
+        LOG.info("Message received, shutting down Camel context");
+
+        context.stop();
+
+        LOG.info("Order execution example complete");
+    }
+
+    private NewOrderSingle createNewOrderMessage() {
+        NewOrderSingle order = new NewOrderSingle(
+                new ClOrdID("CLIENT_ORDER_ID"),
+                new HandlInst('1'),
+                new Symbol("GOOG"),
+                new Side(Side.BUY),
+                new TransactTime(LocalDateTime.now()),
+                new OrdType(OrdType.LIMIT));
+
+        order.set(new OrderQty(10));
+        order.set(new Price(300.00));
+
+        return order;
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java
new file mode 100644
index 00000000..a78ebe86
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjEventJsonTransformer.java
@@ -0,0 +1,54 @@
+/*
+ * 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.transform;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.quickfixj.QuickfixjEndpoint;
+import quickfix.DataDictionary;
+import quickfix.Message;
+import quickfix.Session;
+import quickfix.SessionID;
+
+public class QuickfixjEventJsonTransformer {
+    private final QuickfixjMessageJsonTransformer renderer;
+
+    public QuickfixjEventJsonTransformer() {
+        renderer = new QuickfixjMessageJsonTransformer();
+    }
+
+    public String transform(Exchange exchange) {
+        SessionID sessionID = 
exchange.getIn().getHeader(QuickfixjEndpoint.SESSION_ID_KEY, SessionID.class);
+        Session session = Session.lookupSession(sessionID);
+        DataDictionary dataDictionary = session.getDataDictionary();
+
+        if (dataDictionary == null) {
+            throw new IllegalStateException("No Data Dictionary. Exchange must 
reference an existing session");
+        }
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("\"event\": {\n");
+
+        org.apache.camel.Message in = exchange.getIn();
+        for (String key : in.getHeaders().keySet()) {
+            sb.append("  \"").append(key).append("\": 
").append(in.getHeader(key)).append(",\n");
+        }
+
+        sb.append(renderer.transform(in.getBody(Message.class), "  ", 
dataDictionary)).append("\n");
+        sb.append("}\n");
+        return sb.toString();
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java
new file mode 100644
index 00000000..2b70acfc
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonPrinter.java
@@ -0,0 +1,36 @@
+/*
+ * 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.transform;
+
+import org.apache.camel.Exchange;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import quickfix.ConfigError;
+
+public class QuickfixjMessageJsonPrinter {
+
+    private static final Logger LOG = 
LoggerFactory.getLogger(QuickfixjMessageJsonPrinter.class);
+    private QuickfixjEventJsonTransformer formatter;
+
+    public QuickfixjMessageJsonPrinter() throws ConfigError {
+        formatter = new QuickfixjEventJsonTransformer();
+    }
+
+    public void print(Exchange exchange) {
+        LOG.info(formatter.transform(exchange));
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java
new file mode 100644
index 00000000..4a0ee3aa
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/transform/QuickfixjMessageJsonTransformer.java
@@ -0,0 +1,110 @@
+/*
+ * 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.transform;
+
+import java.util.Iterator;
+
+import quickfix.DataDictionary;
+import quickfix.Field;
+import quickfix.FieldMap;
+import quickfix.FieldType;
+import quickfix.Group;
+import quickfix.Message;
+import quickfix.MessageUtils;
+import quickfix.Session;
+import quickfix.SessionID;
+
+public class QuickfixjMessageJsonTransformer {
+
+    public String transform(Message message) {
+        SessionID sessionID = MessageUtils.getSessionID(message);
+        Session session = Session.lookupSession(sessionID);
+        DataDictionary dataDictionary = session.getDataDictionary();
+
+        if (dataDictionary == null) {
+            throw new IllegalStateException("No Data Dictionary. Exchange must 
reference an existing session");
+        }
+
+        return transform(message, dataDictionary);
+    }
+
+    public String transform(Message message, DataDictionary dataDictionary) {
+        return transform(message, "", dataDictionary);
+    }
+
+    public String transform(Message message, String indent, DataDictionary dd) 
{
+        StringBuilder sb = new StringBuilder();
+        sb.append(indent).append("\"message\": ");
+        if (message == null) {
+            sb.append("null");
+        } else {
+            sb.append("{\n");
+            String contentIndent = indent + "  ";
+
+            transform("header", message.getHeader(), sb, contentIndent, dd);
+            sb.append("\n");
+
+            transform("body", message, sb, contentIndent, dd);
+            sb.append("\n");
+
+            transform("trailer", message.getTrailer(), sb, contentIndent, dd);
+            sb.append("\n");
+
+            sb.append(indent).append("}");
+        }
+        return sb.toString();
+    }
+
+    private void transform(String name, FieldMap fieldMap, StringBuilder sb, 
String indent, DataDictionary dd) {
+        sb.append(indent).append("\"").append(name).append("\": {\n");
+        int fieldCount = 0;
+        Iterator<Field<?>> fieldIterator = fieldMap.iterator();
+        while (fieldIterator.hasNext()) {
+            if (fieldCount > 0) {
+                sb.append(",\n");
+            }
+            Field<?> field = fieldIterator.next();
+            sb.append(indent).append("  
\"").append(dd.getFieldName(field.getField())).append("\": ");
+            if (dd.hasFieldValue(field.getField())) {
+                int tag = field.getField();
+                sb.append("[ 
\"").append(field.getObject().toString()).append("\", \"")
+                        .append(dd.getValueName(tag, 
field.getObject().toString())).append("\" ]");
+            } else {
+                FieldType fieldType = dd.getFieldType(field.getField());
+                if (Number.class.isAssignableFrom(fieldType.getJavaType())) {
+                    sb.append(field.getObject());
+                } else {
+                    
sb.append("\"").append(field.getObject().toString()).append("\"");
+                }
+            }
+            fieldCount++;
+        }
+
+        sb.append("\n");
+
+        Iterator<Integer> groupKeys = fieldMap.groupKeyIterator();
+        while (groupKeys.hasNext()) {
+            int groupTag = groupKeys.next();
+            for (Group group : fieldMap.getGroups(groupTag)) {
+                String groupName = dd.getFieldName(groupTag);
+                transform(groupName, group, sb, indent + "  ", dd);
+            }
+        }
+
+        sb.append(indent).append("}").append("\n");
+    }
+}
diff --git 
a/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java
 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java
new file mode 100644
index 00000000..4938ede4
--- /dev/null
+++ 
b/quickfixj/src/test/java/org/apache/camel/component/quickfixj/examples/util/CountDownLatchDecrementer.java
@@ -0,0 +1,42 @@
+/*
+ * 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.util;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Handler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CountDownLatchDecrementer {
+    private static final Logger LOG = 
LoggerFactory.getLogger(CountDownLatchDecrementer.class);
+
+    private String label;
+    private CountDownLatch latch;
+
+    public CountDownLatchDecrementer(String label, CountDownLatch latch) {
+        this.label = label;
+        this.latch = latch;
+    }
+
+    @Handler
+    public void decrement(Exchange exchange) {
+        LOG.info("Decrementing latch count: {}", label);
+        latch.countDown();
+    }
+}
diff --git a/quickfixj/src/test/resources/examples/gateway.qf.cfg 
b/quickfixj/src/test/resources/examples/gateway.qf.cfg
new file mode 100644
index 00000000..5e6b4605
--- /dev/null
+++ b/quickfixj/src/test/resources/examples/gateway.qf.cfg
@@ -0,0 +1,59 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+#
+# Creates an initiators and acceptors that communicate within a 
+# VM (no external socket connections).
+#
+[default]
+SocketAcceptProtocol=VM_PIPE
+SocketAcceptPort=7001
+SocketConnectProtocol=VM_PIPE
+SocketConnectPort=7001
+FileLogPath=target/log
+
+#
+# Initiator for simulating trader #1
+#
+[session]
+ConnectionType=initiator
+BeginString=FIX.4.2
+SenderCompID=TRADER@1
+TargetCompID=GATEWAY
+
+#
+# Initiator for simulating trader #2
+#
+[session]
+ConnectionType=initiator
+BeginString=FIX.4.2
+SenderCompID=TRADER@2
+TargetCompID=GATEWAY
+
+#
+# Acceptor for simulating the routing gateway
+#
+[session]
+ConnectionType=acceptor
+BeginString=FIX.4.2
+SenderCompID=GATEWAY
+TargetCompID=TRADER@1
+
+[session]
+ConnectionType=acceptor
+BeginString=FIX.4.2
+SenderCompID=GATEWAY
+TargetCompID=TRADER@2
diff --git a/quickfixj/src/test/resources/examples/inprocess.qf.cfg 
b/quickfixj/src/test/resources/examples/inprocess.qf.cfg
new file mode 100644
index 00000000..5a3bd598
--- /dev/null
+++ b/quickfixj/src/test/resources/examples/inprocess.qf.cfg
@@ -0,0 +1,46 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+#
+# Creates an initiator and acceptor that communicate within a 
+# VM (no external socket connections).
+#
+[default]
+UseJmx=Y
+SocketAcceptProtocol=VM_PIPE
+SocketConnectProtocol=VM_PIPE
+HeartBtInt=120
+FileLogPath=target/log
+
+#
+# Initiator for simulating a trader
+#
+[session]
+ConnectionType=initiator
+BeginString=FIX.4.2
+SenderCompID=TRADER
+TargetCompID=MARKET
+SocketConnectPort=7001
+
+#
+# Acceptor for simulating the market
+#
+[session]
+ConnectionType=acceptor
+BeginString=FIX.4.2
+SenderCompID=MARKET
+TargetCompID=TRADER
+SocketAcceptPort=7001
\ No newline at end of file
diff --git a/quickfixj/src/test/resources/log4j2.properties 
b/quickfixj/src/test/resources/log4j2.properties
new file mode 100644
index 00000000..7337c3a3
--- /dev/null
+++ b/quickfixj/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-quickfix-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file

Reply via email to