Mule ESB - Configure Multiple Components in same Flow - java

I am getting an error message when trying to add a Spring component to a Mule Flow. This should be a common user-case, but I wasn't able to find the right documentation or examples. Thanks in advance.
The follow was the original configuration and works fine:
<flow name="ApplicationEndpoint">
<inbound-endpoint address="server:port/JSONAPI/"/>
<jersey:resources>
<component>
<spring-object bean="myJerseyService"/>
</component>
</jersey:resources>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<flow-ref name="ErrorHandling" doc:name="Flow Reference"/>
</catch-exception-strategy>
</flow>
I simply want to add a new component to do some post-processing. When I try this, it doesn't work:
<flow name="ApplicationEndpoint">
<inbound-endpoint address="server:port/JSONAPI/"/>
<jersey:resources>
<component>
<spring-object bean="myJerseyService"/>
</component>
</jersey:resources>
<component>
<spring-object bean="postProcessor"/>
<component>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<flow-ref name="ErrorHandling" doc:name="Flow Reference"/>
</catch-exception-strategy>
</flow>
Where "postProcessor" maps elsewhere in the config as a spring bean.
The error message I get is:
org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'component'. One of '{"http://www.mulesoft.org/schema/mule/core":abstract-lifecycle-adapter-factory, "http://www.mulesoft.org/schema/mule/core":binding}' is expected.

The above error clearly shows that the tag <component> is not closed..
for example, it should be in following format :-
<component>
<spring-object bean="postProcessor"/>
</component>
where you need to end the tag like the following :- </component>
One more thing ... I tried to run your code, but due to server:port/JSONAPI/ configured in your inbound-endpoint address it gives a error saying the xml is malformed
So I modified your code as following and it ran successfully :-
<flow name="ApplicationEndpoint">
<inbound-endpoint address="http://localhost:8189/JSONAPI"/>
<jersey:resources>
<component>
<spring-object bean="myJerseyService"/>
</component>
</jersey:resources>
<component>
<spring-object bean="postProcessor"/>
</component>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<flow-ref name="ErrorHandling" doc:name="Flow Reference"/>
</catch-exception-strategy>
</flow>
So, you can now use it and modify as per your requirement

Related

Mule: Interface binding for different components, how to avoid duplication?

We have the following mule flow:
<flow name="mule-flow-1">
<component>
<spring-object bean="springBean_1"/>
<binding interface="com.acme.EmailService" method="send">
<vm:outbound-endpoint path="send-email" exchange-pattern="one-way"/>
</binding>
</component>
</flow>
but right now we want to introduce new flow, with new Spring bean which uses the same EmailService.send method, so, we can do it as:
<flow name="mule-flow-2">
<component>
<spring-object bean="springBean_2"/>
<binding interface="com.acme.EmailService" method="send">
<vm:outbound-endpoint path="send-email" exchange-pattern="one-way"/>
</binding>
</component>
</flow>
As you can see, we bound EmailService.send method twice in two different flows and it is pure code duplication.
Is it possible to bind EmailService.send method somewhere in common place and just use ref in mule-flow-1 and mule-flow-2?
maybe you can use subflow? Define your component there and then use flow-ref in any flow you want to reuse it.
<sub-flow name="mule-flow-send">
<component>
<spring-object bean="springBean_1"/>
<binding interface="com.acme.EmailService" method="send">
<vm:outbound-endpoint path="send-email" exchange-pattern="one-way"/>
</binding>
</component>
</sub-flow>
and then reusing:
<flow name="mule-flow-1">
<flow-ref name="mule-flow-send" doc:name="mule-flow-send"/>
</flow>
<flow name="mule-flow-2">
<flow-ref name="mule-flow-send" doc:name="mule-flow-send"/>
</flow>

Mule vm:inbound-endpoint not triggered

I have a list which I want to process in paraller, so after calling collection-splitter, I post each record to an outbound-endpoint, but the receiving inbound-endpoint is not been triggered.
Configuration below;
<flow name="ProcessPolledOrders" doc:name="ProcessPolledOrders">
<set-session-variable variableName="fileName" value="#[message.payload.orderBatch.orderSourceName]" />
<set-session-variable variableName="batchId" value="#[message.payload.orderBatch.id]" />
<logger message="************* Item: #[sessionVars.fileName] processing resumed. ***********" level="INFO"/>
<component>
<spring-object bean="PolledOrderSplitter"/>
</component>
<set-session-variable variableName="size" value="#[message.payload.size()"/>
<collection-splitter/>
<set-property propertyName="MULE_CORRELATION_GROUP_SIZE" value="#[sessionVars.size]" />
<set-property propertyName="MULE_CORRELATION_ID" value="#[sessionVars.fileName]" />
<choice>
<when>
<payload-type-filter expectedType="model.Order"/>
<vm:outbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
</when>
<otherwise>
<echo-component/>
</otherwise>
</choice>
</flow>
<flow name="PollerOrderProcessingFlow" doc:name="PollerOrderProcessingFlow">
<vm:inbound-endpoint exchange-pattern="one-way" path="step2" doc:name="VM"/>
<logger message="***************** Validating order with id #[message.payload.id] ********************"
level="INFO"/>
<component>
<spring-object bean="PolledOrderValidationComponent"/>
</component>
<collection-aggregator timeout="600000" failOnTimeout="false"
doc:name="Validated Orders Aggregator"/>
<component>
<spring-object bean="BatchOrderUpdateComponent"/>
</component>
<default-exception-strategy>
<flow-ref name="ValidationProcessingExceptionFlow" />
</default-exception-strategy>
</flow>
Are you getting any exception? try to debug and see where the message dropping? I tried similar flow and working fine for me.

