Use Topic object when communicating with amazon SNS api through mule - amazon-web-services

I'm using Anypoint Studio to experiment with connectors. At this point, i'm trying to make a simple flow that lists topics available at the amazon SNS endpoint and searches if a certain topic is available.
So far, i'm able to get a response from the API with the list of topics, which i then transform to json using Object to JSON transformer, but i want to iterate through the list to search for a certain topic(using java or whatever filter). The topic entity already exists in the amazon API in Anypoint Studio but i can't find out how to map it to the response returned by the API. Any hint would be appreciated.
EDIT: Here is the code of the flow, removed access keys.
<?xml version="1.0" encoding="UTF-8"?>
<sns:config name="Amazon_SNS" accessKey="" secretKey="" doc:name="Amazon SNS" region="EUWEST1">
<sns:connection-pooling-profile initialisationPolicy="INITIALISE_ONE" exhaustedAction="WHEN_EXHAUSTED_GROW"/>
</sns:config>
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8081" doc:name="HTTP Listener Configuration"/>
<json:object-to-json-transformer name="Object_to_JSON" doc:name="Object to JSON"/>
<flow name="CreateTopic">
<http:listener config-ref="HTTP_Listener_Configuration" path="/createtopic" doc:name="HTTP"/>
<sns:create-topic config-ref="Amazon_SNS" doc:name="Amazon SNS">
<sns:create-topic-request name="#[message.inboundProperties.'http.query.params'.name]"/>
</sns:create-topic>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
<flow name="Subscribe">
<http:listener config-ref="HTTP_Listener_Configuration" path="/Subscribe" doc:name="HTTP"/>
<sns:subscribe config-ref="Amazon_SNS" doc:name="Amazon SNS">
<sns:subscribe-request topicArn="#[message.inboundProperties.'http.query.params'.topic]" protocol="email" endpoint="#[message.inboundProperties.'http.query.params'.subscriber]"/>
</sns:subscribe>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
<flow name="ListTopics">
<http:listener config-ref="HTTP_Listener_Configuration" path="/listTopics" doc:name="HTTP"/>
<sns:list-topics config-ref="Amazon_SNS" doc:name="Amazon SNS">
</sns:list-topics>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
<flow name="Publish">
<http:listener config-ref="HTTP_Listener_Configuration" path="/publish" doc:name="HTTP"/>
<sns:publish config-ref="Amazon_SNS" doc:name="Amazon SNS">
<sns:publish-request topicArn="#[message.inboundProperties.'http.query.params'.topic]" message="There's new content in the topic #[message.inboundProperties.'http.query.params'.topic]" subject="New comments on an idea - Crowdsourcing Forums" messageStructure="Raw"/>
</sns:publish>
<json:object-to-json-transformer doc:name="Object to JSON"/>
</flow>
<flow name="checkTopic">
<http:listener config-ref="HTTP_Listener_Configuration" path="/checkTopic" doc:name="HTTP"/>
<sns:get-topic-attributes config-ref="Amazon_SNS" doc:name="Amazon SNS">
<sns:get-topic-attributes-request topicArn="#[message.inboundProperties.'http.query.params'.topic]"/>
</sns:get-topic-attributes>
</flow>

The message payload you get from sns:list-topics is a com.amazonaws.services.sns.model.ListTopicsResult.
So you can use a MEL transformer to filter the topic list with an expression like:
($ in message.payload.topics if $.topicArn contains 'my-topic')
Reference: Projections and folds in MVEL 2.0

Related

Mule getting list of objects from s3 bucket

