Using Mule Anypoint, I want to achieve functionality without flow-ref - java

I want to write a java file to control the business flow of mule message,
I do not want to use flow-ref module.
How can I achieve it? Below is my mule xml segment.
<flow name="gtrfsettleFlow">
<wmq:inbound-endpoint queue="PINOSAY" doc:name="WMQ"/>
<component class="com.hsbc.gtrf.settle.esb.Rout" doc:name="Java"/>
<flow-ref name="flow2" metadata:id="0ec4db90-8b8c-476b-8186-cfc6b015435c" doc:name="re"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
<sub-flow name="flow1">
<wmq:outbound-endpoint queue="PINOSAY" doc:name="WMQ" connector-ref="WMQ"/>
<logger message="this is flow1" level="INFO" doc:name="Logger"/>
</sub-flow>
<sub-flow name="flow2">
<logger message="now is flow 2" level="INFO" doc:name="Copy_of_Logger"/>
</sub-flow>

You can develop java class implementing Callable interface. Where you can access MuleContext (Event, MuleMessage, Payload and properties). Please refer following link for more details
https://docs.mulesoft.com/mule-user-guide/v/3.8/developing-components#customizing-the-message-flow-behavior

Related

GraphHopper .jar only log Errors, Bad Requests, etc

I'm using GrpahHopper's self hosted routing server v0.5, running on Ubuntu 15.10.
The solution is run via a terminal with a jar file and arbitrary OSM data.
Is there a way to control the logged output of the server (e.g. to only show exceptions, bad requests, etc.)?
For that you'll have to repackage GraphHopper as there is no 'outside' configuration option provided - raise an issue if you need this.
Change the log4j.xml file under web/src/main/resources e.g. replace the root and com.graphhopper logger via the following snippet:
<logger name="com.graphhopper" additivity="false">
<level value="warn" />
<appender-ref ref="ASYNC" />
</logger>
<root>
<priority value="warn"></priority>
<appender-ref ref="ASYNC"/>
</root>
Then repackage GH via the quickstart from source.
Update it might be possible without repackaging via
export JAVA_OPTS="-Dlog4j.debug -Dlog4j.configuration=some-log-config.xml"
using the mentioned and updated log4j.xml but I've not tested this yet. See the log4j docs

Mule MEL usage and ExceptionUtils.containsType(exception, type)

My mule flow has a Catch Exception Strategy like below:
<catch-exception-strategy when="org.mule.util.ExceptionUtils.containsType(exception, IllegalArgumentException.class)"
doc:name="Catch Exception Strategy">
<logger message="IllegalArgumentException occurred" level="INFO" doc:name="logInfo" />
</catch-exception-strategy>
The expression org.mule.util.ExceptionUtils.containsType(exception, IllegalArgumentException.class) sends null as second argument to the method containsType of the class org.mule.util.ExceptionUtils. When I changed the expression to org.mule.util.ExceptionUtils.containsType(exception, java.lang.IllegalArgumentException.class), this time mule says the expression is wrong and throws an exception.
So my question is why the expression org.mule.util.ExceptionUtils.containsType(exception, IllegalArgumentException.class) sends null to second argument?
Can anyone please suggest?
If you want to implement a different treatment for each type of Exception you can use the "choice-exception-strategy". Here you have an example:
<flow name="Sample_Flow">
...
<choice-exception-strategy doc:name="Choice Exception Strategy">
<catch-exception-strategy doc:name="Catch Exception Strategy" when="#[exception.causedBy(org.mule.api.routing.filter.FilterUnacceptedException)]">
<set-variable variableName="errorStatusCode" value="404" doc:name="Set status code"/>
<set-variable variableName="errorReasonPhrase" value="Not Found" doc:name="Set reason phrase"/>
</catch-exception-strategy>
<rollback-exception-strategy doc:name="Rollback Exception Strategy">
<logger level="INFO" doc:name="Logger" message="Unknown error"/>
</rollback-exception-strategy>
</choice-exception-strategy>
</flow>
In the case of your specific implementation you can try just using "IllegalArgumentException" instead of "llegalArgumentException.class":
<catch-exception-strategy when="org.mule.util.ExceptionUtils.containsType(exception, IllegalArgumentException)">
<logger message="IllegalArgumentException occurred #[exception.getCauseException().getClass()] - #[IllegalArgumentException]: #[org.mule.util.ExceptionUtils.containsType(exception.getCauseException(), IllegalArgumentException)]" level="INFO" doc:name="logInfo" />
</catch-exception-strategy>
After the analysis I found that the expression "IllegalArgumentException.class" returns null, but the expression "IllegalArgumentException" returns the class.
You can find more information in the next link:
https://docs.mulesoft.com/mule-user-guide/v/3.7/choice-exception-strategy

Anypoint Studio-Mule ESB create custom Socket Listener

i need to implement a simple mule esb flow with Anypoint Studio.
What i need is to open-up a socket listener on the starting of the flow, and sending to a second Java component the messages which came to the listener...
Can anybody point me to the right direction?
You can use a tcp:connector or ssl:connector, for example:
<!-- Connector -->
<tcp:connector name="tcpConnector" validateConnections="true" receiveBufferSize="102400" clientSoTimeout="10000" receiveBacklog="0" sendBufferSize="0" serverSoTimeout="10000" socketSoLinger="0" doc:name="TCP connector">
<tcp:eof-protocol payloadOnly="true" rethrowExceptionOnRead="true"/>
</tcp:connector>
<!-- Endpoints -->
<tcp:endpoint name="tcpEndpoint" host="${tcp.endpoint.host}" port="${tcp.endpoint.port}" responseTimeout="10000" doc:name="TCP"/>
<flow name="tcpFlow" doc:name="tcpFlow">
<inbound-endpoint ref="tcpEndpoint" doc:name="Generic"/>
<logger level="INFO" doc:name="log" message="Receive payload #[payload]" />
<component class="...Component" doc:name="" doc:description=""/>
</flow>

How to make parallel outbound calls

My use case requires to enrich my input with smne data and send it to an outbound endpoint.
The data for enriching is obtained by making calls to two web-services and then extract the data from the reply.
This extracted data is enriched into my input XML and sent to an outbound endpoint.
The two web-service calls that I need to make needs to be parallel, as they don't have dependency on another. This way I could save my processing time.
Please suggest how I could achieve this parallel processing in a flow in Mule.
Note: I have tried using ALL flow control, but it seems that is calling the web-services (sub-flows) sequentially.
Given below is my abstract flow.
<flow name="mainFlow">
<inbound-endpoint> .....
<some validation>
<setting some flow variables>
<!-- Now make calls to the sub-flows which has some processing of the input and make some web-service calls -->
<all>
<flow-ref name="myFlow1" />
<flow-ref name="myFlow2" />
<flow-ref name="myFlow3" />
</all>
<enrich the input with the data obtained from the output of the above three flows>
<outbound-endpoint>
</flow>
<flow name="myFlow1">
<some transformer to transform the payload provided >
< the tran sformed payload is passed as input to the web-service call>
<http:outbound-endpoint ...>
<transform the reply from the web-service call>
</flow>
<flow name="myFlow2">
<some transformer to transform the payload provided >
< the tran sformed payload is passed as input to the web-service call>
<http:outbound-endpoint ...>
<transform the reply from the web-service call>
</flow>
<flow name="myFlow3">
<some transformer to transform the payload provided to it>
< the tran sformed payload is passed as input to the web-service call>
<http:outbound-endpoint ...>
<transform the reply from the web-service call>
</flow>
Here is a simple configuration that shows one way to make a fork/join with two HTTP outbound endpoints. To add a third endpoint, set MULE_CORRELATION_GROUP_SIZE to 3 and the MULE_CORRELATION_SEQUENCE of the third async flow-ref to 3.
<flow name="fork">
<vm:inbound-endpoint path="fork.in" />
<set-property propertyName="MULE_CORRELATION_GROUP_SIZE"
value="2" />
<all enableCorrelation="IF_NOT_SET">
<async>
<set-property propertyName="MULE_CORRELATION_SEQUENCE"
value="1" />
<flow-ref name="parallel1" />
</async>
<async>
<set-property propertyName="MULE_CORRELATION_SEQUENCE"
value="2" />
<flow-ref name="parallel2" />
</async>
</all>
</flow>
<sub-flow name="parallel1">
<logger level="INFO" message="parallel1: processing started" />
<http:outbound-endpoint address="..."
exchange-pattern="request-response" />
<logger level="INFO" message="parallel1: processing finished" />
<flow-ref name="join" />
</sub-flow>
<sub-flow name="parallel2">
<logger level="INFO" message="parallel2: processing started" />
<http:outbound-endpoint address="..."
exchange-pattern="request-response" />
<logger level="INFO" message="parallel2: processing finished" />
<flow-ref name="join" />
</sub-flow>
<sub-flow name="join">
<collection-aggregator timeout="6000"
failOnTimeout="true" />
<combine-collections-transformer />
<logger level="INFO"
message="Continuing processing of: #[message.payloadAs(java.lang.String)]" />
</sub-flow>
EDIT: In the above config, the aggregator times out after 6 seconds. This is potentially too short for your actual use case: increase as you see fit. Also it is set to fail on time-out, which is maybe not the behaviour you desire in case not all the outbound HTTP endpoint interactions succeeded: it's up to you to decide based on your use case.

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