I'm trying to upgrade from Camel 2.0 to 2.6
I have this in my applicationContext-camel.xml file...
<camel:route >
<camel:from uri="transactionSaleBuffer" />
<camel:policy ref="routeTransactionPolicy"/>
<camel:transacted ref="transactionManagerETL" />
<camel:to uri="detailFactProcessor" />
</camel:route>
by adding in the two lines in the middle (policy and transacted) I get the exception...
Caused by: org.apache.camel.FailedToCreateRouteException: Failed to create route route2 at: >>> From[transactionSaleBuffer] <<< in route: Route[[From[transactionSaleBuffer]] -> [Tr
ansacted[ref:trans... because of Route route2 has no output processors. You need to add outputs to the route such as to("log:foo").
I can see this is because the Camel class RouteDefinition.java makes a call to ProcessorDefinitionHelper.hasOutputs(outputs, true).
This passes in an array of one Object ([Transacted[ref:transactionManagerETL]])
This one object has one two children
[Transacted[ref:transactionManagerETL]]
CHILD-[Policy[ref:routeTransactionPolicy],
CHILD-To[detailFactProcessor]
The Policy child has no outputs, so the exception is thrown.
Yet I don't know how to add a child, my XML above matches the schema.
Maybe I'm missing something else?
My setup matches the example...Apache Camel: Book in One Page (See section: Camel 1.x - JMS Sample)
Can anyone please help me out.
Thanks!
Jeff Porter
Try as follows
<camel:route>
<camel:from uri="transactionSaleBuffer" />
<camel:transacted ref="transactionManagerETL" />
<camel:policy ref="routeTransactionPolicy">
<camel:to uri="detailFactProcessor" />
</camel:policy>
</camel:route>
Related
I am using payload-deserializer-transformer in my TCP client as follows.
<context:property-placeholder />
<int:gateway id="gw"
service-interface="myGateway"
default-request-channel="objectIn"
default-reply-channel="objectOut" />
<int-ip:tcp-connection-factory id="client"
type="client"
host="${client.server.TCP.host}"
port="${client.server.TCP.port}"
single-use="true"
so-timeout="10000" />
<int:channel id="objectIn" />
<int:payload-serializing-transformer input-channel="objectIn" output-channel="bytesOut"/>
<int:channel id="bytesOut" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="bytesOut"
reply-channel="bytesIn"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000" />
<int:channel id="bytesIn" />
<int:payload-deserializing-transformer input-channel="bytesIn" output-channel="objectOut" />
<int:channel id="objectOut" />
The above works fine for message length < 2048 but if the message exceeds this limit I get following error.
Caused by: java.io.IOException: CRLF not found before max message length: 2048
at org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer.fillToCrLf(ByteArrayCrLfSerializer.java:66)
at org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer.deserialize(ByteArrayCrLfSerializer.java:44)
at org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer.deserialize(ByteArrayCrLfSerializer.java:31)
at org.springframework.integration.ip.tcp.connection.TcpNetConnection.getPayload(TcpNetConnection.java:120)
at org.springframework.integration.ip.tcp.connection.TcpMessageMapper.toMessage(TcpMessageMapper.java:113)
at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:165)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
How can I set maxMessageSize property on the payload-deserializing-transformer in this case?
This has nothing to do with the transformer; the error is in the outbound gateway.
First of all, you should not be using text-based delimiting for inbound TCP messages; a serialized object contains binary data and might contain CRLF (0x0d0a) somewhere in the middle.
You should be using one of the binary-capable deserializers in the gateway.
You can read about TCP serializers/deserializers in the reference manual.
You should configure the outbound gateway to use a ByteArrayLengthHeaderSerializer in the serializer and deserializer attributes; it can handle binary payloads.
The remote system will also need to be changed to use a length header instead of using CRLF to detect the end of a message. If the remote system is also Spring Integration, simply change its serializer/deserializer too.
For other readers who are using text-based messaging, the ByteArrayCrlfSerializer can be configured with a maxMessageSize which defaults to 2048.
The ByteArrayLengthHeaderSerializer also has a maxMessageSize (also 2048) which is configurable - this is to prevent OOM conditions when a bad message is received.
I have several Spring-Integration elements configured in the XML file (see below)
From the amqp channel adapter the messages are directed to the router integrationSecondaryRouter that has implementation integrationRouterImpl.
If there is a not caught exception in integrationRouterImpl I expect that the Rabbit MQ will send the message again and again. However, this does not happen. The Rabbit MQ monitor does not show any messages accumulation. An error in my configuration?
<int-amqp:inbound-channel-adapter
channel="integrationFrontDoorQueueChannel"
queue-names="${integration.creation.orders.queue.name}"
header-mapper="integrationHeaderMapper"
connection-factory="connectionFactory"
error-channel="errorChannel"
/>
<int:chain
id="integrationFrontDoorQueueChain"
input-channel="integrationFrontDoorQueueChannel"
output-channel="integrationRouterChannel">
<int:transformer ref="integrationJsonPayloadTransformer" method="transformMessagePayload"/>
<int:filter ref="integrationNonDigitalCancellationFilter" method="filter"/>
<int:filter ref="integrationPartnerFilter" method="filter"/>
<int:filter ref="integrationOrderDtoDgcAndGoSelectFilter" method="filter"/>
</int:chain>
<int:header-value-router
id="integrationPrimaryRouter"
input-channel="integrationRouterChannel"
default-output-channel="integrationFrontDoorRouterChannel"
resolution-required="false"
header-name="#{T(com.smartdestinations.constants.SdiConstants).INTEGRATION_PAYLOAD_ACTION_HEADER_KEY}">
<int:mapping
value="#{T(com.smartdestinations.service.integration.dto.IntegrationAction).EXCLUSION_SCAN.name()}"
channel="integrationExclusionChannel"
/>
</int:header-value-router>
<int:router
id="integrationSecondaryRouter"
ref="integrationRouterImpl"
input-channel="integrationFrontDoorRouterChannel"
method="route"
resolution-required="false"
default-output-channel="nullChannel"
/>
Look, you have error-channel="errorChannel" and the Documentation on the matter points out:
The default "errorChannel" is a PublishSubscribeChannel.
Yes, there is one subscriber. but it just _org.springframework.integration.errorLogger.
Since there is no anyone who re-throws your exception to the SimpleMessageListenerContainer, thefore no reason to nack message and redelive it again.
We have a Mule Service running on a server. I am developing a stand alone Mule Client that connects directly into the Mule service.
When I run the client, I am receiving the below error:
ERROR 2015-09-23 10:36:02,724 [[cheetah-web-services].connector.http.mule.default.receiver.03] org.mule.exception.DefaultMessagingExceptionStrategy:
********************************************************************************
Message : Failed to transform from "byte[]" to "Object"
Type : org.mule.api.transformer.TransformerException
Code : MULE_ERROR-109
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transformer/TransformerException.html
Transformer : ByteArrayToMuleMessage{this=1574dd9, name='null', ignoreBadInput=false, returnClass=SimpleDataType{type=org.mule.api.MuleMessage, mimeType='*/*'}, sourceTypes=[SimpleDataType{type=[B, mimeType='*/*'}, SimpleDataType{type=java.io.InputStream, mimeType='*/*'}]}
********************************************************************************
Exception stack is:
1. com.mycompany.myapp.service.model.ServiceSearch; class invalid for deserialization (java.io.InvalidClassException)
java.io.ObjectStreamClass$ExceptionInfo:150 (null)
2. java.io.InvalidClassException: com.mycompany.myapp.service.model.ServiceSearch; class invalid for deserialization (org.apache.commons.lang.SerializationException)
org.mule.util.SerializationUtils:85 (null)
3. Failed to transform from "byte[]" to "Object" (org.mule.api.transformer.TransformerException)
org.mule.transformer.simple.ByteArrayToSerializable:54 (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transformer/TransformerException.html)
********************************************************************************
Root Exception stack trace:
java.io.InvalidClassException: com.mycompany.myapp.service.model.ServiceSearch; class invalid for deserialization
I have setup a remote dispatcher agent on the server.
<client:remote-dispatcher-agent>
<client:remote-endpoint address="http://localhost:20809" exchange-pattern="request-response" responseTimeout="10000"/>
I have created a separate mule client.
<client:remote-dispatcher-agent>
<client:remote-endpoint ref="remoteDispatcherChannel" />
<client:xml-wire-format/>
</client:remote-dispatcher-agent>
<http:endpoint name="remoteDispatcherChannel"
host="localhost"
port="20809"
path="_remoting"
exchange-pattern="request-response" />
Below is the Client Code. The ServiceSearch object implements all Serializable.
MuleClient muleClient = new MuleClient(true);
RemoteDispatcher dispatcher2 = muleClient.getRemoteDispatcher("http://127.0.0.1:20809/_remoting");
MuleMessage result = dispatcher2.sendToRemoteComponent("myAppServiceDelegate", ServiceSearch, msgMap);
Below is the Mule Service flow on the server I am trying to get into. I am coming in on the invoker step. I choice this step as I could sent the object directly to the service in the required format
<flow name="post:/service/search:my-web-services-config" initialState="started">
<logger level="INFO" doc:name="Log Request Properties" message="Request Type: #[message.inboundProperties.'http.method'], Request Path: #[message.inboundProperties.'http.request.path'], Request Params: #[message.inboundProperties.'http.query.params']" />
<json:json-to-object-transformer returnClass="com.mycompany.myapp.service.model.ServiceSearch" ignoreBadInput="true" mimeType="application/json" doc:name="Request JSON to ServiceSearch" />
<invoke object-ref="myappServiceDelegate" method="processSearch" methodArguments="#[payload],#[flowVars.'CLIENT_ID']" doc:name="Calling Search Delegate" />
<logger message="Generated DSL: #[payload.queryDSL]" level="INFO" doc:name="Log Query DSL" />
<flow-ref name="BigDataSearchFlow" doc:name="Big Data Flow" />
<exception-strategy ref="globalResponseExceptionStrategy" doc:name="Reference Exception Strategy" />
</flow>
I would appreciate some feedback on this approach and suggestions on what I should look for in the ServiceSearch object.
Russ
You are using an order/newer version of com.mycompany.myapp.service.model.ServiceSearch or none at all at the server side.
Please make sure both ends do have the very same version of the file.
Please share any links to configure activiti with camel. All examples I could get were showing SERVICETASK->CAMELROUTE->FILE and then FILE->RECIEVETASK(Activiti)
This involves some BUSINESS_KEY, which I couldn't figure out what exactly is
I need an example showing SERVICE TASK -> CAMEL ROUTE-> RECEIEVTASK(Signal the Activiti). I dont know why but this example gives me error
file: activiti-flow.bpmn20.xml:
<process id="camelprocess" name="My process" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<serviceTask id="servicetask1" name="Service Task" activiti:async="true" activiti:delegateExpression="${camel}"></serviceTask>
<receiveTask id="receivetask1" name="Receive Task"></receiveTask>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="servicetask1"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="servicetask1" targetRef="receivetask1"></sequenceFlow>
<sequenceFlow id="flow3" sourceRef="receivetask1" targetRef="endevent1"></sequenceFlow>
activiti-camel-spring.xml
<bean id="camel" class="org.activiti.camel.CamelBehaviour">
<constructor-arg index="0">
<list>
<bean class="org.activiti.camel.SimpleContextProvider">
<constructor-arg index="0" value="camelprocess" />
<constructor-arg index="1" ref="camelContext" />
</bean>
</list>
</constructor-arg>
</bean>
<camel:camelContext id="camelContext">
<camel:route>
<camel:from uri="activiti:camelprocess:servicetask1"/>
<camel:to uri="bean:serviceActivator?method=doSomething(${body})"/>
<camel:to uri="activiti:camelprocess:receivetask1"/>
</camel:route>
</camel:camelContext>
Error is:
1|ERROR|org.slf4j.helpers.MarkerIgnoringBase:161||||>> Failed delivery for (MessageId: ID-viscx73-PC-49557-1376961951564-0-1 on ExchangeId: ID-viscx73-PC-49557-1376961951564-0-2). Exhausted after delivery attempt: 1 caught: org.activiti.engine.ActivitiIllegalArgumentException: Business key is null
at org.activiti.engine.impl.ProcessInstanceQueryImpl.processInstanceBusinessKey(ProcessInstanceQueryImpl.java:87)
at org.activiti.camel.ActivitiProducer.findProcessInstanceId(ActivitiProducer.java:78)
at org.activiti.camel.ActivitiProducer.signal(ActivitiProducer.java:58)
at org.activiti.camel.ActivitiProducer.process(ActivitiProducer.java:49)
at org.apache.camel.util.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process (AsyncProcessorConverterHelper.java:61)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:73)
All forums/links that has ACTIVITI->CAMELROUTE(FILE) then
in other route CAMEL_FILE->RECIEVETASK
And they suggest to add some key like PROCESS_KEY_PROPERTY or PROCESS_ID_PROPERTY
I don't get where these properties fit into
I am trying to work it from example at link
http://bpmn20inaction.blogspot.in/2013/03/using-camel-routes-in-activiti-made.html
I am not sure whether process after giving service task to camel, is not moving at all to receive task and waiting up there or CAMEL is unable to find receive task
Please share some suggestion on this
Thanks
It worked by adding inbuilt camel queues as shown in the example. I thought they were just shown as example for various routes. But by passing to queue actually the ServiceTask was made asynchronous in camel and later from queue they were read and invoked the receive task in activiti
<camel:to uri="seda:tempQueue"/>
<camel:from uri="seda:tempQueue"/>
Thanks
I don't know whether you'd solved the problem or not, but actually I faced the same problem.
And finally, I found a solution of the problem.
In fact, it is correct that PROCESS_ID_PROPERTY property must be provided otherwise the activiti engine doesn't know to execute which process instance. So, I just set PROCESS_ID_PROPERTY value in the header when sending the JMS to activemq, and when the message back, just set the propertiy from header. Something likes:
from("activiti:process:simpleCall").setHeader("PROCESS_ID_PROPERTY", simple("${property.PROCESS_ID_PROPERTY}")).to("activemq:queue:request");
from("activemq:queue:reply").setProperty("PROCESS_ID_PROPERTY", simple("${header.PROCESS_ID_PROPERTY}")).to("activiti:process:simpleReceive");
Hope it will help you.
How can I represent this route in Camel's DSL:
<camel:camelContext id="camel-context">
<camel:route id="conductor-event" trace="true">
<camel:from uri="direct:conductor/event"/>
<camel:log message="handling conductor-event: id=${exchangeId}"/>
<!-- execute each filter in sorted order -->
<camel:bean ref="beaner.BProcessors"/>
<camel:log message="after: [bprocessors]: id=${exchangeId}"/>
<!-- map the event to a route -->
<camel:recipientList parallelProcessing="false">
<camel:method ref="beaner.Mappings" />
</camel:recipientList>
<camel:log message="after event mapping: id=${exchangeId}"/>
</camel:route>
</camel:camelContext>
I have this so far, but I get a "Caused by: java.net.URISyntaxException: Illegal character in scheme name at index 0: %7BCamelToEndpoint=...":
RouteDefinition routeDef = from("direct:conductor/event")
.log( "handling conductor-event: id=${exchangeId}" )
.beanRef( "beaner.BProcessors" )
.log( "after: [bprocessors]: id=${exchangeId}" );
ExpressionClause<RecipientListDefinition<RouteDefinition>> recipientList = routeDef.recipientList();
recipientList.properties().setParallelProcessing( false );
recipientList.method( "beaner.EventMappings" );
routeDef.log( "after event mapping: id=${exchangeId}" );
here is the route in JavaDSL...note that the recipientList parallelProcessing is false by default...
from("direct:conductor/event")
.log("handling conductor-event: id=${exchangeId}")
.beanRef("beaner.BProcessors")
.log("after: [bprocessors]: id=${exchangeId}")
.recipientList(bean("beaner.Mappings"))
.log("after event mapping: id=${exchangeId}");
You should use a RouteBuilder class in Java DSL to access the DSL.
Then inside the configure method you can build the routes almost identical as in XML DSL.
See the getting started guide here: http://camel.apache.org/walk-through-an-example.html