Transform Http Response to object mule esb

Im doing a sample bookstore. When the user has booked a order, the system send him an email with the dates from the order. The system send the email but it shows the next error:
Root Exception stack trace:
java.lang.IllegalArgumentException: Cannot apply transformer HttpClientMethodResponseToObject{this=6911a11b, name='HttpClientMethodResponseToPedido', ignoreBadInput=false, returnClass=SimpleDataType{type=org.mule.entities.Pedido, mimeType='text/html'}, sourceTypes=[SimpleDataType{type=org.apache.commons.httpclient.HttpMethod, mimeType='*/*'}]} on source payload: class org.mule.transport.http.HttpResponse
at org.mule.DefaultMuleMessage.applyAllTransformers(DefaultMuleMessage.java:1427)
at org.mule.DefaultMuleMessage.applyTransformers(DefaultMuleMessage.java:1379)
at org.mule.DefaultMuleMessage.applyTransformers(DefaultMuleMessage.java:1371)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
My XML is the next:
<smtp:gmail-connector name="Gmail" validateConnections="true" doc:name="Gmail" contentType="text/html" />
<flow name="Email" doc:name="Email">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" doc:name="HTTP" path="Email"/>
<http:static-resource-handler resourceBase="docroot" defaultFile="index.html" doc:name="HTTP Static Resource Handler"/>
</flow>
<flow name="Correo" doc:name="Correo">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="Facturacion" doc:name="HTTP" transformer-refs="Java"/>
<component doc:name="Generar Pedido" class="org.mule.components.GenerarPedido"/>
<smtp:outbound-endpoint host="smtp.gmail.com" port="587" user="email%40gmail.com" password="pass" connector-ref="Gmail" to="#[payload.email]" from="BookStore S.A." responseTimeout="10000" doc:name="SMTP" transformer-refs="Java1" mimeType="text/html"/>
<http:response-builder status="200" contentType="text/html" doc:name="HTTP Response Builder"/>
<http:http-response-to-object-transformer returnClass="org.mule.entities.Pedido" encoding="UTF-8" mimeType="text/html" doc:name="HTTP Response to Object"/>
</flow>
Anyone can help me?
Your payload is not a HTTP response, so you cannot use the http-response-to-object-transformer. This is used after calling an http:outbound-endpoint which returns a 'HTTP response'.

MULE ESB - simple jaxws client don't work ... - Message payload is of type: ContentLengthInputStream

