[ 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.