I am getting started with Mule ESB. I am trying to build a SOAP proxy service that receives a SOAP request and redirects it to a SOAP service.
A simple example like this works fine -
<flow name="http_redirectFlow1" doc:name="http_redirectFlow1">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:8092/HelloProxyService" doc:name="HTTP"/>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:8080/soapsvc/hello" contentType="text/xml" doc:name="HTTP"/>
</flow>
Now I want to dump the contents of the request to a file. Which is the best way to do it? I tried to use the File connector by inserting this segment between the inbound and outbound endpoints -
<file:outbound-endpoint path="c:/temp" outputPattern="temp.txt" responseTimeout="10000" doc:name="File"/>
But that doesn't seem to work. I get an exception that says "Content must be set before entity is written". Not sure what it is, but I may be completely wrong in how I am doing. Please help....
Figured it out myself. I had to translate the DOM to XML using the dom-to-xml transformer. The XML dump is done as follows :-
<mulexml:dom-to-xml-transformer returnClass="java.lang.String"></mulexml:dom-to-xml-transformer>
<file:outbound-endpoint path="c:/temp" outputPattern="Dump_Rcvd.txt" responseTimeout="10000" doc:name="File" />
Thanks !
Alternately you can use <object-to-string-transformer doc:name="Object to String"/> before file:outbound-endpoint that will make the payload as a String format and can be written into a file easily
Use File Connector and Transformers involving Bytearray.
Related
I'm trying to send SOAP envelope with standard mule HTTP Request and I'm having trouble with setting Media-Type of an outbound request. The webservice expects "application/soap+xml", but setting 'Content-Type: application/soap+xml' header in POST Request or setting mime-type to payload doesn't seem to work. I keep getting error 415 - unsupported media type. Does anybody have any idea what can I do to resolve this issue? My XML code so far (I've changed names and addresses, the idea stays the same):
<flow name="get-report">
<http:listener config-ref="asdf-httpListenerConfig" path="/" doc:name="HTTP"/>
<custom-transformer encoding="UTF-8" mimeType="application/soap+xml" class="Authorization" doc:name="Java"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<http:request config-ref="HTTP_Request_Configuration" path="path.svc" method="POST" doc:name="HTTP">
<http:request-builder>
<http:header headerName="Content-Type" value="application/soap+xml"/>
<http:header headerName="action" value="someAction"/>
<http:header headerName="host" value="someHost"/>
</http:request-builder>
</http:request>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
</flow>
The 'Authorization' transformer isn't really relevant, right now I just hardcode entire envelope and return it.
Also, POST'ing an envelope via soapUI with the same addresses, content type and media-type works fine.
Setting the header in the http:request should definitely set the Content-Type header, so i would suggest this is not the issue. Though it is dependant on the API implementation, 415 Unsupported Media Type can be caused by the requests Content-Type, Content-Encoding or by inspecting the data directly. Perhaps it could be caused by the XML structure.
I have been following this tutorial which is really great to consume wb services from WSDL http://training.middlewareschool.com/mule/consuming-wsdl-first-service/.
I have been trying to do a similar approach by generating a client web service in Eclipse using CXF and publishing the web service in Mule. My question is: if I configure for the client and mule application to have the same endpoint (for example: localhost:8082/ipsoap/test), how can I have the web service work the same way as with the tutorial.
Meaning if I test sending a request to mule from the client (in eclipse) I should receive the right response from mule. Thank you in advance for your time.
So in short:
1-I generated a client app in eclipse using the wsdl in the following link in the tutorial: http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl
2- As a start in Mule, I added an http connector and a logger and changed the endpoint path in eclipse to the one I set on the HTTP connector on Mule. Thus, I can see that there is a payload when I am sending a request to Mule from the client in Eclipse.
3- I need to have an application, namely my client app in eclipse, consume a published service in Mule. Now I think this is achieved using the CXF component but I still fail to make it work. In fact, I wonder if this is one valid way of using Mule since I couldn't find any tutorial about what I am trying to achieve.
So here is how I test it:
I used the same endpoint I used in Mule and receive the following log:
> INFO 2014-07-07 13:19:46,124
> [[soapservice].connector.http.mule.default.receiver.02]
> org.mule.api.processor.LoggerMessageProcessor: message transformation
> <soapenv:Envelope
> xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
> xmlns:q0="http://ws.cdyne.com/"
> xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
> <soapenv:Body>
> <q0:ResolveIP>
> <q0:ipAddress>173.194.36.39</q0:ipAddress>
> <q0:licenseKey/>
> </q0:ResolveIP> </soapenv:Body> </soapenv:Envelope>
>
> ERROR 2014-07-07 13:19:46,134
> [[soapservice].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: String 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: String (org.mule.api.transport.DispatchException)
> org.mule.module.cxf.CxfOutboundMessageProcessor:150
> (http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/transport/DispatchException.html)
> -------------------------------------------------------------------------------- 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)
As you can see the soap request can be seen but it is not consumed at the level of the CXF component. Here is my mule code:
<flow name="SoapService" doc:name="SoapService">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8082" path="test/cap.asmx" doc:name="HTTP"/>
<byte-array-to-string-transformer doc:name="Byte Array to String"/>
<logger message="message transformation #[message.payload]" level="INFO" doc:name="Logger"/>
<flow-ref name="RequestResponse" doc:name="Flow Reference"/>
<logger level="INFO" doc:name="Logger" message="after posting #[message.payload]"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
</flow>
<flow name="RequestResponse" doc:name="RequestResponse">
<cxf:jaxws-client operation="ResolveIP" clientClass="pck.IP2Geo" port="IP2GeoSoap" wsdlLocation="file:/C:/Users/12204-hajjam1/workspace/ipgo/src/ipgeo.wsdl" doc:name="soap 2"/>
<logger message="before posting #[message.payload]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" method="POST" address="http://localhost:10387/ip2geo/ip2geo.asmx" doc:name="HTTP"/>
</flow>
Also if I add a set payload with the ip #[{'173.194.36.39',''}] (the second argument can be left empty) before the cxf component it returns a an empty element. Yet, the response should be something like this:
<pck.IPInformation>
<city>Mountain View</city>
<stateProvince>CA</stateProvince>
<country>United States</country>
<organization/>
<latitude>37.4192</latitude>
<longitude>-122.0574</longitude>
<areaCode>0</areaCode>
<timeZone/>
<hasDaylightSavings>false</hasDaylightSavings>
<certainty>90</certainty>
<regionName/>
<countryCode>US</countryCode>
</pck.IPInformation>
Thus, my problem is with the consumption and retrieval of the response.
I apologize for the length but I have been struggling with this and haven't found a solution online. Thanks in advance.
You should create an instance of the message class that as been generated for the ResolveIP method from the WSDL and use it as the message payload before the cxf:jaxws-client element.
I am working on a part of a Mule ESB application and the issue I am having is very analogous to a chat room.
The chat room (server, Mule ESB) can listen for many chatters (clients, external applications) and when a single chatter (c1) inputs a message, the server echos it to all the other chatters, except for c1. In my case though, I would need to also echo it to c1.
I am having a hard time wrapping my mind around some detailed aspects of how the message processing works in Mule ESB. I read the documentation about transports and believe I may need to work with Message Receivers and Message Dispatchers.
Consider the following configuration:
<mule ...>
<tcp:connector name="tcpConn" doc:name="TCP connector" clientSoTimeout="0" keepAlive="true" keepSendSocketOpen="true" receiveBacklog="0" receiveBufferSize="0" reuseAddress="true" sendBufferSize="0" serverSoTimeout="0" socketSoLinger="0" validateConnections="true">
<reconnect-forever />
<tcp:direct-protocol payloadOnly="true"/>
</tcp:connector>
</spring:beans>
<tcp:endpoint exchange-pattern="request-response" host="localhost" port="8090" name="ListenEndpoint" responseTimeout="10000" doc:name="TCP"/>
<flow name="ChatroomExampleFlow1" doc:name="ChatroomExampleFlow1">
<tcp:inbound-endpoint exchange-pattern="request-response" ref="ListenEndpoint" responseTimeout="10000" doc:name="Client Message"/>
<logger level="INFO" doc:name="Logger"/>
<all doc:name="All">
<tcp:outbound-endpoint host="${client1.host}" port="${client1.port}" responseTimeout="10000" doc:name="TCP"/>
<tcp:outbound-endpoint host="${client2.host}" port="${client2.port}" responseTimeout="10000" doc:name="TCP"/>
<tcp:outbound-endpoint host="${client3.host}" port="${client3.port}" responseTimeout="10000" doc:name="TCP"/>
</all>
</flow>
</mule>
If I know at configuration time the host and port of all clients, then this configuration holds. However, my goal is to be able to send out the messages to clients that have established a connection, which could be up to n clients. As more clients connect/disconnect, I would need to add or remove them from the list.
There exists a <recipient-list expression="#[app.registry.remoteEndpoints]"/> where the expression should evaluate to a List of endpoints and the flow will send the message to every endpoint in the collection. However, for my purposes this does not work (see answer below). See the documentation for recipient list
<mule ...>
<tcp:connector name="tcpConn" doc:name="TCP connector" clientSoTimeout="0" keepAlive="true" keepSendSocketOpen="true" receiveBacklog="0" receiveBufferSize="0" reuseAddress="true" sendBufferSize="0" serverSoTimeout="0" socketSoLinger="0" validateConnections="true">
<reconnect-forever />
<tcp:direct-protocol payloadOnly="true"/>
</tcp:connector>
<spring:beans>
<spring:bean name="remoteEndpoints" scope="singleton" class="java.util.ArrayList"/>
</spring:beans>
<tcp:endpoint host="localhost" exchange-pattern="one-way" port="8090" name="ListenEndpoint" responseTimeout="10000" doc:name="TCP"/>
<flow name="ChatroomExampleFlow1" doc:name="ChatroomExampleFlow1">
<tcp:inbound-endpoint ref="ListenEndpoint" responseTimeout="10000" doc:name="Client Message"/>
<echo-component doc:name="Echo"/>
<component class="EndpointStorer" doc:name="Java"/>
<recipient-list expression="#[app.registry.remoteEndpoints]"/>
</flow>
</mule>
And with EndpointStorer looking like this:
public Object onCall(MuleEventContext eventContext) throws Exception
{
Registry registry = eventContext.getMuleContext().getRegistry();
MuleMessage message = eventContext.getMessage();
ArrayList arrList = (ArrayList) registry.get("remoteEndpoints");
Object remoteAddress = message.getOutboundProperty("MULE_REMOTE_CLIENT_ADDRESS");
String tcpAddr = "tcp://" + remoteAddress.toString().substring(1); //substring 1 because we see the remote client address as something like /127.0.0.1:4943
if (!arrList.contains(tcpAddr))
{
arrList.add(tcpAddr);
}
return message;
}
You can't reach established inbound TCP connections, at least not using TCP outbound endpoints. It may be possible to extend the TCP connector to expose the Socket in http://github.com/mulesoft/mule/blob/mule-3.x/transports/tcp/src/main/… but it's no small feat.
You could consider using the AJAX transport.
We have produced JAX-WS web-services with the help of Java API and published. Now we would like to queuing the requests, which are coming for the services with the help of JMS. We chosen the ACTIVE MQ JMS Server with the combination of MULE ESB.
We have tried the proxying of webservices with the help of two Http Endpoints. It is working fine. So When i trying to test it by sending request from SOAP UI to Http inbound end point, it is forwarding request to my services and get back the response to SOAP UI.
But when we are trying to put the JMS endpoint in between these Http end points, the request is forwarded to my services, but not the message (SOAP).
Please help me to resolve the issue or suggest me the alternative way for Queuing.
Following image shows flow in MULE.
.
Following is the flow :
<jms:activemq-connector name="Active_MQ1" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="finalFlow1" doc:name="finalFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8888" contentType="text/xml" doc:name="HTTP"/>
<jms:outbound-endpoint exchange-pattern="request-response" queue="servicesQueue" connector-ref="Active_MQ1" doc:name="JMS"/>
<http:outbound-endpoint mimeType="text/xml" doc:name="HTTP" exchange-pattern="request-response" method="POST" path="MyServices" host="localhost" port="5050" />
</flow>
Actually MyServices is produced at http://localhost:5050/MyServices
The problem is probably due to that you are expecting a string payload in your JMS queue and the http:inbound-endpoint produces a stream payload.
Try putting <object-to-string-transformer/> before the jms:outbound-endpoint.
I tried to read a file and email through Mule. But it throws the following exception.
org.mule.api.transformer.TransformerException: Could not find a transformer to transform "SimpleDataType{type=javax.mail.internet.MimeMessage, mimeType='*/*'}" to "SimpleDataType{type=java.io.InputStream, mimeType='*/*'}".
at org.mule.registry.MuleRegistryHelper.lookupTransformer(MuleRegistryHelper.java:252)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:355)
at org.mule.DefaultMuleMessage.getPayload(DefaultMuleMessage.java:313)
+ 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
My mule file is as follows:
<flow name="Exception_HandlingFlow1" doc:name="Exception_HandlingFlow1">
<file:inbound-endpoint path="D:\WorkArea\COPA\In" responseTimeout="10000" doc:name="File Writer">
<file:file-to-string-transformer/>
</file:inbound-endpoint>
<component doc:name="Java" class="com.exhnlr.Handler.ExceptionHandler"/>
<smtps:outbound-endpoint host="192.168.131.139" responseTimeout="10000" doc:name="SMTP"
from="anbu1#bibs.com" subject="test" to="anbu1#bibs.com" user="anbu1" mimeType="text/plain">
<email:string-to-email-transformer/>
</smtps:outbound-endpoint>
</flow>
I have read a similiar link How to parse inbound e-mail when using Mule's IMAP transport?, but it didn't work for me.
Please help.
Add an <object-to-string-transformer /> after the file inbound endpoint.