Hi guys first of all I want you to see my wsdl file it's DHL24 api I want learn a bit on this and use simple example here is the link https://dhl24.com.pl/webapi.html
I want to use getVersion as you can see we don't need to provide any data to this only in response we have getVersionResult - STRING
First of all I created package generated from apache CTX using simple project here is POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>pl.test</groupId>
<artifactId>DhlServiceClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<apache.cxf-version>2.5.9</apache.cxf-version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${apache.cxf-version}</version>
<executions>
<execution>
<id>Wsdl2Java - gasShopService.wsdl</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${basedir}/src/main/java/</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/dhlService.wsdl</wsdl>
<extraargs>
<extraarg>-client</extraarg>
<extraarg>-autoNameResolution</extraarg>
<extraarg>-p</extraarg>
<extraarg>pl.test</extraarg>
<extraarg>-aer=false</extraarg>
<extraarg>-verbose</extraarg>
<extraarg>-frontend</extraarg>
<extraarg>jaxws21</extraarg>
<extraarg>-wsdlLocation </extraarg>
<extraarg>classpath:dhlService.wsdl</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
All is fine here I have package and classes so I start to create second project (as dependency I added this package - this works fine)
Now I want to create simple flow:
<flow name="getVersion" doc:name="getVersion">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="getVersion" doc:name="HTTP"/>
<logger doc:name="getVersion" message="Test Before" level="ERROR"/>
<cxf:jaxws-client operation="getVersion" clientClass="pl.test.integration.dhl.ws.client.DHL24WebapiService" port="DHL24WebapiPort" enableMuleSoapHeaders="true" doc:name="SOAP">
</cxf:jaxws-client>
<logger doc:name="getVersion" message="Test after" level="ERROR"/>
</flow>
Nothing big but when I post to this I have:
ERROR 2014-06-28 20:36:10,289
[[gaspoldhlservice].connector.http.mule.default.receiver.02]
org.mule.api.processor.LoggerMessageProcessor: Test Before ERROR
2014-06-28 20:36:10,291
[[gaspoldhlservice].connector.http.mule.default.receiver.02]
org.mule.exception.DefaultMessagingExceptionStrategy:
**************************************************************************** Message : wrong number of arguments. Failed to route
event via endpoint: org.mule.module.cxf.CxfOutboundMessageProcessor.
Message payload is of type: ContentLengthInputStream Code
: MULE_ERROR--2
-------------------------------------------------------------------------------- Exception stack is:
1. wrong number of arguments (java.lang.IllegalArgumentException) sun.reflect.NativeMethodAccessorImpl:-2 (null)
2. wrong number of arguments. Failed to route event via endpoint: org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
type: ContentLengthInputStream
(org.mule.api.transport.DispatchException)
org.mule.module.cxf.CxfOutboundMessageProcessor:150
-------------------------------------------------------------------------------- Root Exception stack trace: java.lang.IllegalArgumentException: wrong
number of arguments at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
I was searching a bit in google and found something like this. I add after inbound:
<object-to-byte-array-transformer />
And I had other error:
ERROR 2014-06-28 20:45:18,149
[[gaspoldhlservice].connector.http.mule.default.receiver.02]
org.mule.api.processor.LoggerMessageProcessor: Test Before ERROR
2014-06-28 20:45:18,151
[[gaspoldhlservice].connector.http.mule.default.receiver.02]
org.mule.exception.DefaultMessagingExceptionStrategy:
**************************************************************************** Message : wrong number of arguments. Failed to route
event via endpoint: org.mule.module.cxf.CxfOutboundMessageProcessor.
Message payload is of type: byte[] Code :
MULE_ERROR--2
-------------------------------------------------------------------------------- Exception stack is:
1. wrong number of arguments (java.lang.IllegalArgumentException) sun.reflect.NativeMethodAccessorImpl:-2 (null)
2. wrong number of arguments. Failed to route event via endpoint: org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
type: byte[] (org.mule.api.transport.DispatchException)
org.mule.module.cxf.CxfOutboundMessageProcessor:150
-------------------------------------------------------------------------------- Root Exception stack trace: java.lang.IllegalArgumentException: wrong
number of arguments at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
I need a little bit push here its very simple method and I cant handle it right ...
AFTER EDIT:
Changed to your flow with:
<flow name="getVersion" doc:name="getVersion">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="getVersion" doc:name="HTTP"/>
<cxf:jaxws-client operation="getVersion" serviceClass="pl.test.integration.dhl.ws.client.DHL24WebapiService" port="DHL24WebapiPort" enableMuleSoapHeaders="true" doc:name="SOAP">
</cxf:jaxws-client>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8088/consumeTest" doc:name="HTTP" method="POST"/>
</flow>
<flow name="consumeTest" doc:name="consumeTest">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="consumeTest" doc:name="HTTP"/>
<logger doc:name="getVersion" message="Test AFTER" level="ERROR"/>
</flow>
Answer is
No such operation: getVersion. Failed to route event via endpoint:
org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
type: ContentLengthInputStream
When I use clientClass instead of serviceClass:
wrong number of arguments. Failed to route event via endpoint:
org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
type: ContentLengthInputStream
You need to put an outbound endpoint after cxf:jaxws-client like
<http:outbound-endpoint exchange-pattern="request-response" address="Your external webservice path that you are tying to consume " doc:name="HTTP" method="POST"/> to post the value to the external webservice ..
for example If your external webservice is at http://localhost:8086/mainData?wsdl then you need to put
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8086/mainData" doc:name="HTTP" method="POST"/> ................ and one more thing ... could you plase change
<cxf:jaxws-client operation="getVersion" clientClass="pl.execon.integration.dhl.ws.client.DHL24WebapiService" port="DHL24WebapiPort" enableMuleSoapHeaders="true" doc:name="SOAP"> to
`<cxf:jaxws-client operation="getVersion" serviceClass="pl.execon.integration.dhl.ws.client.DHL24WebapiService" port="DHL24WebapiPort" enableMuleSoapHeaders="true" doc:name="SOAP">` in your flow and try ...
So the final flow would be something like :-
<flow name="getVersion" doc:name="getVersion">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="getVersion" doc:name="HTTP"/>
<cxf:jaxws-client operation="getVersion" serviceClass="pl.execon.integration.dhl.ws.client.DHL24WebapiService" port="DHL24WebapiPort" enableMuleSoapHeaders="true" doc:name="SOAP">
</cxf:jaxws-client>
<http:outbound-endpoint exchange-pattern="request-response" address="Your external webservice path that you are tying to consume " doc:name="HTTP" method="POST"/>
</flow>
AFTER EDIT:
Changed to your flow with:
<flow name="getVersion" doc:name="getVersion">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="getVersion" doc:name="HTTP"/>
<cxf:jaxws-client operation="getVersion" serviceClass="pl.test.integration.dhl.ws.client.DHL24WebapiService" port="DHL24WebapiPort" enableMuleSoapHeaders="true" doc:name="SOAP">
</cxf:jaxws-client>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:8088/consumeTest" doc:name="HTTP" method="POST"/>
</flow>
<flow name="consumeTest" doc:name="consumeTest">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8088" path="consumeTest" doc:name="HTTP"/>
<logger doc:name="getVersion" message="Test AFTER" level="ERROR"/>
</flow>
Answer is
No such operation: getVersion. Failed to route event via endpoint:
org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
type: ContentLengthInputStream
When I use clientClass instead of serviceClass:
wrong number of arguments. Failed to route event via endpoint:
org.mule.module.cxf.CxfOutboundMessageProcessor. Message payload is of
type: ContentLengthInputStream