Need to retrieve the list of objects from S3 bucket through MULE ESB. But when getting the payload.getkey(), it's throws the error: unable to resolve method: org.mule.module.s3.model.ObjectListing.getKey() [arglength=0]]
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="9090" doc:name="HTTP Listener Configuration"/>
<s3:config name="Amazon_S3__Configuration" accessKey="XXXXXXX" secretKey="XXXXXXXX" doc:name="Amazon S3: Configuration"/>
<flow name="s3bucket-downloadfilesFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/getfiles" doc:name="HTTP"/>
<s3:list-objects config-ref="Amazon_S3__Configuration" bucketName="ge-datastaging-dev" prefix="Mule/inbound/" maxKeys="5" doc:name="Amazon S3"/>
<logger level="INFO" doc:name="Logger"/>
<foreach collection="#[payload]" doc:name="For Each">
<logger level="INFO" doc:name="Logger" message=" inside foreach...... #[payload.getCommonPrefixes()] ...."/>
<logger level="INFO" doc:name="Logger" message=" ################...... #[payload.getNextMarker()] ...."/>
<logger level="INFO" doc:name="Logger" message=" ################...... #[payload.getKey()] ...."/>
</foreach>
</flow>
Instead of looping on payload, do <foreach> on ObjectSummaries object in ObjectListing like this:
<s3:list-objects config-ref="Amazon_S3__Configuration" bucketName="ge-datastaging-dev" prefix="Mule/inbound/" maxKeys="5" doc:name="Amazon S3"/>
<foreach doc:name="For Each" collection="#[payload.objectSummaries]">
<s3:get-object-content config-ref="Amazon_S3__Configuration" bucketName="#[payload.getBucketName()]" key="#[payload.getKey()]" doc:name="Amazon S3"/>
</foreach>

Mule https call with string payload with query string and HTTP POST method

I am new to ESB mule. I have tried to reach https url using ESB mule.
For my request i have to build the URL and POST content.
Building URL -
I have prepared the value and set it in the java string. This was mapped in the config file using - setInvocationProperty.
Post content :
Post content is the string message.
When i run the program i am getting error message saying
The request signature we calculated does not match the signature you provided
In my java file, i have lines to print the query string value and the payload in console.
When I hit the url with post content written in console using postman chrome extension, i am getting successful response.
But with ESB mule i could not get the successful response.
Could you please show some light to fix this issue ?
Here I have pasted my ESB mule configuration file content.
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:wmq="http://www.mulesoft.org/schema/mule/ee/wmq" xmlns:metadata="http://www.mulesoft.org/schema/mule/metadata" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/wmq http://www.mulesoft.org/schema/mule/ee/wmq/current/mule-wmq-ee.xsd">
<http:listener-config name="HTTP_Listener_Configuration" host="localhost" port="8084" basePath="/mule" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="mws.amazonservices.com" port="443" doc:name="HTTP Request Configuration" protocol="HTTPS" >
<http:proxy host="proxy.aaa.com" port="8080" username="John" password="pass"/>
</http:request-config>
<flow name="secondflowFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/" doc:name="HTTP"/>
<custom-transformer class="com.mule.URLBuilding.BuildURL" doc:name="Java"/>
<set-payload value="#[message.payloadAs(java.lang.String)]" doc:name="Set Payload"/>
<http:request config-ref="HTTP_Request_Configuration" method="POST" path="/Products/2011-10-01" doc:name="Amazon_Call_HTTPS">
<http:request-builder>
<http:query-param paramName="MarketplaceId" value="#[flowVars.strMarketplaceId]"/>
<http:query-param paramName="ASINList.ASIN.1" value="#[flowVars.strASINListASIN1]"/>
<http:query-param paramName="AWSAccessKeyId" value="#[flowVars.strAWSAccessKeyId]"/>
<http:query-param paramName="Action" value="#[flowVars.strAction]"/>
<http:query-param paramName="SellerId" value="#[flowVars.strSellerId]"/>
<http:query-param paramName="MWSAuthToken" value="#[flowVars.strMWSAuthToken]"/>
<http:query-param paramName="SignatureVersion" value="2"/>
<http:query-param paramName="Timestamp" value="#[flowVars.strtimestamp]"/>
<http:query-param paramName="Version" value="#[flowVars.strVersion]"/>
<http:query-param paramName="Signature" value="#[flowVars.strsignature]"/>
<http:query-param paramName="SignatureMethod" value="#[flowVars.strSignatureMethod]"/>
</http:request-builder>
<http:success-status-code-validator values="0..599"/>
</http:request>
</flow>
</mule>

Axis web service consumer and Mule 3.6

I'm going to try latest mule runtime to consume an old Axis web service.
Just trying to use "Web service consumer" component without success.
My first try on a method without parameters result in
org.apache.cxf.interceptor.Fault: Failed to load transport: org/mule/transport axis (org.mule.api.registry.ServiceException). Message payload is of type: MuleUniversalConduit$1
at org.mule.module.cxf.transport.MuleUniversalConduit$2.handleMessage(MuleUniversalConduit.java:194) ~[mule-module-cxf-3.6.1.jar:3.6.1]
...
this is my actual config
mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting" xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
xmlns:ws="http://www.mulesoft.org/schema/mule/ws" xmlns:json="http://www.mulesoft.org/schema/mule/json" xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.6.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/tls http://www.mulesoft.org/schema/mule/tls/current/mule-tls.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ws http://www.mulesoft.org/schema/mule/ws/current/mule-ws.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd">
<tls:context name="MyWSTLS_Context" doc:name="TLS Context">
<tls:trust-store path="trustStore/truststore.ts" password="secret"/>
<tls:key-store path="trustStore/keystore.jks" password="secret" keyPassword="toosecret"/>
</tls:context>
<ws:consumer-config name="MyWS_WS_getVersion_Consumer" wsdlLocation="Version.wsdl" service="VersionService" port="Version" serviceAddress="axis:http://staging.myws.com/myws/services/Version" doc:name="Web Service Consumer" connectorConfig="HTTPS_MyWSRequest_Configuration"/>
<http:request-config name="HTTPS_MyWSRequest_Configuration" protocol="HTTPS" host="staging.myws.com" port="443" basePath="/MyWS/services" doc:name="HTTP Request Configuration" tlsContext-ref="MyWSTLS_Context"/>
<http:listener-config name="MyWS_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<flow name="wsconsumerFlow">
<http:listener config-ref="MyWS_Listener_Configuration" path="/consumer" doc:name="HTTP"/>
<ws:consumer config-ref="MyWS_WS_getVersion_Consumer" operation="getVersion" doc:name="Web Service Consumer"/>
<logger level="INFO" doc:name="Logger"/>
</flow>
</mule>
The service is an rpc style an requires array of strings as parameters.
Any hint appreciated.
The deprecated but still shipped for backwards compatibility transport for axis is getting into your way.
Just change the axis: from the service address, hopefully it should work if there are no other problems.

How to pass a file as SOAP request to Mule SOAP client to consume service

I have a flow which is exposing a webservice :-
<flow name="ServiceFlow" doc:name="ServiceFlow">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP"/>
<cxf:jaxws-service serviceClass="com.test.services.schema.maindata.v1.MainData" doc:name="SOAP"/>
<component class="com.test.services.schema.maindata.v1.Impl.MainDataImpl" doc:name="JavaMain_ServiceImpl"/>
</flow>
This web service have a operation insertDataOperation which takes all the input from SOAP request and insert it in Database...
My SOAP request is as follow :-
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://services.test.com/schema/MainData/V1">
<soapenv:Header/>
<soapenv:Body>
<v1:insertDataRequest>
<v1:Id>311</v1:Id>
<v1:Name>ttttt</v1:Name>
<v1:Age>56</v1:Age>
<v1:Designation>eeeee</v1:Designation>
</v1:insertDataRequest>
</soapenv:Body>
</soapenv:Envelope>
Now I have another web service client flow which is consuming this webservice and the flow is :-
<flow name="ClientFlow" doc:name="ClientFlow">
<file:inbound-endpoint responseTimeout="10000" connector-ref="File_Global" doc:name="File" path="E:\backup\test">
<file:filename-regex-filter pattern="SoapRequestInsert.xml" caseSensitive="false"/>
</file:inbound-endpoint>
<file:file-to-string-transformer encoding="UTF-8" mimeType="text/xml" doc:name="File to String"/>
<cxf:jaxws-client doc:name="SOAP" serviceClass="com.test.services.schema.maindata.v1.MainData" operation="insertDataOperation" port="MainDataPort" />
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP"/>
</flow>
Now here I am trying to consume the webservice by using a file inbound endpoint and passing the SOAP request in the file SoapRequestInsert.xml .. But the issue is that I don't get any error but the data is not inserted in database.. I checked the log .. where I found it enters the insert method of webservice implementation class but it doesn't get the input value ... Please help ... I have taken the reference from the following :- Consuming a JAX-WS in a Mule ESB flow
But It's not working .. what should I do to make it consume successfully and insert into DB ??? Pls help
Because the file you are posting contains the whole SOAP envelope you can HTTP POST it as is:
<flow name="ClientFlow" doc:name="ClientFlow">
<file:inbound-endpoint responseTimeout="10000" connector-ref="File_Global" doc:name="File" path="E:\backup\test">
<file:filename-regex-filter pattern="SoapRequestInsert.xml" caseSensitive="false"/>
</file:inbound-endpoint>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="mainData" doc:name="HTTP"/>
</flow>
Note that you may need to add the SOAP action header, before the http:outbound-endpoint:
<set-property name="SOAPAction"
value="http://services.test.com/schema/MainData/V1/insertDataOperation" />
The final working solution is as David suggested the flow and by setting SOAPAction before outbound endpoint :-
<set-property name="SOAPAction"
value="http://services.test.com/schema/MainData/V1/insertDataOperation" />

Building a custom interceptor with SOAP Web Service MULE

