[
https://issues.apache.org/activemq/browse/CAMEL-1350?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=62202#action_62202
]
Hadrian Zbarcea edited comment on CAMEL-1350 at 9/28/10 5:15 PM:
-----------------------------------------------------------------
Thanks for all the comments and special thanks to Hadrian for his help.
Bengt, I've been doing some experimenting and I believe the following approach
may solve the problems you describe. If these solutions are acceptable, I'll
submit the related modifications for inclusion in the new quickfix component
code. The following code are snippets from a new example class that
demonstrates logon message customization and logon authentication.
For logon message customization, I created an example bean that puts a password
into the FIX RawData field (a common approach for older versions of the FIX
protocol).
{code}
public static class CredentialInjector {
private final String password;
public CredentialInjector(String password) {
this.password = password;
}
public void inject(Exchange exchange) throws InvalidPayloadException {
LOG.info("Injecting password into outgoing logon message");
Message message = ExchangeHelper.getMandatoryInBody(exchange,
Message.class);
message.setString(RawData.FIELD, password);
message.setInt(RawDataLength.FIELD, password.length());
}
}
{code}
I then create a route to process outgoing logon messages. (For those not
familiar with FIX engines, the logon message is generated automatically by the
engine but we want to modify it before it is sent.)
{code}
from("quickfixj:examples/inprocess.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"));
{code}
The CredentialInjector is executing in the same thread as the toAdmin()
callback so any modifications to the outgoing message will be in the sent
message.
For authentication, I created a trivial and unfriendly authenticator that
rejects all logons.
{code}
public static class LogonAuthenticator {
public void authenticate(Exchange exchange) throws RejectLogon,
InvalidPayloadException, FieldNotFound {
LOG.info("Acceptor is rejecting logon for " +
exchange.getIn().getHeader(QuickfixjEndpoint.SESSION_ID_KEY));
Message message = ExchangeHelper.getMandatoryInBody(exchange,
Message.class);
if (message.isSetField(RawData.FIELD)) {
LOG.info("Rejected password: " +
message.getString(RawData.FIELD));
}
throw new RejectLogon("Rejecting logon for test purposes");
}
}
{code}
Notice that it throws the RejectLogon exception which will eventually be
propagated out of the fromAdmin() callback in the QFJ engine. The associated
route is...
{code}
from("quickfixj:examples/inprocess.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());
{code}
The example seems to be working well for both cases. Note that both scenarios
require the Camel processor to be executing in the same thread as the QFJ
engine. It's ok to pass messages to other threads but be sure the message is
persisted locally first since you will not be able to rely on transport-level
resends via FIX.
was (Author: stevebate):
Thanks for all the comments and special thanks to Hadrian for his help.
Bengt, I've been doing some experimenting and I believe the following approach
may solve the problems you describe. If these solutions are acceptable, I'll
submit the related modifications for inclusion in the new quickfix component
code. The following code are snippets from a new example class that
demonstrates logon message customization and logon authentication.
For logon message customization, I created an example bean that puts a password
into the FIX RawData field (a common approach for older versions of the FIX
protocol).
public static class CredentialInjector {
private final String password;
public CredentialInjector(String password) {
this.password = password;
}
public void inject(Exchange exchange) throws InvalidPayloadException {
LOG.info("Injecting password into outgoing logon message");
Message message = ExchangeHelper.getMandatoryInBody(exchange,
Message.class);
message.setString(RawData.FIELD, password);
message.setInt(RawDataLength.FIELD, password.length());
}
}
I then create a route to process outgoing logon messages. (For those not
familiar with FIX engines, the logon message is generated automatically by the
engine but we want to modify it before it is sent.)
from("quickfixj:examples/inprocess.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"));
The CredentialInjector is executing in the same thread as the toAdmin()
callback so any modifications to the outgoing message will be in the sent
message.
For authentication, I created a trivial and unfriendly authenticator that
rejects all logons.
public static class LogonAuthenticator {
public void authenticate(Exchange exchange) throws RejectLogon,
InvalidPayloadException, FieldNotFound {
LOG.info("Acceptor is rejecting logon for " +
exchange.getIn().getHeader(QuickfixjEndpoint.SESSION_ID_KEY));
Message message = ExchangeHelper.getMandatoryInBody(exchange,
Message.class);
if (message.isSetField(RawData.FIELD)) {
LOG.info("Rejected password: " +
message.getString(RawData.FIELD));
}
throw new RejectLogon("Rejecting logon for test purposes");
}
}
Notice that it throws the RejectLogon exception which will eventually be
propagated out of the fromAdmin() callback in the QFJ engine. The associated
route is...
from("quickfixj:examples/inprocess.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());
The example seems to be working well for both cases. Note that both scenarios
require the Camel processor to be executing in the same thread as the QFJ
engine. It's ok to pass messages to other threads but be sure the message is
persisted locally first since you will not be able to rely on transport-level
resends via FIX.
> camel-quickfix component in apache camel distribution
> -----------------------------------------------------
>
> Key: CAMEL-1350
> URL: https://issues.apache.org/activemq/browse/CAMEL-1350
> Project: Apache Camel
> Issue Type: New Feature
> Environment: <properties>
> <camel-version>2.0-SNAPSHOT</camel-version>
> <fuse-version>2.x-fuse-SNAPSHOT</fuse-version>
> <activemq-version>5.2.0</activemq-version>
> <quickfix-version>1.3.3</quickfix-version>
> <mina-version>1.1.0</mina-version>
> <slf4j-version>1.5.6</slf4j-version>
> </properties>
> Reporter: Charles Moulliard
> Assignee: Hadrian Zbarcea
> Fix For: 2.5.0
>
> Attachments: camel-quickfix-2.zip, camel-quickfix.patch,
> camel-quickfix.zip, camel-quickfix.zip, QuickFixDataFormat.java,
> reportincident.quickfix.zip
>
>
> Hi,
> ATTENTION: Ignoring converter type: org.apache.camel.fix.FixConverter as a
> dependent class could not be found: java.lang.NoClassDefFoundError:
> biz/c24/io/api/data/DataType
> java.lang.NoClassDefFoundError: biz/c24/io/api/data/DataType
> at java.lang.Class.getDeclaredMethods0(Native Method)
> at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
> at java.lang.Class.getDeclaredMethods(Class.java:1791)
> at
> org.apache.camel.impl.converter.AnnotationTypeConverterLoader.loadConverterMethods(AnnotationTypeConverterLoader.java:147)
> at
> org.apache.camel.impl.converter.AnnotationTypeConverterLoader.load(AnnotationTypeConverterLoader.java:78)
> at
> org.apache.camel.impl.converter.DefaultTypeConverter.checkLoaded(DefaultTypeConverter.java:260)
> at
> org.apache.camel.impl.converter.DefaultTypeConverter.convertTo(DefaultTypeConverter.java:95)
> at
> org.apache.camel.impl.converter.DefaultTypeConverter.convertTo(DefaultTypeConverter.java:71)
> at
> org.apache.camel.util.IntrospectionSupport.convert(IntrospectionSupport.java:263)
> at
> org.apache.camel.util.IntrospectionSupport.setProperty(IntrospectionSupport.java:221)
> at
> org.apache.camel.util.IntrospectionSupport.setProperties(IntrospectionSupport.java:188)
> at
> org.apache.camel.impl.DefaultComponent.setProperties(DefaultComponent.java:213)
> at
> org.apache.camel.component.file.GenericFileComponent.createEndpoint(GenericFileComponent.java:63)
> at
> org.apache.camel.component.file.GenericFileComponent.createEndpoint(GenericFileComponent.java:33)
> at
> org.apache.camel.impl.DefaultComponent.createEndpoint(DefaultComponent.java:81)
> at
> org.apache.camel.impl.DefaultCamelContext.getEndpoint(DefaultCamelContext.java:330)
> at
> org.apache.camel.util.CamelContextHelper.getMandatoryEndpoint(CamelContextHelper.java:54)
> at org.apache.camel.model.RouteType.resolveEndpoint(RouteType.java:96)
> at
> org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:106)
> at
> org.apache.camel.impl.DefaultRouteContext.resolveEndpoint(DefaultRouteContext.java:112)
> at org.apache.camel.model.FromType.resolveEndpoint(FromType.java:72)
> at
> org.apache.camel.impl.DefaultRouteContext.getEndpoint(DefaultRouteContext.java:81)
> at org.apache.camel.model.RouteType.addRoutes(RouteType.java:239)
> at org.apache.camel.model.RouteType.addRoutes(RouteType.java:86)
> at
> org.apache.camel.impl.DefaultCamelContext.startRouteDefinitions(DefaultCamelContext.java:661)
> at
> org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:651)
> at
> org.apache.camel.spring.SpringCamelContext.maybeDoStart(SpringCamelContext.java:166)
> at
> org.apache.camel.spring.SpringCamelContext.doStart(SpringCamelContext.java:161)
> at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:49)
> at
> org.apache.camel.spring.SpringCamelContext.maybeStart(SpringCamelContext.java:96)
> at
> org.apache.camel.spring.SpringCamelContext.onApplicationEvent(SpringCamelContext.java:115)
> at
> org.springframework.context.event.SimpleApplicationEventMulticaster$1.run(SimpleApplicationEventMulticaster.java:78)
> at
> org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:49)
> at
> org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:76)
> at
> org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:274)
> at
> org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:736)
> at
> org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:383)
> at
> org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
> at
> org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
> at
> org.apache.camel.spring.Main.createDefaultApplicationContext(Main.java:232)
> at org.apache.camel.spring.Main.doStart(Main.java:186)
> at org.apache.camel.impl.ServiceSupport.start(ServiceSupport.java:49)
> at org.apache.camel.util.MainSupport.run(MainSupport.java:121)
> at org.apache.camel.util.MainSupport.run(MainSupport.java:299)
> at org.apache.camel.spring.Main.main(Main.java:98)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> at java.lang.reflect.Method.invoke(Method.java:597)
> at org.apache.camel.maven.RunMojo$1.run(RunMojo.java:396)
> at java.lang.Thread.run(Thread.java:619)
> The org.apache.camel.fix.FixConverter class uses proprietary classes :
> import biz.c24.io.api.data.BooleanDataType;
> import biz.c24.io.api.data.CharDataType;
> import biz.c24.io.api.data.ComplexDataObject;
> import biz.c24.io.api.data.ComplexDataType;
> import biz.c24.io.api.data.DataType;
> import biz.c24.io.api.data.DateDataType;
> import biz.c24.io.api.data.Element;
> import biz.c24.io.api.data.IntDataType;
> import biz.c24.io.api.data.NumberDataType;
> import biz.c24.io.api.data.StringDataType;
> import biz.c24.io.api.presentation.TextualSource;
> import biz.c24.io.fix42.NewOrderSingleElement;
> Except if those classes are part of open source community but How can I use
> this component without Artix Data Service ?
> ex config :
> <route>
> <from uri="fixserver:banzai-to-camel.cfg" />
> <to uri="log:quickfix" />
> </route>
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.