How to remove Mule Headers from SOAP response - soap

I have a requirement where I need to expose a SOAP webservice .. So I have the following Mule flow :-
<jms:activemq-connector name="Active_MQ" brokerURL="tcp://localhost:61616" validateConnections="true" doc:name="Active MQ"/>
<flow name="Flow1" doc:name="Flow1" >
<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"/>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
<jms:outbound-endpoint queue="NewQueue" connector-ref="Active_MQ" doc:name="JMS" exchange-pattern="request-response"/>
<logger message="Response2 :- #[message.payload]" level="INFO" doc:name="Logger"/>
<mulexml:xml-to-object-transformer doc:name="XML to Object"/>
</flow>
<flow name="flow2" doc:name="flow2" >
<jms:inbound-endpoint connector-ref="Active_MQ" address="jms://tcp:NewQueue" doc:name="JMS" exchange-pattern="request-response" disableTemporaryReplyToDestinations="true" responseTimeout="90000"/>
<set-variable variableName="SOAPRequest" value="#[message.payload]" doc:name="Variable"/>
<mulexml:xml-to-object-transformer doc:name="XML to Object"/>
<component class="com.test.services.schema.maindata.v1.Impl.MainDataImpl" doc:name="JavaMain_ServiceImpl">
<method-entry-point-resolver>
<include-entry-point method="retrieveDataOperation"/>
<include-entry-point method="insertDataOperation"/>
<include-entry-point method="updateDataOperation"/>
<include-entry-point method="deleteDataOperation"/>
</method-entry-point-resolver>
</component>
<mulexml:object-to-xml-transformer doc:name="Object to XML"/>
</flow>
Here you can see the request is getting into JMS queue from the first flow and the second flow use JMS inbound takes it from the JMS queue and the webservice implemented class proccess it .. Now the service works fine without any issue .. the only issue is it get Mule Header in the SOAP in the response like the following :-
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<mule:header xmlns:mule="http://www.muleumo.org/providers/soap/1.0">
<mule:MULE_CORRELATION_ID>ID:ANIRBAN-PC-49483-1408719168461-1:1:10:1:1</mule:MULE_CORRELATION_ID>
<mule:MULE_CORRELATION_GROUP_SIZE>-1</mule:MULE_CORRELATION_GROUP_SIZE>
<mule:MULE_CORRELATION_SEQUENCE>-1</mule:MULE_CORRELATION_SEQUENCE>
</mule:header>
</soap:Header>
<soap:Body>
<deleteDataResponse xmlns="http://services.test.com/schema/MainData/V1">
<Response>Data not exists !!! Please provide correct ID</Response>
<Id>0</Id>
<Age>0</Age>
</deleteDataResponse>
</soap:Body>
</soap:Envelope>
Now please help me to remove the Mule headers from the SOAP response .. I tried with the following :- <cxf:jaxws-service serviceClass="com.test.services.schema.maindata.v1.MainData" enableMuleSoapHeaders="false" doc:name="SOAP"/> but no use .. it's still showing the Mule headers .. Please help ..

You can potentially get away with a temporary workaround until the enableMuleSoapHeaders="false" issue gets solved, by either:
Adding a between the HTTP inbound endpoint and the CXF service ; in order to remove the undue SOAP headers but XSL-Transformation
Using delete-message-property to remove the MULE_* props at the end of Flow1, right after the mulexml:xml-to-object-transformer

I also found an alternate solution off adding it to cxf:outInterceptors
<cxf:jaxws-service serviceClass="com.test.services.schema.maindata.v1.MainData" doc:name="SOAP">
<cxf:outInterceptors >
<spring:bean id="outfault" class="com.test.services.schema.SOAPOptionalData.SOAPInterceptorOutboundHeaderRemover"/>
</cxf:outInterceptors>
</cxf:jaxws-service>
And in the Java class :-
public class SOAPInterceptorOutboundHeaderRemover extends AbstractSoapInterceptor {
public SOAPInterceptorOutboundHeaderRemover() {
super(Phase.PRE_PROTOCOL);
}
#Override
public void handleMessage(SoapMessage arg0) throws Fault {
List<Header> headerList = arg0.getHeaders();
Header muleHeader = null;
boolean isMuleHeader = false;
for (Header header : headerList) {
ElementNSImpl element = (ElementNSImpl) header.getObject();
if ("mule:header".equals(element.getNodeName())) {
isMuleHeader = true;
muleHeader = header;
}
}
if (isMuleHeader) {
arg0.getHeaders().remove(muleHeader);
}
}
}
And this is also working fine

