Scenario: I have to call a WSDL based webService and parse its response.
Problem: I am having problem to update the SOAPMessage SOAP Header & SOAP Body OR SOAP Enevelope, which I can create using the classes generated from the WSimport tool.
I have generated java classes for the provided wsdl using WSimport tool. There were many classess generated and among them I found one class which has objects to create SOAP Header, Body and other details as shown in the picture. My problem is that when I generate my soapbody and header from the provided class, I am not able to add it to the SOAP Message which i want to post to the webservice in order to get the response. Is there any method that i need to create to generate SOAP message ?
{
Body mySoapBody = new Body();
Header mySoapHeader = new Header();
Envelope mySoapEnevelope = new Envelope();
//Generate SOAP Body
mySoapBody.getAny().add(objofIdentifyCustomerClass);
//Generate SOAP Header
mySoapHeader.getAny().add(emfHeader);
//Generate SOAP Enevelope
mySoapEnevelope.setBody(mySoapBody);
mySoapEnevelope.setHeader(mySoapHeader);
//This is an Issue, Cant add generated Header to the SOAP Message
SOAPMessage soapMsg= MessageFactory.newInstance().createMessage( );
//MessageFactory factory = MessageFactory.newInstance();
//SOAPMessage message = factory.createMessage();
soapMsg.getSOAPBody().addDocument(getRE02XMLBodyMsg(ciscoRE02Request));
// How to add/update SOAP Header in the SOAPMessage ????
}
I guess I was not understanding the process correctly. I read blogs of this location which helped me resolve the problem and made the code efficient:
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client/
If you have problem writing to a WebService I highly encourage you to read this article.
Regards,
Nevin
Related
I want to read Soap response - how can i convert soap response to pojos(Class objects)
Also i want to send soap post request - how can i convert class objects to soap request.
I need both ways, can you please help here
If you want to marshal and unmarshal a SOAP message to POJOs, you can use xjc to generate JAXB bindings from the schema https://www.w3.org/2003/05/soap-envelope/.
However SOAP is not usually unmarshaled using JAXB, but through a specialized framework: SOAP with Attachments API for Java. This framework can also unmarshal SOAPs with attachments: it's a multipart/related MIME document with an XML SOAP message and a series of attachments.
To deserialize using SAAJ you use a MessageFactory and provide the MIME headers of the message and an input stream:
final InputStream is = ...;
final MimeHeaders mimeHeaders = ...;
final SOAPMessage soap = MessageFactory.newInstance().createMessage(mimeHeaders, is);
If you have SOAPMessage, you can access the parts you are interested in through getSOAPPart, getSOAPBody, getSOAPHeader which return you DOM interfaces, which you can transform to POJOs using JAXB.
To serialize you just have to create a new SOAPMessage, fill it and call the writeTo method:
final SOAPMessage soap = MessageFactory.newInstance().createMessage();
... // fill the message
final OutputStream os = ...;
soap.writeTo(os);
I'm trying to use Opentext Content Web Services(CWS) from my axis2-based web-service.
This is a piece of code that creates a proxy client to CWS and passes an authentication token in a header.
DocumentManagement_Service docManService = new DocumentManagement_Service();
DocumentManagement docManClient = docManService.getBasicHttpBindingDocumentManagement();
try
{
// The namespace of the OTAuthentication object
final String ECM_API_NAMESPACE = "urn:api.ecm.opentext.com";
// Create a SOAP header
SOAPHeader header = MessageFactory.newInstance().createMessage().getSOAPPart().getEnvelope().getHeader();
// Add the OTAuthentication SOAP header element
SOAPHeaderElement otAuthElement = header.addHeaderElement(new QName(ECM_API_NAMESPACE, "OTAuthentication"));
// Add the AuthenticationToken SOAP element
SOAPElement authTokenElement = otAuthElement.addChildElement(new QName(ECM_API_NAMESPACE, "AuthenticationToken"));
authTokenElement.addTextNode(authToken);
// Set the SOAP header on the docManClient
String ENDPOINT_ADDRESS_PROPERTY = WSBindingProvider.ENDPOINT_ADDRESS_PROPERTY;
((WSBindingProvider) docManClient).setOutboundHeaders(Headers.create(otAuthElement));
}
catch (SOAPException e)
{
System.out.println("Failed to set authentication SOAP header!\n");
System.out.println(e.getMessage());
System.out.println(e.getStackTrace());
return;
}
This code works fine when executed from simple java application. In that case docManClient is a SEIStub object and setOutboundHeaders method works after casting to WSBindingProvider.
But when this code is executed inside my axis2 webservice, docManClient is JAXWSProxyHandler object and it can not be casted into WSBindingProvider nor execute setOutboundHeaders method.
So my question is - How do I pass my header with AuthElement using JAXWSProxyHandler (do the same as setOutBoundHeaders method do) OR Can I somehow convert JAXWSProxyHandler object to SEIStub object?
The problem occurs because you are using an API that is specific to the JAX-WS implementation in the JRE. However, when running on Axis2, the JAX-WS implementation provided by Axis2 will be used instead. That implementation supports a different set of API extensions.
What this means is that your code is not portable across different JAX-WS implementations. You have two options:
Make it portable by only using standard APIs. In your case this would require implementing a JAX-WS handler that adds the header. To pass the authToken to the handler, you would cast the client to BindingProvider and add the data to the request context.
Remove the axis2-jaxws JAR from your Axis2 deployment so that your code will use the JAX-WS implementation from the JRE. Of course this won't work if the service itself is deployed as a JAX-WS service. Unfortunately the code snippet doesn't show whether that's the case or not.
How do I remove a
<soapenv:Header xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
node from a response message using Java (or web service configuration)?
I don't want to send back user name and password that is displayed in the header. Do I create a class to extend AbstractSoapInterceptor?
I am using `cxf bus to configure my web service.
I donĀ“t know how are you receiving the SOAP message, but If you can use (or instantiate) a javax.xml.soap.SOAPMessage you remove the header element or attribute that is bothering you:
// Removes the attribute "key" from the message header
message.getSOAPHeader().removeAttribute("key");
Anyway, reusing the same message sounds weird to me, perhaps you should consider creating a new fresh response message:
This statement create a brand new message:
MessageFactory mf = MessageFactory.newInstance();
SOAPMessage message = mf.createMessage(headers, in)
This one, from Mime headers and an inputstream:
MessageFactory mf = MessageFactory.newInstance();
SOAPMessage message = mf.createMessage(headers, in)
I'm trying to send an attachment to client from Axis2 web service. The problem is that the message context, which client receives from the service, does not contain any attachments, though the last one seems to add it.
Here is the brief code of both sides.
Service:
MessageContext inMC = MessageContext.getCurrentMessageContext();
OperationContext operationContext = inMC.getOperationContext();
MessageContext outMC = operationContext.getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
DataHandler handler = new DataHandler (new FileDataSource("C://goods.xml"));
String attachID = outMC.addAttachment(handler);
OMElement idElem = factory.createOMElement("doc", ns);
idElem.addAttribute("href", "cid:" + attachID, ns);
Client (trying to receive attachment):
MessageContext mcResponse = operationClient.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
SOAPBody body = mcResponse.getEnvelope().getBody();
OMElement attachElem = body.getFirstChildWithName (new QName("doc"));
String attachID = attachElem.getAttributeValue (new QName("href"));
attachID = attachID.replaceFirst("cid:", "");
DataHandler dataHandler = mcResponse.getAttachment(attachID);
getAttachment() method returns null. In case of debugging the client application, IDE shows, that attachment map in input message context does not contain any elements (size=0). The OMElement object (idElem), which contains attachment id, is received and read by client normally (debug showed cid). The parameters enableSwA, cacheAttachments, attachmentDIR, sizeThreshold are set both in services.xml and programming part of client. What is wrong with the message context?
Thanks a lot for any suggestions.
Upd: TCPmon showed the following content.
Request to service:
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><getXMLFile xmlns="http://axis2.apache.org"><filename>goods.xml</filename></getXMLFile></soapenv:Body></soapenv:Envelope>
I guess it's ok :)
Response from service:
109
<?xml version='1.0' encoding='UTF-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><doc href="cid:d06f3b36afdfcbd2e135ecfbcad05ee602661262b059ed38#apache.org"></doc></soapenv:Body></soapenv:Envelope>
0
I apologize for a bit simple questions, but where the attachment should be reflected? I guess, if the service send an attachment, the SOAP message contains binary data, isn't it?
I checked also for putting the attachment into message context on service side - it's OK, I can get it there back from context after adding.
you can use tcpmon[1] to trace the http message and isolate the problem.
Anyway the better method for handling attachments is to use MTOM. Which can be used with data binding frameworks like ADB[2], or with POJO as well.
thanks,
Amila.
[1] http://ws.apache.org/commons/tcpmon/
[2] http://amilachinthaka.blogspot.com/2009/01/using-mtom-with-axis2.html
The problem was solved. The trouble was on the service side. TCPmon showed there was no attachments in responce message. However, the same example service works fine. After checking and comparing every operation on my service, it came out that programming part is not the reason either. The only one was left - service settings. So, the reason is that settings fields in service.xml file on the service, which require boolean type, does not allow any additional symbols. My mistake:
Incorrect:
<parameter name="enableSwA">
true
</parameter>
Correct:
<parameter name="enableSwA">true</parameter>
i have been trying to send SOAP attachment using Camel+SpringWS.
Following is code inside my RouteBuilder class, endpoint is working properly i have already got empty SOAP response :
from("spring-ws:rootqname:{http://www.lala.org/Bean}GetBookRequest?endpointMapping=#endpointMapping").process(new Processor() {
public void process(Exchange arg0) throws Exception {
//SpringWebserviceMessage msg = (SpringWebserviceMessage) arg0.getIn(); // --> SpringWebserviceMessage instance
arg0.getOut().addAttachment("test",new DataHandler(new FileDataSource("c:/CompanyLogo.jpg")));
}
});
I have also tried adding attachment through SpringWebserviceMessage, but it doesn't make any effect.
Is anyone know how to add SOAP Attachment with Camel+SpringWS?
I'm not familiair with Camel but I do remember a case where I had to place a SOAP attachment in the message with spring-ws as well. The trick for me was to use a SaajSoapMessage.
Below is a snippet on how to attach a file using spring-ws in java:
JAXBElement<ShowCandidateType> responseElement = (JAXBElement<ShowCandidateType>) kandidaatServiceTemplate.marshalSendAndReceive(
objectFactory.createProcessCandidate(processCandidate),
new WebServiceMessageCallback() {
public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
SaajSoapMessage saajMessage = (SaajSoapMessage) message;
//Use the file name as the contentId
saajMessage.addAttachment(file.getName(), file);
}
}
);
The key was implementing the doWithMessage and casting the WebServiceMessage to a SaajSoapMessage.
The Camel component for Spring-WS doesn't contains any attachment / header support that was officially released.
However, the latest snapshot of camel-spring-ws contains the patch that address this issue.
Look here: https://issues.apache.org/jira/browse/CAMEL-5724
Here is current doc of the proposed functionality
The header and attachment propagation
The endpoint will use so called "hook" the MessageFilter (default implementation is provided by BasicMessageFilter) to propagate the exchange headers and attachments into WebSdrviceMessage response.
Now you can use
exchange.getOut().getHeaders().put("myCustom","myHeaderValue")
exchange.getIn().addAttachment("myAttachment", new DataHandler(...))
Note: If the exchange header in the pipeline contains text, it generates Qname(key)=value attribute in the soap header.
Recommended is to create a QName class directly and put into any key into header.
Don't know how your webservice expects the attachment. I had a requirement to send attachment using Camel + Soap. If you plan to use '#mtom', you need to add a binary message part and then you need to add the attachment, with the reference to the binary part.
Or else, if your webservice is using base64 encoded attachments. You simply need to set your file contents, base64 encoded to the attachment field name in message.
If you can share the wsdl, I will be able to help you better.