I'am using Mule Community Edition 3.4.
I have a problem with the UntilSuccessful component. The scenario is now exposed:
I have a flow composed by a UntilSuccessful component in which there's a SOAP component that makes a request to a Web Service. In this flow there is an ExcpetionStrategy, too. The problem that I have is that when an exception occurs inside the UntilSuccessful (i.e in the SOAP component) the ExcpetionStrategy is not able to handle it because it (the Exception thrown) is handled by some mechanism inside the UntilSuccessful component.
Because I need to handle the Exception in the ExcpetionStrategy, I thought to build a custom outbound interceptor (inside the SOAP component) that intercept the SOAP response (an exception if it's thrown) and that is able to throw an Exception in order to trigger the ExcpetionStrategy.
Could anyone help me with this problem? I tried to read the documentation but it is sparse and does not explain very well how to build a custom outbound exception.
What I would to do is to save somewhere the name of Exception thrown (i.e if server thrown a NumberFormatException, I would save its name somewhere in order to use it in the ExceptionStrategy)
Below you can see a snippet of mule configuration file:
<flow name="ProvaClient" doc:name="ProvaClient">
<quartz:inbound-endpoint jobName="TalendJob" repeatInterval="5000" repeatCount="0" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job>
<quartz:payload>error</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
<object-to-string-transformer doc:name="Object to String"/>
<until-successful objectStore-ref="OS_Bean" maxRetries="2" secondsBetweenRetries="2" doc:name="Until Successful" deadLetterQueue-ref="myQueue">
<processor-chain doc:name="Processor Chain: Wait For Web Service Response">
<processor-chain doc:name="Processor Chain: Web Service">
<cxf:jaxws-client operation="getCode" clientClass="it.aizoon.prova.client.ProvaService" port="ProvaPort" enableMuleSoapHeaders="true" doc:name="SOAP">
</cxf:jaxws-client>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" path="service/prova" method="POST" doc:name="HTTP"/>
</processor-chain>
<logger message="PAYLOAD: #[payload]" level="INFO" doc:name="Logger"/>
</processor-chain>
</until-successful>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<!-- <processor ref="myExceptionHandler_id"/> -->
<logger message="EXCEPTION STRATEGY" level="INFO" doc:name="Logger"/>
</catch-exception-strategy>
</flow>
Here you can see the server which exposes a web service:
<flow name="provaServer" doc:name="provaServer">
<http:inbound-endpoint exchange-pattern="request-response" doc:name="HTTP" host="localhost" path="service/prova" port="8081"/>
<logger message="SERVER" level="INFO" doc:name="Logger"/>
<cxf:jaxws-service serviceClass="it.aizoon.prova.Prova" doc:name="Process SOAP Request" />
<component class="it.aizoon.prova.ProvaImpl" doc:name="Java"/>
</flow>
And here there is the ProvaImpl.java, the implementation of Web Service. How you can see, if the string passed as argument in getCode() function is error, an exception in thrown and I would that it is managed by the exception strategy defined in the client
#WebService(endpointInterface = "it.aizoon.prova.Prova",
serviceName = "Prova")
public class ProvaImpl implements Prova{
#Override
public String getCode(String code) throws NumberFormatException{
// TODO Auto-generated method stub
if(code.equals("error")) throw new NumberFormatException();
String str = "Andato a buon fine!";
return str;
}
}
I would change the approach rather than using an interceptor. If you need to invoke the exception strategy wihout triggering the until-succesful router first, I would move your cxf:jaxws-client etc. to a private flow. To quote Mule in Action 2nd edition on private flows:
This decoupling allows defining processing and error handling
strategies that are local to the private flow.
<flow name="ProvaClient" doc:name="ProvaClient">
...
<until-successful objectStore-ref="OS_Bean"
maxRetries="2" secondsBetweenRetries="2" doc:name="Until Successful"
deadLetterQueue-ref="myQueue">
<processor-chain doc:name="Processor Chain: Wait For Web Service Response">
<processor-chain doc:name="Processor Chain: Web Service">
<flow-ref name="externalCallFlow" />
</processor-chain>
<logger message="PAYLOAD: #[payload]" level="INFO" doc:name="Logger" />
</processor-chain>
</until-successful>
...
</flow>
<flow name="externalCallFlow">
<cxf:jaxws-client operation="getCode"
clientClass="it.aizoon.prova.client.ProvaService" port="ProvaPort"
enableMuleSoapHeaders="true" doc:name="SOAP">
</cxf:jaxws-client>
<http:outbound-endpoint exchange-pattern="request-response"
host="localhost" port="8081" path="service/prova" method="POST"
doc:name="HTTP" />
<catch-exception-strategy doc:name="Catch Exception Strategy">
<!-- Handle exception here locally and return custom exception or error
message for the unil-successful router -->
</catch-exception-strategy>
</flow>
You can then handle exceptions locally and return a custom exception or error
message for the until-successful router to catch using the following attribute: failureExpression="exception-type:java.lang.NumberFormatException"
Here's a dummy example I knocked up to throw a NumberFormatException, log the exception in the exception strategy and retry:
<flow name="test" doc:name="test">
<http:inbound-endpoint address="http://localhost:8081/test"
doc:name="HTTP" />
<until-successful objectStore-ref="OS_Bean"
maxRetries="2" secondsBetweenRetries="2" doc:name="Until Successful">
<processor-chain doc:name="Processor Chain: Wait For Web Service Response">
<processor-chain doc:name="Processor Chain: Web Service">
<flow-ref name="externalCallFlow" doc:name="Flow Reference" />
</processor-chain>
</processor-chain>
</until-successful>
</flow>
<flow name="externalCallFlow" doc:name="externalCallFlow">
<scripting:component>
<scripting:script engine="groovy">
throw new java.lang.NumberFormatException();
</scripting:script>
</scripting:component>
<default-exception-strategy>
<processor-chain>
<logger level="ERROR"
message="NumberFormatException Occurred : #[message.payload.getException().getCause()]" />
<scripting:component>
<scripting:script engine="groovy">
throw message.payload.getException().getCause();
</scripting:script>
</scripting:component>
</processor-chain>
</default-exception-strategy>
</flow>