Related

Mule ESB Flow calling SOAP not working but worked from SOAP UI

Details : I have created on flow in MuleESB which is calling a web-service without any parameter just sending it username, password and token in a property and it is working fine.
But the second API I want to post some parameters while calling soap request but I don't know how to use it I tried to pass through set payload but no response.
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration"/>
<http:request-config name="HTTP_Request_Configuration" host="webservicehostadd" port="443" doc:name="HTTP Request Configuration">
<http:basic-authentication username="username" password="pass"/>
</http:request-config>
<ws:consumer-config name="Web_Service_Consumer" wsdlLocation="https://xxxx/1.0?wsdl" service="xxx" port="xxxx" serviceAddress="https://xxxxx/1.0" connectorConfig="HTTP_Request_Configuration" doc:name="Web Service Consumer"/>
<flow name="mycustomflow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/TEST" doc:name="HTTP"/>
<set-property propertyName="APIKey" value="xxx-xxx-xxx-xxx-xxx" doc:name="Property"/>
<dw:transform-message doc:name="Transform Message" metadata:id="xxx-xxx-xxx-xxx-xxxxxxxx">
<dw:input-payload mimeType="application/xml"/>
<dw:set-payload><![CDATA[%dw 1.0
%output application/xml
%namespace ns0 http://localhost/getDetails:getDetailsWSD
---
{
ns0#getDetails: {
getDetailsOrder: {
ID: payload.ns0#getDetails.getDetailsOrder.ID,
AllData: payload.ns0#getDetails.getDetailsOrder.AllData
}
}
}]]></dw:set-payload>
</dw:transform-message>
<ws:consumer config-ref="Web_Service_Consumer" operation="employeeDetails" doc:name="Web Service Consumer"/>
</flow>
It showed the below error:
Exception while executing:
[row,col]: [1,1]
Unexpected character '{' (code 123) in prolog; expected '<'
at [row,col {unknown-source}]: [1,1].
Updated answer:
<dw:transform-message metadata:id="XXXXX" doc:name="Transform Message">
<dw:set-payload><![CDATA[
%output application/xml skipNullOn="everywhere"
%namespace ns0 localhost/getDetails:getDetailsWSD
---
{
ns0#getDetails: {
getDetailsOrder: {
ID: payload.ns0#getDetails.getDetailsOrder.ID,
AllData: payload.ns0#getDetails.getDetailsOrder.AllData
}
}
}]]>
</dw:set-payload>
</dw:transform-message>
In your scenario: you are passing a body in XML format and sometimes an empty body in your Postman requests.
Passing an empty body results your payload to be {NullPayload}. To handle this, we have to remove explicitly defining the input mime type: <dw:input-payload mimeType="application/xml"/>.
In your transformation: ID: payload.ns0#getDetails.getDetailsOrder.ID,. You are retrieving a value from an empty payload and this will fail. To avoid failing, we have added: skipNullOn="everywhere". You can read more about it here.
I have tried the transformation myself which results to this:
<?xml version='1.0' encoding='UTF-8'?>
<ns0:getDetails xmlns:ns0="http://localhost/getDetails:getDetailsWSD">
<getDetailsOrder/>
</ns0:getDetails>
I think we are done with your initial issue regarding transformation of your empty payload. Your concern now is consuming the web service.
Thank you.

Customizing Spring Integration Web Service SOAP Envelope/Header

I am trying to send a SOAP request using Spring Integration like
<int:chain input-channel="wsOutChannel" output-channel="stdoutChannel">
<int-ws:header-enricher>
<int-ws:soap-action value="..."/>
</int-ws:header-enricher>
<int-ws:outbound-gateway
uri="..."/>
</int:chain>
but you can only add the SOAP body, and Spring Integration adds the envelope, header, and body tags like
<SOAP-ENV:Envelope>
<SOAP-ENV:Header>
<SOAP-ENV:Body>
...
</SOAP-ENV:Body>
<SOAP-ENV:Header>
</SOAP-ENV:Envelope>
I need to customize the envelope and header tags with specific attributes, for example:
<soapenv:Envelope attribute1="value1" attribute2="value2">
and child elements, for example:
<soapenv:Header>
<child>...<child>
<soapenv:Header>
Is this possible with Spring Integration Web Services, or should I not use int-ws:outbound-gateway and take a different approach?
You can add a ClientInterceptor (via the interceptor attribute) which allows you to modify the request before it's sent out.
EDIT
#Artem's suggestion is simpler but the interceptor gives you access to the response too; but either way, the code is similar.
For the interceptor:
public class MyInterceptor extends ClientInterceptorAdapter {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
SoapMessage request = (SoapMessage) messageContext.getRequest();
SoapEnvelope envelope = request.getEnvelope();
envelope.addAttribute(new QName("foo"), "bar");
SoapHeader header = envelope.getHeader();
header.addHeaderElement(new QName("http://fiz/buz", "baz"));
return super.handleRequest(messageContext);
}
}
For the callback version:
#Override
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SoapEnvelope envelope = ((SoapMessage) message).getEnvelope();
envelope.addAttribute(new QName("foo"), "bar");
SoapHeader header = envelope.getHeader();
header.addHeaderElement(new QName("http://fiz/buz", "baz"));
}
I thing you can inject WebServiceMessageCallback:
<xsd:attribute name="request-callback" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Reference to a Spring Web Services WebServiceMessageCallback. This enables changing
the Web Service request message after the payload has been written to it but prior
to invocation of the actual Web Service.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.ws.client.core.WebServiceMessageCallback"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
and cast the message to the SoapMessage and use its getEnvelope() to customize a desired way.

Spring Integration should route Message (with SOAP Headers)

I am trying to write configure a gateway, which should take a complete SOAP Message and then delegate it to another SOAP Provider (incl. all SOAP headers of the first request).
What I have done so far:
1) web.xml
MessageDispatcherServlet with Mapping:
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/appservices/*</url-pattern>
</servlet-mapping>
2) Configuration with an Endpoint-Mapping
<bean class="org.springframework.ws.server.endpoint.mapping.UriEndpointMapping">
<property name="defaultEndpoint" ref="ws-in-gw"/>
</bean>
3) Configuration of Spring Integration inbound-gateway and outbound-gateway
<int-ws:inbound-gateway id="ws-in-gw"
request-channel="in"
reply-channel="out"
mapped-request-headers="*" />
<int:channel id="in" />
<int:channel id="out" />
<int-ws:outbound-gateway
id="ws-out-gw-status"
request-channel="in-status"
reply-channel="out-status"
uri="http://${delegationServer}/${delegation.contextroot}/soap/AnotherService"
interceptor="soapEnricher"
</int-ws:outbound-gateway>
<bean id="soapEnricher" class="foo.bar.SoapHeaderEnricher" />
public class SoapHeaderEnricher implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
try {
SoapMessage soapMessage = (SoapMessage) messageContext.getRequest();
SoapHeader sh = soapMessage.getSoapHeader();
// can use sh.addHeaderElement(new QName(...)) now, but where are the original Headers???
} catch () {
}
}
My first Problem was, that the original SOAP Headers had been cut of, so I introduced the ' mapped-request-headers="*" ' attribute at the inbound gateway.
When I now configure a wire-tap, I see the Headers (myToken:MySecretToken) are received:
DEBUG 10:46:53 - [Payload DOMSource content=javax.xml.transform.dom.DOMSource#24a6ce98][Headers={errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#43456ff4, myToken:MySecretToken=org.springframework.ws.soap.saaj.SaajSoapHeaderElement#3b91ead, ...}]
This is the SOAP Message for my test:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:stat="http://status.service.promakler.provinzial.com/">
<soapenv:Header>
<myToken:MySecretToken xmlns=""
xmlns:myToken="http://foo.bar">12345</myToken:MySecretToken>
</soapenv:Header>
<soapenv:Body>
<stat:getStatus/>
</soapenv:Body>
</soapenv:Envelope>
So the Headers are now in my Message, but in the ClientInterceptor, there is no way to get the Headers (just the payload)?! I can add new Headers, but how can I get the original Header?
Can anybody give me a hint (or perhaps there is even a quiet simpler solution??)
Regards
Timo
Try to introduce a custom extension of DefaultSoapHeaderMapper and override populateUserDefinedHeader to extract those SaajSoapHeaderElement from the MessageHeaders and populate them to the SoapHeader. And finally inject your solution to the header-mapper of your <int-ws:outbound-gateway>.

Example for adding attachment to email at mule

I would like to ask how to add file as attachment in Mule (3.4.0)?
I tried many solutions and googled a lot but haven't found anything good.
This is what I have now (last try before posting here):
<sub-flow name="sendBackMail" doc:name="sendBackMail">
<set-attachment attachmentName="changed.xml" value="#[payload]" contentType="text/xml" doc:name="Attachment"/>
<logger message="Attachment ok" level="INFO" doc:name="Logger"/>
<file:file-to-byte-array-transformer doc:name="File to Byte Array"/>
<logger message="Attachment ok. Message: #[message]" level="INFO" doc:name="Logger"/>
<smtps:outbound-endpoint host="${mailSMTP}" port="${mailSendPort}"
user="${mailUser}" password="${mailPass}" to="${receiver}"
from="${mailUser}" responseTimeout="60000" doc:name="SMTP"
connector-ref="SMTP" mimeType="text/xml" subject="msp2bass" >
</smtps:outbound-endpoint>
</sub-flow>
It sends mail but I get content of xml file as body of mail.
What should I do/change so that mail would be sent as attachment. I get file from another sevice, do XSLT on it and then I should send it to some mail.
Any more info I should provide?
Thank you!
EDIT
How I call bean:
<spring:bean id="SetAttachment" name="SetAttachment" class="si.irose.msp.cust.bass.SetAttachment">
</spring:bean>
<component doc:name="Java">
<spring-object bean="SetAttachment"/>
</component>
Java class:
package si.irose.msp.cust.bass;
import org.mule.api.MuleEventContext;
import org.mule.api.MuleMessage;
import org.mule.api.lifecycle.Callable;
public class SetAttachment implements Callable{
private MuleMessage mule;
private String name;
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
mule = eventContext.getMessage();
String tryit="routeid";
for (int i=0;i<mule.getInvocationPropertyNames().toArray().length;i++) {
if (mule.getInvocationPropertyNames().toArray()[i].equals(tryit)) {
name=mule.getInvocationProperty(mule.getInvocationPropertyNames().toArray()[i].toString()).toString();
break;
}
}
mule.addOutboundAttachment(name, mule.getInvocationProperty(name), "text/xml");
return null;
}
}
Ok issue solved.
When you read from file inbound or generate with quartz (string or file) you can add "Attachment" directly BUT if you do an XSLT transformation and then try to send that payload via smtp, then you need to add "Object to String" transformer before attachment.
Final working solution:
<sub-flow name="sendBackMail" doc:name="sendBackMail">
<object-to-string-transformer doc:name="Object to String"/>
<set-attachment attachmentName="changed.xml" value="#[payload]" contentType="text/xml" doc:name="Attachment"/>
<logger message="Attachment ok" level="INFO" doc:name="Logger"/>
<file:file-to-byte-array-transformer doc:name="File to Byte Array"/>
<logger message="Attachment ok. Message: #[message]" level="INFO" doc:name="Logger"/>
<smtps:outbound-endpoint host="${mailSMTP}" port="${mailSendPort}"
user="${mailUser}" password="${mailPass}" to="${receiver}"
from="${mailUser}" responseTimeout="60000" doc:name="SMTP"
connector-ref="SMTP" mimeType="text/xml" subject="msp2bass" >
</smtps:outbound-endpoint>
</sub-flow>
I haven't checked yet what transformer you need to apply if you do any other job instead of XSLT so if anyone wish to add some knowledge to this then please do so and add comment.
You need to use set-payload before the smtps:outbound-endpoint to set the body of the email to whatever you want, otherwise it will contain the same value attached with set-attachment.
Also remove the file:file-to-byte-array-transformer: it's unclear what it's there for.

MULE ESB : Binding multiple Web Services to one Client

I have a client which connects to a Web service to get some information. I have a requirement where I have to send the same information to multiple services using different ports. To solve this without modifying the client code I found MULE ESB, which is supposed to do exactly what I need.
I've found a guide where I could connect one client to one service using MULE ESB and one port, but I cant find a way to chain the services so they all listen to one port but have different themselves.
This is how it's supposed to look like:
UPDATE :
here is my current Mule Applications config :
<mule xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:http="http://www.mulesoft.org/schema/mule/http" 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" version="CE-3.2.1" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
<flow name="flows1Flow1" doc:name="flows1Flow1">
<http:inbound-endpoint exchange-pattern="request-response" address="http://localhost:4433/miniwebservice" mimeType="text/xml" doc:name="HTTP"/>
<http:outbound-endpoint exchange-pattern="request-response" address="http://localhost:4434/miniwebservice?wsdl" mimeType="text/xml" doc:name="HTTP"/>
</flow>
</mule>
Here is the WebService :
Client :
package miniwebservice;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
public class TestWsClient
{
public static void main( final String[] args ) throws Throwable
{
String url = ( args.length > 0 ) ? args[0] : "http://localhost:4434/miniwebservice";
Service service = Service.create(
new URL( url + "?wsdl" ),
new QName( "http://miniwebservice/", "HalloWeltImplService" ) );
HalloWelt halloWelt = service.getPort( HalloWelt.class );
System.out.println( "\n" + halloWelt.hallo( args.length > 1 ? args[1] : "" ) );
}
}
Server :
package miniwebservice;
import javax.xml.ws.Endpoint;
public class TestWsServer
{
public static void main( final String[] args )
{
String url = ( args.length > 0 ) ? args[0] : "http://localhost:4434/miniwebservice";
Endpoint.publish( url, new HalloWeltImpl() );
}
}
InterfaceImpl :
package miniwebservice;
import javax.jws.WebService;
#WebService( endpointInterface="miniwebservice.HalloWelt" )
public class HalloWeltImpl implements HalloWelt
{
public String hallo( String wer )
{
return "Hallo " + wer;
}
}
interface :
package miniwebservice;
import javax.jws.*;
#WebService
public interface HalloWelt
{
public String hallo( #WebParam( name = "wer" ) String wer );
}
If I start the Server and the Mule aplication and try to reach http://localhost:4434/miniwebservice?wsdl ower http://localhost:4433/miniwebservice I get the folowing Exception in my Browser (FireFox 8.0) :
Couldn't create SOAP message due to exception: XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,1]
Message: Content is not allowed in prolog.
I just started to work with Mule so I thouth that this would be enouth to get redirect mule to the Service to get the wsdl but its seems like its a bit complicatet.
Disclaimers:
This is not the final solution to the whole problem, which includes dispatching to several services and aggregating results, but a step in the right direction.
This is not representative of how web service proxying is done in Mule (which is way simpler) but a barebone approach to HTTP request routing so aggregation can be added.
Since you want to forward HTTP GET requests to the ?wsdl processor and HTTP POST SOAP request to the web service, you need to handle the target HTTP method and request URI propagation yourself:
<flow name="flows1Flow1">
<http:inbound-endpoint exchange-pattern="request-response"
address="http://localhost:4433/miniwebservice" />
<message-properties-transformer scope="outbound">
<add-message-property key="http.method" value="#[header:INBOUND:http.method]" />
</message-properties-transformer>
<logger level="INFO" category="ddo" />
<http:outbound-endpoint exchange-pattern="request-response"
address="http://localhost:4434#[header:INBOUND:http.request]" />
</flow>
(tested and validated with TestWsClient and TestWsServer)