Win a copy of The Java Performance Companion this week in the Performance forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Understanding how to write spring ws using JAXB

 
Milly Biswas
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,

As everyone introduces, I am new to webservice and need some clarifications/advice.

A little background:I created a UploadService. The purpose is to upload files/zip files from Client Server. What I did to create the ws is
1. Create a schema file (xsd) and generate the classes using the JAXB2.0. [Following the spring-ws and using Jax2b for marshalling the request]
2. In the xsd file, I have UploadFileRequest element, which contains the details of the File, which will be uploaded.
<complexType name="UploadFile">
<sequence>
<element name="name" type="string"/>
<element name="file" type="base64Binary" xmime:expectedContentTypes="application/octet-stream"/>
</sequence>
</complexType>
3. In my client project, I invoke the "webServiceTemplate.marshalSendAndReceive(request)".
4. Also I created an UploadFault class which extends java.lang.Exception. And I have the @WebFault Annotation to it e.g[@WebFault(name="UploadException", faultBean="UploadException",targetNamespace="http://www.example.org/UploadFileSchema")]. And set the UploadException object in its contructor along with some message.
5. The UploadException class is a bean for setting errorMessage.

Everything works fine and my files are transfered.

Now the questions:
1. Is using xmime:expectedContentTypes="application/octet-stream" , the correct/best way to do it? I tried using "application/zip" but it did not work as the DataHandler object contains the contentType as application/octet-stream (in the endpoint class).
2. When "webServiceTemplate.marshalSendAndReceive(request)" is invoked, what happens exactly? Does the request become a part of the SoapBody? I tried to debug, and found that the datahandler is passed as an attachment to the SoapPart. I am not sure here, how this method works, whether the request is a SoapBody?
3. When I throw a UploadException, from my ServiceImpl class. I do it the following way:
UploadException uploadException = jAXB_ObjectFactory.createUploadException();
uploadException.setMessage("Some Error Msg");
throw new UploadFault("Error in Validating File.", uploadException);
3.a) Now when testing for this exception, I expect that the exception thrown will be UploadFault at the client side. But the exception thrown is SoapFaultClientException. Am I missing some configuration? Do I need to add UploadFault to SoapFault separately?

Please help.

Thanks
Milly
 
H Paul
Ranch Hand
Posts: 471
4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
1.
http://jax-ws.java.net/nonav/2.1.4/docs/mtom-swaref.html
2.1 xmime:expectedContentType to Java type mapping

MIME Type/Java Type

image/gif
java.awt.Image

image/jpeg
java.awt.Image

text/plain
java.lang.String

text/xml or application/xml
javax.xml.transform.Source

*/*
javax.activation.DataHandler

If I understand correctly the above, should xmime:expectedContentTypes="*/*" work?

2.
Have you tried to post Spring related code in Spring forum as you're using is SPRING-WS?
 
Milly Biswas
Greenhorn
Posts: 4
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Paul,

Thanks for the link... I will try to use the xmime:expectedContentTypes="*/*", it should work. Using application/octet-stream will be the content type of the Data Handler object in any case. But I will test the difference by using just xmime:expectedContentTypes="*/*".


And yesterday, I was able to clear my doubts. So here it goes...
1. Is using xmime:expectedContentTypes="application/octet-stream" , the correct/best way to do it?
Not sure yet, but will try the above mentioned suggestion.
2. When "webServiceTemplate.marshalSendAndReceive(request)" is invoked, what happens exactly? Does the request become a part of the SoapBody?
Yes it does. Initially I was trying to debug and find the content of the SoapMessage, but when I printed the SoapMessage to a file, I was able to verify that these request object we sent via the marshalling, becomes a part of the SoapBody.

NOTE: In order to print the request/response/fault object, I have written a custom interceptor class which implements the org.springframework.ws.server.EndpointInterceptor Interface and implemented the methods, handleRequest,handleResponse and handleFault. I invoke the following method from these individual handler method. Also in the spring-servlet.xml this custom interceptor nees to be included in the org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping.

private void writeSoapMessage(MessageContext messageContext, String fileName) {
try {
SoapMessage soapMessage = null;

if (fileName.equals("Soap_Request.xml")) {
soapMessage = (SoapMessage) messageContext.getRequest();
} else if (fileName.equals("Soap_Response.xml")) {
soapMessage = (SoapMessage) messageContext.getResponse();
} else if (fileName.equals("Soap_Fault.xml")) {
soapMessage = (SoapMessage) messageContext.getResponse();
}

File msgFile = new File("D:\\", fileName);
FileOutputStream fos = new FileOutputStream(msgFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream();

soapMessage.writeTo(baos);
baos.writeTo(fos);

} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

3.a) Now when testing for this exception, I expect that the exception thrown will be UploadFault at the client side. But the exception thrown is SoapFaultClientException. Am I missing some configuration? Do I need to add UploadFault to SoapFault separately?

Well now my requirement has changed, i do not need to throw my custom exception to the client anymore. The client is ok with the SoapFaultClientException. I am still not sure how to achieve this, may be will test later.
As far as configuration goes, I did the following:
1. Create CustomException class, which extends RuntimeException.
2. Add @SoapFault(fault= FaultCode.CLIENT) annotation to it.
3. Add the following to the spring-servlet.xml. This will resolve the @SoapFault annotation mentioned above.
<bean class="org.springframework.ws.soap.server.endpoint.SoapFaultAnnotationExceptionResolver" />
4. Throw the CustomException, when required. And the spring-ws framework takes care of the rest. This exception becomes a part of the SoapFault. The exception message, will be the FaultString, and the fault code = CLIENT.

Hope this explanation helps other newbie like me.





 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic