We have a requirement to service the GUI with a SI service. The GUI communicates with the backend over JMS queues, and will wait for a response on a tmp queue that is specified in the jms replyTo header property.
So there can be 10 gui's making queries to the backend, and receiving messages on their individual tmp queues.
So I wrote a SI service using inbound gateway that looks like this
<int:channel id="inChannel" />
<int:channel id="outChannel" />
<int-jms:inbound-gateway id="jmsSampleService" request-destination-name="TEST_QUEUE_2" request-channel="inChannel"
connection-factory="qpidJmsConnectionFactory" extract-request-payload="true" error-channel="errorChannel" />
<int:service-activator input-channel="inChannel" ref="sampleService2" method="processMessage" />
public class SampleService2 {
public Response processMessage(Object obj) throws Exception {
LOG.info("Message received on sample service. ");
Thread.sleep(5000);
Response response = new ResponseImpl();
response.setPayload("Test response");
return response;
}
This works fine, i can see the service return a message back on the jmsReplyTo queue. However, this is a single threaded synchronous operation which means unless GUI1 was serviced, GUI2 's call will be blocked. I want to do this asynchronously since this is simply a method call on a class.
We were doing something similar in mule
<flow name="sampleServiceFlow">
<jms:inbound-endpoint queue="TEST_QUEUE" connector-ref="queryQpidConnector" />
<byte-array-to-object-transformer />
<component>
<spring-object bean="sampleService" />
</component>
<object-to-byte-array-transformer />
<expression-filter evaluator="groovy"
expression="message.getOutboundProperty('replyToQueueName') != null" />
<jms:outbound-endpoint queue="#[header:OUTBOUND:replyToQueueName]" connector-ref="queryQpidConnector" />
</flow>
Since the mule service does not have any txns, it is able to simply consume a message in auto-ack, and have the SampleService's method call service the call.
Is there a way of implementing something like this in SI? perhaps by using the message-driven-channel-adapter? Is there a way to propagate jms header properties between channels?
Simply use concurrency on the inbound gateway. concurrent-consumers is the min max-concurrent-consumers (if specified) is the max; the adapter's container with adjust the concurrency depending on demand.
I am not sure what you mean by
Is there a way to propagate jms header properties between channels?
The jms headers are mapped to integration headers and vice-versa.
Related
I have following flows in my mule config .
<flow name="SimpleTest" processingStrategy="asynchronous">
<http:listener path="/orders/{id}" config-ref="myRequestConfig"
allowedMethods="GET" />
<set-payload value="SUCCESS" />
<flow-ref name="subFlowTest" />
<logger level="ERROR" message="value is : after subflow" />
</flow>
<sub-flow name="subFlowTest">
<scripting:component doc:name="sleep">
<scripting:script engine="groovy">
<scripting:text>
java.lang.Thread.sleep(5000);
</scripting:text>
</scripting:script>
</scripting:component>
</sub-flow>
It gives Unable to process a synchronous event asynchronously error . i want to call the subflow asynchronously , so if my parent flow is asyncronous , the subflow will automatically becomes asyncronous , correct ? so why am i getting this error ?
You can call your subflow asynchronously by using async message processor.
<async doc:name="Async">
<flow-ref name="subFlowTest" doc:name="Call Sub Flow"/>
</async>
HTTP endpoint makes a call to this flow through it automatically synchronous, so you have a conflict between your flow's strategy and its inbound endpoint. By definition, HTTP is synchronous.
Your problem lies on your understanding of HTTP.
Hope it helps.
/T
subflow semantic is more like a macro expansion than a function call. You don't call a subflow, but use a subflow to extract message processors into a different xml structure for readability. In runtime it is the same than if you copy all the message processors of the subflow and put them inside the flow.
Why would you execute your script component asynchronously?
I've upgraded from Mule 3.5.x to 3.6.x and since the old http transport is deprecated in 3.6.x I wanted to migrate to the new HTTP connector.
Here is the original code for calling my webservice:
<http:outbound-endpoint ref="OrderEndpoint" doc:name="GetApprovedOrder">
<cxf:jaxws-client serviceClass="com.acme.orders.IOrderServiceBean"
port="OrderServiceBean_v2_0Port"
operation="getApprovedOrderOp" />
</http:outbound-endpoint>
The point I have got to with the new connector is as follows:
<cxf:jaxws-client serviceClass="com.acme.orders.v2_0.IOrderServiceBean" port="OrderServiceBean_v2_0Port" operation="getApprovedOrderOp" />
<http:request config-ref="http.request.config" path="acme-services/OrderServiceBean_v2_0" method="POST" />
The issue that I have is that with the old version of the code, after calling the web service, the payload would be the response [java] object. With the new version of the code the payload is a org.glassfish.grizzly.utils.BufferInputStream containing the soap xml.
I could use a combination of xpath and a jaxb-xml-object-transformer to convert the contents of the stream to the response object, this just seems like a backwards step though.
I have looked into using the jaxws-client without the request and also at the ws-consumer, but my following requirements seems to rule these options out (unless I'm just misunderstanding how to use them).
I need to use the contract first method for calling the web services, see above where I have specified serviceClass rather than wsdl.
The web services use basic auth, therefore I need to specify a username and password.
I need to be able to specify the host and port (or at least the address) of the web service.
The solution is: wrap your element into a processor-chain
As follows:
<processor-chain>
<cxf:jaxws-client serviceClass="com.acme.orders.v2_0.IOrderServiceBean" port="OrderServiceBean_v2_0Port" operation="getApprovedOrderOp" />
<http:request config-ref="http.request.config" path="acme-services/OrderServiceBean_v2_0" method="POST" />
</processor-chain>
This is because cxf is intercepting, so after the processor chain you would have the same object as you had in your previous solution.
Is there a way to test a choice router for the following scenario which is based on the http.status? I am seeking a way to test the first condition of the router
<flow>
<choice>
<when expression="#[message.inboundProperties['http.status'] !=201">
......
<otherwise>
.....
</otherwise>
</choice>
</flow>
I want to verify that a javax.ws.rs.core.Response with can be correctly handled by the HTTP endpoint.
The flow doesn't have an inbound endpoint (thus it's a private flow) so to test it
create a test flow in a test XML config file that you will load side by side with your other Mule configuration XML files,
add an inbound VM endpoint to this test flow and make it call the private flow you want to test,
in your functional test case, use the Mule Client to dispatch a test message over the VM endpoint, setting properties on this test message that will end-up as inbound properties in the private flow.
I have a simple Mule flow where I receive an XML message via an HTTP endpoint and then do some processing on it. One of the first steps is to send the message via another outbound HTTP endpoint to a web service. The service just saves the message and does no processing on it. Therefore I effectively want to ignore the return value of the outbound endpoint and continue processing the message that was originally received. I tried making the endpoint on-way, but then my current Mule message becomes empty.
How do I call a endpoint, but ignore any return and continue processing with my original message?
You could use a <wiretap>: http://www.mulesoft.org/documentation/display/current/Routing+Message+Processors#RoutingMessageProcessors-WireTap
Or use <async> scope: http://www.mulesoft.org/documentation/display/current/Async+Scope+Reference
Or use an <enricher> if you want store the response in a variable but leave the current payload alone: http://www.mulesoft.org/documentation/display/current/Message+Enricher
Note that wiretap and enricher are synchronous and will block further processing where async won't.
In this case Async should be a better option.
Async in Mule helps to continue with the processing ignoring the results of the message processors called inside the async.
ex:
<flow name="sample" >
<http:inbound-endpoint ...... />
.... Some processing.....
<async>
<http:outbound-endpoint ....... />
</async>
...... Continue with the processing with the original message....
</flow>
Hope this helps.
I am reasonably experienced in BizTalk but new to the ESB Tool kit. We don't really have the need for an ESB solution as such but I would like to use the ESB Portal to display errors, modify messages and resubmit.
I have successfully, as far as I can tell, installed and configured the ESB tool kit correctly on my dev machine.
I have managed to send errors to the portal by enabling routing for failed messages and from within an Orchestration by creating a message thus: FaultMessage = Microsoft.Practices.ESB.ExceptionHandling.ExceptionMgmt.CreateFaultMessage();
The messages display correctly in the portal and on selecting 'Edit' I am given the option to resubmit via WCF OnRamp, SOAP OnRamp and HTTPReceive. This is where my problem starts. I have been using the WCF OnRamp to resubmit and on doing so I get a message:
This message has been successfully resubmitted
However on returning to the home screen of the portal I now have a new error for the Microsoft.Practices.ESB application:
There was a failure executing the receive pipeline: "Microsoft.Practices.ESB.Itinerary.Pipelines.ItinerarySelectReceiveXml, Microsoft.Practices.ESB.Itinerary.Pipelines, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Source: "ESB Itinerary Selector" Receive Port: "OnRamp.Itinerary" URI: "/ESB.ItineraryServices.WCF/ProcessItinerary.svc" Reason: Error 135008: The itinerary was not found in the repository.
I presume I need to configure something here, a resolver perhaps for my message but I, so far, have not been able to find a guide that will help me through this issue. Is there a walk through out there some where that shows the full end to end exception handling with ESB Portal? I have managed to find plenty of help with getting messages into it but not for configuring for resubmit. Thanks.
Coincidentally I was trying to make this work today as well...
If you set the Itinerary resolver connection string on the WCF OnRamp's receive pipeline component configuration to use ITINERARY-STATIC:\headerRequired=true; (instead of ITINERARY-STATIC:\headerRequired=false;), then you'll get the following message in the event viewer:
The itinerary name is required and was not provided
Meaning the Itinerary isn't present in the custom SOAP header.
I also traced the message going from the ESB.Portal using Fiddler (after turning off the Message security in both the ESB.Portal and the BizTalk receive location). No Itinerary custom SOAP header.
After going through the ESB.Portal code, I found the cause in MessageResubmitter.cs:
[Serializable]
public static class MessageResubmitter
{
/// <summary>
/// Submits an XML message to the WCF OnRamp. The URL of the WCF OnRamp is defined in the
/// portal web.config. Context properties are not resubmitted, they are expected to be
/// applied by the receiving pipeline.
/// </summary>
/// <param name="doc">The XML document to submit.</param>
/// <returns>True if the submission was successful, false if the submission failed.</returns>
public static bool ResubmitWCF(XmlDocument doc)
{
try
{
ProcessRequestClient onRamp = new ProcessRequestClient();
onRamp.SubmitRequest(**null**, doc.OuterXml);
return true;
}
catch (Exception)
{
return false;
}
}
The first argument of SubmitRequest is the Itinerary, which is set to null. This means the ESB.Portal does not resend the Itinerary as a custom SOAP header to BizTalk when you resubmit the message.
At the moment, I can think of the following options to make this work:
1) Create a (or modify the existing) generic WCF OnRamp to use the BRE to determine the Itinerary to be associated with the resubmitted message. This could however become complex, because you'll need to create your rules to be able to deal with any messages resubmitted from any step within your itineraries.
2) Modify the code of the ESB.Portal to be able to resend the Itinerary + current step as a Custom SOAP header.
I'm probably going for option 2.
The WCF OnRamp uses the ItinerarySelectReceiveXml pipeline this can be configured to point to an Itinerary or Business Rule and thus the message can be easily routed depending on its message type and content.
My issue now is that a third party got there before me on our installation so I am now looking into creating a new OnRamp and configuring the ESB portal to pick that up in its resubmit list.
We had a similar issue recently. While we were exporting our itineraries to a local database, and deploying them, the ESB would not be able to find the itineraries.
It turned out a consultant we had on site had modified the esb.config file in ESB Toolkit to look for itineraries on a server instead of the local machine.
So, if, like me, you are sure the itineraries are being exported to the right place and that they are deployed, modify the esb.config connection string.
<connectionStrings>
<add name="ItineraryDb" connectionString="Data Source=.;Initial Catalog=EsbItineraryDb;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionString>