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.
Related
Here I am trying to convert Json data to CSV format and finally send this file to Ofbiz server api but the api endpoint require some authentication content when I send parameter in URL I got the output below.
{"_ERROR_MESSAGE_":"Error calling event: org.apache.ofbiz.webapp.event.EventHandlerException: Found URL parameter [configId] passed to secure (https) request-map with uri [uploadAndImportFileFromCSVFile] with an event that calls service [uploadAndImportFile]; this is not allowed for security reasons! The data should be encrypted by making it part of the request body (a form field) instead of the request URL. Moreover it would be kind if you could create a Jira sub-task of https://issues.apache.org/jira/browse/OFBIZ-2330 (check before if a sub-task for this error does not exist). If you are not sure how to create a Jira issue please have a look before at https://cwiki.apache.org/confluence/display/OFBIZ/OFBiz+Contributors+Best+Practices Thank you in advance for your help.","sessionId":"someId.jvm1","removePathAlias":false,"loggedIn":true,"USERNAME":"__","_LOGIN_PASSED_":"TRUE","webSiteId":"API"}
After that I used MultipartBuilder to send request below.
exchange.getIn().setHeader("bearer",token);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
File file =new File("//home/r2/Desktop/ofBizFile/orderFile.csv");
builder.addPart("configId",new StringBody("CON_ID"));
builder.addPart("fileTypeEnumId",new StringBody("CSV_FILE"));
builder.addPart("_uploadedFile_contentType",new StringBody("text/csv"));
builder.addPart("uploadedFile",new FileBody(file));
exchange.getIn().setBody(builder.build());
I also tried something like this.
exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1");
exchange.getIn().setHeader(Exchange.HTTP_QUERY,"USERNAME=abc&PASSWORD=bc69");
exchange.getIn().setBody("configId=CON_ID&fileTypeEnumId=CSV_FILE");
Here is my camel route
//Route 1
from("couchdb:http://localhost:5984/order")
.process(new JsonToCsvProcessor())
//Storing file into local directory
.to("file:/home/r2/Desktop/ofBizFile?fileExist=append&fileName=order-${date:now:yyyyMMdd}.csv");
.to("direct:jsonToCsv");
//Route 2
from("direct:jsonToCsv")
.setHeader(Exchange.HTTP_QUERY,constant("USERNAME=__&PASSWORD=__"))
//For get token
.to("https4://SomeAddress.com/centerAPI/getAuthenticationToken")
//Get the token and set required parameter for route 3
.process(new ProcessorGetToken())
.to("direct:hold");
//Route 3
from("direct:hold")
.setHeader(Exchange.HTTP_QUERY,constant("USERNAME=__&PASSWORD=__"))
.to("https4://SomeAddress.com/centerAPI/uploadAndImportFileFromCSVFile?throwExceptionOnFailure=false")
//How I know the file is submited successfuly ?
.to("stream:out").end();
So the problem is how I can send data inside the body in Route2 ProcessorGetToken for next Route3 ?
I'll give a shot into the dark here. Reading your error message:
The data should be encrypted by making it part of the request body (a form field) instead of the request URL
Don't you have a documentation about this integration? I think you need more clarification about this process and what's need to encrypt your data before sending it.
Also, try to set the Exchange.HTTP_METHOD to POST into your route, like this:
exchange.setProperty(Exchange.CHARSET_NAME, "ISO-8859-1");
exchange.getIn().setHeader(Exchange.HTTP_METHOD, "POST");
exchange.getIn().setHeader(Exchange.HTTP_QUERY,"USERNAME=abc&PASSWORD=bc69");
exchange.getIn().setBody("configId=CON_ID&fileTypeEnumId=CSV_FILE");
Take a look into this unit test to see more examples sending data over HTTP. There's also many other tests there.
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
I am trying to get the raw XML response from a web service, instead of the usual set of POJOs.
I am using a webservice client that I generated (so I have access to the client's code) from a WSDL and some schemas. The client is generated in RAD 7.5, I think using JAX-WS. I've been looking at the client code itself, but I'm not even sure if the client code ever handles raw XML or if it passes it off to other libraries.
You can do it using
javax.xml.ws.handler.soap.SOAPHandler<javax.xml.ws.handler.soap.SOAPMessageContext>
you can simply get message using SOAPMessageContext#getMessage() and convert message to String using method
public static String getXmlMessage(SOAPMessage message) throws Exception
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
message.writeTo(os);
final String encoding = (String) message.getProperty(SOAPMessage.CHARACTER_SET_ENCODING);
if (encoding == null)
{
return new String(os.toByteArray());
}
else
{
return new String(os.toByteArray(), encoding);
}
}
Also you can read here about SOAP handler on client side
Article
It's not widely documented, but you can use the Dispatch interface to implement JAXWS clients which work directly w/ the XML. Here and here are some articles for getting started.
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'm testing an application sending a mail with attachment in a integration environment. For this i'm setting up a fake smtp mail server (http://quintanasoft.com/dumbster/) and configure my application to use it. At the end of my test i want to check if my application has sent the email via my fake mail server and also want to know, if the content (at least the attached file) is exactly that i'm expecting.
Dumpster is wrapping these mails into its own objects just containing header key-value pairs and the body as plain text. My question is how i can easily part the mail body to get and evaluate the attached file content from it.
Attach a file that you are certain of the mime-types in javamail. Sending the email over smtp allows us to make use of the fact that there is a string of data inside the body of the email before the bytes of the file. The bytes of the file are base64 and get included in the main chunk of the characters of the email.
private static final String YOUR_ATTACMETN_DATA = "Content-Type: image/jpeg; name=Invoice.jpgContent-Transfer-Encoding: base64Content-Disposition: attachment; filename=image.jpg";
#Before
public final void setup() throws UserException{
server = SimpleSmtpServer.start();
}
#After
public final void tearDown(){
server.stop();
}
#Test
public void test_that_attachment_has_been_recieved() throws IOException, MessagingException {
email = getMessage();
YourEmailSendingClass.sendEmail(email);
Iterator<SmtpMessage> it = server.getReceivedEmail();
SmtpMessage recievedMessage = (SmtpMessage)it.next();
assertTrue(recievedMessage.getBody.contains(YOUR_ATTACHMENT_DATA)));
}
Here is another is a page of someone who did something similar to this in greater detail.
http://www.lordofthejars.com/2012/04/why-does-rain-fall-from-above-why-do.html
As a place to start (not sure if there are easier ways to do it), consider using the JavaMail API. Try to grab the whole message (including headers) -- probably with SmtpMessage.toString(), wrap it in some new ByteArrayInputStream(smtpMessage.toString().getBytes()), and pass it to a javax.mail.internet.MimeMessage.
(NOTE: I'm not that familiar with the MIME standard and I don't know if you should use the getBytes(Charset) overload here).