How to filter a single URI from a group of URI's in a Mule inbound endpoint?

I have the following code to configure a Jersey service at "http://localhost:8080/alpha":
*** my mule config ***
<flow name="flow1">
<inbound-endpoint address="http://localhost:8080/" exchange-pattern="request-response" />
<jersey:resources>
<component>
<singleton-object class="com.address.Flow1Resource"/>
</component>
</jersey:resources>
</flow>
*** Flow1Resource.java ***
#Path("/alpha")
public class Flow1Resource {...}
I want to add a new inbound-endpoint that handles all the addresses under "http://localhost:8080" except "http://localhost:8080/alpha" (e.g. "http://localhost:8080/beta"). These new addresses need a single jersey resource. For example:
*** my mule config ***
<flow name="flow1">
<inbound-endpoint address="http://localhost:8080/" exchange-pattern="request-response" />
<jersey:resources>
<component>
<singleton-object class="com.address.Flow1Resource"/>
</component>
</jersey:resources>
</flow>
<flow name="flow2">
<inbound-endpoint address="http://localhost:8080/*" exchange-pattern="request-response" />
<jersey:resources>
<component>
<singleton-object class="com.address.Flow2Resource"/>
</component>
</jersey:resources>
</flow>
*** Flow1Resource.java ***
#Path("/alpha")
public class Flow1Resource {...}
*** Flow2Resource.java ***
#Path("/")
public class Flow2Resource {
#Path("beta")
public void beta() {...}
#Path("gamma")
public void gamma() {...}
...
}
How do I set up the mule inbound-endpoint to capture all the addresses (i.e. beta & gamma), except for a specific url (i.e. alpha).
I know that I can hardcode the paths in the mule config, but this would result in duplication because each address (i.e. beta & gamma) would need its own flow and resource code, which are similar.
Please note that I used "http://localhost:8080/*" in the code above as an conceptual example. It does not work.
--- Update ---
I forgot to mention that the beta and gamma uri's also have security associated with them using:
<http:inbound-endpoint ...>
<spring-security:http-security-filter realm="mule-realm"/>
</http:inbound-endpoint>
I tried adding a 'choice' element to the endpoint, but it complained that spring-security was invalid inside the choice decision structure.
A solution would also need to accommodate this feature.
An easy way to achieve your goal is to combine your flows into one and use the choice router. In this configuration your flow will look like the following:
<flow name="stackoverflowFlow1" doc:name="stackoverflowFlow1">
<http:inbound-endpoint exchange-pattern="request-response"
host="localhost" port="8081" doc:name="HTTP" />
<logger level="ERROR" />
<choice doc:name="Choice">
<when expression="#[message.inboundProperties['http.request'] == '/']">
<processor-chain>
<logger message="/ invoked " level="ERROR" />
<jersey:resources doc:name="REST">
<component class="Resource" />
</jersey:resources>
</processor-chain>
</when>
<otherwise>
<processor-chain>
<logger message="otherwise invoked " level="ERROR" />
<jersey:resources doc:name="REST">
<component class="ApplicationsResource" />
</jersey:resources>
</processor-chain>
</otherwise>
</choice>
</flow>
As you can imagine you can take decision on the path or on top of any other http header.
You can find this router documentation here and a list of the most common http properties you can use to make your choices here

Categories