i have a flow that works as follows:
<flow name="ChatListener">
<quartz:inbound-endpoint jobName="eventTimer"
repeatInterval="${chatListener.pollingInterval}">
<quartz:event-generator-job />
</quartz:inbound-endpoint>
<filter ref="ActiveTrainingFilter" />
<component>
<singleton-object class="com.ChatListener.ChatListener" />
</component>
<not-filter>
<payload-type-filter expectedType="org.mule.transport.NullPayload" />
</not-filter>
<collection-splitter />
<vm:outbound-endpoint path="ChatMsgs"
exchange-pattern="one-way" />
<default-exception-strategy>
<vm:outbound-endpoint path="ErrorMsgs"/>
</default-exception-strategy>
</flow>
Now, what is actually hapenning is that the generator calls the singleton compnent which does some DB retrieval and returns a collection of a java bean class which i later split (the null filter is in case i want to stop the flow).
My problem is - suppose i have an error connecting to the db and the component's oninitialise fails. What would keep the generator from trying to call the component over and over again? (and producing an error every time).
It looks to me as if i've handling something not quite right, So what would be the good to implement it to deal with exceptions?
Any ideas? thanks in advance!
I would try the following:
Declare the quartz endpoint in a global manner,
Use it in the flow.
Create a custom exception strategy and use it in the flow too.
Inject the global quartz endpoint in this custom exception strategy.
In this strategy, if the exception caught is one you deem characteristic to unrecoverable failure, call endpoint.stop().
You would need to go through JMX to restart the endpoint after clearing the error condition.
Related
I am trying to send and receive message to and from JMS topics.
<testcase name="DeliveryToPT3PLIT">
...
<actions>
...
<send endpoint="fromEndpoint">
<message>
<resource file="com/roche/icc/citrus/messages/input/PT-3PLWoBatchSplit.xml"/>
</message>
<header>
...
</header>
</send>
<receive endpoint="toEndpoint">
<description>Receive asynchronous message from topic</description>
<message>
<resource file="com/roche/icc/citrus/messages/output/PT-3PLWoBatchSplit.xml"/>
</message>
<header>
...
</header>
</receive>
</actions>
</testcase>
It seems that these operations go one after another. The problem is that my application works really fast and when I send a message to first topic it appears on "toEndpoint" almost immediately. So the receive operation does not manage to catch appropriate message since it has been already processed.
Is there any way to make this operations simultaneously?
Regards
There is one thing to note about using JMS topics, because they work in a publish/subscribe manner, you have to subscribe first in order to receive the message.
That means you need to subscribe to the topic before a message is going to be published. Also, if you say that your application is fast, you may need to wait a few millis before sending the message. Here is a Java DSL example of what I think may work for you. (Note: I have tested this example with a JMS topic)
parallel().actions(
sequential().actions( // Thread #1
...
receive(action -> action.endpoint(toEndpoint).payload("message to be received"))),
sequential().actions( // Thread #2
sleep(500),
send(action -> action.endpoint(fromEndpoint).payload("message to be sent"))));
Notice the parallel() action container. It will execute every action inside it in a separate thread. Each sequential() represents a series of actions that allows you to group them together. Because both sequential() containers are inside the parallel(), the actions inside each of them will be executed on different threads.
So what happens here: you split your actions on two threads. On the first thread you wait for a message. On the second thread, you make it sleep for 500 millis first, after which you send the message.
I'm sorry that I don't have an XML example, but I hope this helps anyway.
Also don't forget to set the pub-sub-domain property to true on your endpoints. See the Citrus documentation on JMS topics: here.
Input:-
<balanceInquiry>
<request>
<amount>
<amount>5.0</amount>
<currency/>
</amount>
</request>
</balanceInquiry>
<balanceInquiry>
<request>
<amount>
<amount>10.0</amount>
<currency/>
</amount>
</request>
</balanceInquiry>
<balanceInquiry>
<request>
<amount>
<amount>57.0</amount>
<currency/>
</amount>
</request>
</balanceInquiry>
I am trying to hit a SOAP webservice using the above input, but the webservice can only accept one balanceInquiry request at once. So I am spliting the request into different balanceInquiry using splitter. but if the status of 1st request is success then I have to go for 2nd and so on. If anyone of them fails then I need to rollback all the previous transaction. there is a attribute which can be "success" or "fail" depending on the request.
So I want to know if there is any component to achieve this in mule? Please suggest.
I believe you should take a look at the foreach documentation. https://docs.mulesoft.com/mule-user-guide/v/3.7/foreach and the exception handling strategy ; https://docs.mulesoft.com/mule-user-guide/v/3.7/error-handling.
If your 3 inquiries are in the same message and that you are using the default exception strategy, it will rollback the previous transactions... assuming you are writing the SOAP responses in a database using a DB connector.
Since I don't know exactly what you wish to do in your transaction, here's another interesting link : https://docs.mulesoft.com/mule-user-guide/v/3.7/rollback-exception-strategy
I'm building an exception handler for a jboss/camel project. Catching the exception with an onException clause works, and I can access the caught exception from a bean, but that work's only directly in exception handler. Since I need this handler in multiple different projects, I want to direct from the handler to a different route (in a different context), and handle the exception there centrally. But after the routing, the caught exception is not accessible any longer. Why is this, and how can I fix that. I'd like not to have to add another EJB to all of my projects.
Code:
<camelContext id="project1Context" xmlns="http://camel.apache.org/schema/spring">
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<bean ref="projectSpecificBean" method="peekException" />
<to uri="activemq:queue:centralExceptionHandling" />
</onException>
[... the routes of the context, where the exception happens ...]
</camelContext>
In the bean:
public void peekException(Exchange camelExchange) {
Exception e = camelExchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
log.warn("Caught general Exception", e);
}
This gives me access to the Exception inside the bean. But when I remove the <bean ref="projectSpecificBean" method="peekException" /> from the onException clause and add the same thing to the route at activemq:queue:centralExceptionHandling (to a bean local to that project there, in a different camelContext), I cannot find the exception anywhere in the exchange.
To be able to receive exception on the client of ActiveMQ queue you need use camel jms component option "transferExchange". This option must be enabled on both sides (during sending to ActiveMQ queue and receiving from it). In that case not only message body/headers will be sent but whole exchange will be transfered. See http://camel.apache.org/jms.html (transferExchange option). In general it will then looks like there are no queue between exception route and exception handler route. Here are some details from documentation:
You can transfer the exchange over the wire instead of just the body and headers. The following fields are transferred: In body, Out body, Fault body, In headers, Out headers, Fault headers, exchange properties, exchange exception. This requires that the objects are serializable. Camel will exclude any non-serializable objects and log it at WARN level. You must enable this option on both the producer and consumer side, so Camel knows the payloads is an Exchange and not a regular payload.
Example of code:
<camelContext id="project1Context" xmlns="http://camel.apache.org/schema/spring">
<onException>
<exception>java.lang.Exception</exception>
<handled>
<constant>true</constant>
</handled>
<bean ref="projectSpecificBean" method="peekException" />
<to uri="activemq:queue:centralExceptionHandling?transferExchange=true" />
</onException>
[... the routes of the context, where the exception happens ...]
</camelContext>
// Somewhere in the central exception handler.
<camelContext id="exceptionHandlerContext" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="activemq:queue:centralExceptionHandling?transferExchange=true" />
<!-- Here you will have almost completely the same exchange as it was before it was sent to ActiveMq -->
</route>
</camelContext>
I'm face with a situation where we cannot use schema to validate incoming request (basically schema is there but it accepts any String in request, wsdl designers have their own reasons to do that to accept request from different sources and flexibility). But when the request is received, I validate that the child element of request wrapper is what we expect (using XPath for that). Now if the child element is not what expected, I'd like to throw Soap Fault with Client code and may be include error message that schema validation failed, request doesn't contain valid element.
I'm using Mule 3.3 and doing my XPath validation in <choice> element and I want to throw exception in <otherwise> block.
Is there a way to throw Soap Fault manually in mule flow and
How to add custom fault string. I'm not sure if an outInterceptor will solve the purpose as I'm not using schemaValidation attribute of <cxf:proxyService>.
Here is part of my flow
<http:inbound-endpoint address="${service.address}" exchange-pattern="request-response">
<cxf:proxy-service wsdlLocation="classpath:service.wsdl" namespace="http://company.com/services/service" service="CompanyService" />
</http:inbound-endpoint>
<choice>
<when>.....</when>
<otherwise><!-- Here I want to throw Soap Fault ---></otherwise>
</choice>
<catch-exception-strategy>
<flow-ref name="generateErrorResponse" />
</catch-exception-strategy>
Since you are using a cxf:proxy-service you have complete control on the response. For example, if you add the following in your otherwise block, you'll be able to create whatever SOAP fault you want:
<expression-component><![CDATA[
message.payload = '<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
+ '<faultcode>A code</faultcode><faultstring>A string</faultstring>'
+ '</soap:Fault>';
]]></expression-component>
I have 2 custom actions exectuting one after the other in the same service like this
<actions mep="RequestResponse">
<action name="ActionA" class="ClassA"/>
<action name="ActionB" class="ClassB"/>
</actions>
Suppose that ActionA does some validations over the received msg. If the validations found that the msg is invalid, how does you send a response to the invoker about that failure?
Right now in my actions I set the response in the message at ActionA and put a mark in it indicating that I found an error in ActionA and ActionB checks for that mark before executing its code. I found this method useful but a burden because all of my actions have to start with:
if (!markIspressent) {
//Code goes here
}
return message.
I have tried setting the response msg at ActionA and returning null to stop the pipeline but that isn't working. I also tried another method that I found of throwing an ActionProcessingFaultException(message,"SomeTextGoesInHere") but that also isn't working.
My main problem with this second one is that the ESB tries to reprocess the msg that thrown that exception and I don't see the response that I set into message until the ESB gives up and sends it back. But that giving up takes up to 60s.
So my question is how can you send a response msg to the invoker before reaching up the end of the service pipeline.
Thanks
The options in finishing earlier the pipeline are:
- return null;
- split the service into three (note service 1 is OneWay and based on your action's results routes to the appropriate service)
Service 1
<actions mep="OneWay">
<action name="ActionA" class="ClassA"/>
<action name="ActionA1" class="RouteBasedOnMsgContentTo(Service 2 or Service 3)"/>
</actions>
Service 2
<actions mep="RequestResponse">
<action name="ActionB" class="ClassB"/>
</actions>
Service 3
<actions mep="RequestResponse">
<action name="ActionC" class="ClassC-SimplyRespondsTheProblem"/>
</actions>