How to send a response to the invoker of a service without reaching the end of the pipeline - jboss-esb

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>

Related

Send out 1 email after all Oozie jobs finish

So far, I've been using oozie email actions to send out email enriched with some information, when submitting job in our hadoop cluster :
<workflow-app name="[WF-DEF-NAME]" xmlns="uri:oozie:workflow:0.1">
...
<action name="[NODE-NAME]">
<email xmlns="uri:oozie:email-action:0.2">
<to>[COMMA-SEPARATED-TO-ADDRESSES]</to>
<cc>[COMMA-SEPARATED-CC-ADDRESSES]</cc> <!-- cc is optional -->
<subject>[SUBJECT]</subject>
<body>[BODY]</body>
<content_type>[CONTENT-TYPE]</content_type> <!-- content_type is optional -->
<attachment>[COMMA-SEPARATED-HDFS-FILE-PATHS]</attachment> <!-- attachment is optional -->
</email>
<ok to="[NODE-NAME]"/>
<error to="[NODE-NAME]"/>
</action>
...
</workflow-app>
This is for sending out emails after each submitted workflows.
Let's say i have 560 jobs running and instead of receiving 560 emails, i would like to receive only 1 single email that will contain a sum up of what happened in that specific business day ( successes, failures etc..)
I am not finding any solution on how to implement this.
Has anyone already tried something like that, and if yes, could you please point me to some possible approach to this idea?
Please comment out if what i am trying to achieve is not clear enough,
Thanks

Simultanous sending and receiving

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.

Camel and CXF: How to get the outbound message?

I have this camel route:
from("cxf:bean:endpointDocs01?loggingFeatureEnabled=true")
.to("direct:CBR")
.transform().method(WebServiceUtils.class,"response()")
.log("Outbound message: ${body}");
endpointDocs01 is defined in the blueprint like this:
<cxf:cxfEndpoint address="/documentos/" id="endpointDocs01"
serviceClass="com.adelco.webservice.ServiceDocs" wsdlURL="wsdl/wsdl03.wsdl">
<cxf:properties>
<entry key="schema-validation-enabled" value="true"/>
</cxf:properties>
</cxf:cxfEndpoint>
This route works with no problems including the schema-validation.
When I send a correct request, I can do "things" (in this case logging) using the last line of the exchange ".log("Outbound message: ${body}". In this case, the log shows this:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<outputDocumento xmlns="http://webservice.adelco.com">
<respuesta>0</respuesta>
<mensaje>El mensaje [113282] fue recibido. Fecha recepciĆ³n Wed Apr 12 17:01:11 CLT 2017</mensaje>
</outputDocumento>
</soap:Body>
</soap:Envelope>
But, when I send a incorrect request, the line ".log("Log outbound message: ${body}" does nothing. However I get a response in the client (a Soap:Fault response)
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<soap:Fault>
<faultcode>soap:Client</faultcode>
<faultstring>Unmarshalling Error: cvc-complex-type.2.4.a: Invalid content was found starting with element 'Sociedad'. One of '{"http://webservice.adelco.com":TipoMovimiento}' is expected.</faultstring>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Why this soap:Fault response in not logged?
Your route is invoked after unmarshalling. So if unmarshalling fails because of invalid input, the route does not trigger and does not log.
Read this article about CXF architecture.
Phase Interceptors
CXF provides an InterceptorChain implementation called the PhaseInterceptorChain. [...]
Let us take a hypothetical simplified example (NOTE: these phases and interceptors don't necessarily exist in CXF). Let us say we are parsing a SOAP message. We may want to have two phases. First, a dispatch phase which parses the soap headers and determines which service to route the Message to. Second, an unmarshal phase which binds the SOAP body to JAXB objects.
Fault Handling
At any point during processing, an interceptor may throw a Fault, or a derivative of a Fault like the SoapFault. This will cause the chain to stop invoking and unwind it. Unwinding consists of calling handleFault on each interceptor that was invoked in reverse order.
When a Fault occurs the processing is stopped and the interceptor chain unwinded. CXF uses different chains for messages (in & out) and Faults (in & out).
To use custom beans (which must implement PhaseInterceptor interface) as interceptors:
<cxf:cxfEndpoint address="/documentos/" id="endpointDocs01"
serviceClass="com.adelco.webservice.ServiceDocs" wsdlURL="wsdl/wsdl03.wsdl">
<cxf:properties>
<entry key="schema-validation-enabled" value="true"/>
</cxf:properties>
<cxf:inInterceptors>
<ref component-id="inInterceptorBean" />
</cxf:inInterceptors>
<cxf:outInterceptors>
<ref component-id="outInterceptorBean" />
</cxf:outInterceptors>
<cxf:outFaultInterceptors>
<ref component-id="outFaultInterceptorBean" />
</cxf:outFaultInterceptors>
</cxf:cxfEndpoint>
As #Allesandro has said, the chain would unwind on failure.
You could've added an onException clause:
onException(ValidationException.class)
.log("Outbound message: ${body}");
from("cxf:bean:endpointDocs01?loggingFeatureEnabled=true")
.to("direct:CBR")
.transform().method(WebServiceUtils.class,"response()")
.log("Outbound message: ${body}");

How to throw Soap Fault manually in mule

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>

Quartz Generator and exception handling

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.