Hello,

I aswell added comments inline (see bellow)


Sergey Beryozkin-2 wrote:
> 
> 
> I have the use case where I have to provide a RESTfull webservice. This
> use
> case has a number of constraints:
> - contract-first (as in, first - definition (WSDL for SOAP, user model for
> REST), then - implementation (ws implementation and JAXB generated stuff))
> - same webservice implementation class for both - SOAP and REST
> 
>> S.B : I'm wondering, should we start thinking about supporting WSDL2 for
>> cases like this one be supported ?
> 
>>> reinis: For my use case it would be very welcome. Basically, any
>>> SOA-like (governance)process 
>>> attempts to push "contract-first". I could imagine a reasonable number
>>> of commercial projects where 
>>> this would be greatly appretiated aswell.
> 
> WSDL (trimmed) looks like this:
> ...
> <wsdl:types>
> <xsd:schema xmlns="http://www.w3.org/2001/XMLSchema";
> targetNamespace="http://mynamespace";
> elementFormDefault="qualified" xmlns:msg="http://myothernamespace";
> xmlns:emailbus="http://mythirdnamespace";>
> <xsd:import schemaLocation="myothernamespace.xsd"
> namespace="http://myothernamespace"; />
> <xsd:import schemaLocation="mythirdnamespace.xsd"
> namespace="http://mythirdnamespace"; />
> <xsd:element name="sendEmail">
> <xsd:complexType>
> <xsd:sequence>
> <xsd:element name="msgCtx" type="msg:ServiceMessageContext"
> minOccurs="1" />
> <xsd:element name="emailMessage" type="emailbus:EmailMessage"
> minOccurs="1" />
> </xsd:sequence>
> </xsd:complexType>
> </xsd:element>
> </xsd:schema>
> </wsdl:types>
> 
> <wsdl:message name="sendEmailIn">
> <wsdl:part element="tns:sendEmail" name="data" />
> </wsdl:message>
> ...
> 
> msgCtx (trimmed) looks like this:
> <complexType name="ServiceMessageContext">
> <sequence>
> <element maxOccurs="1" minOccurs="1" name="messageId" type="string" />
> <element maxOccurs="1" minOccurs="0" name="requestId" type="string" />
> <element maxOccurs="1" minOccurs="0" name="correlationId" type="string" />
> </sequence>
> </complexType>
> 
> emailMessage, like this:
> <complexType name="EmailMessage">
> <sequence>
> <element name="from" type="xsd:string" />
> <element name="to" type="xsd:string" />
> <element name="subject" type="xsd:string" />
> <element name="body" type="tns:Body" />
> <element name="attachments" type="tns:Attachment" minOccurs="0"
> maxOccurs="unbounded" />
> </sequence>
> </complexType>
> <complexType name="Body">
> <sequence>
> <element name="content" type="xsd:base64Binary"
> xmime:expectedContentTypes="text/html" />
> </sequence>
> </complexType>
> <complexType name="Attachment">
> <sequence>
> <element name="content" type="xsd:base64Binary" />
> </sequence>
> </complexType>
> 
> Webservice implementation has this single method:
> public class EmailServiceImpl implements EmailService {
>  public void sendEmail(ServiceMessageContext msgCtx, EmailMessage
> emailMessage) {
> 
> My plan was to define user model and apply it to "EmailService" and
> "EmailServiceImpl" like this:
> 
> <model xlmns="http://cxf.apache.org/jaxrs";>
> <resource name="somepackages.EmailService" path="emailservice"
> produces="application/json" consumes="multipart/form-data">
> <operation name="sendEmail" verb="POST" path="/sendemail">
> &lt;param name="msgCtx" type="REQUEST_BODY" /&gt;
> &lt;param name="emailMessage" type="REQUEST_BODY" /&gt;
> </operation>
> </resource>
> </model>
> 
> This worked aswell atleast to the point where I was able to succesfully
> create a JAX-RS server based on the definition and classes.
> 
> Then, I intended to use HttpClient to perform a multipart post by means of
> JAXB marshaling both parameters ("msgCtx" and "emailMessage"), attaching
> them as Parts to MultipartRequestEntity and posting them over.
> 
>> S.B Note that it is very easy to post attachments with CXF JAXRS on the
>> client side too, the only thing which has not been 
>> impemented yet is the recursive multiparts (that is, when individual
>> multipart/form-data parts contains multiple parts of its own) 
>> but this works on the server.
> 
>>> Reinis: I believe that in my application, e.g. emailMessage contains
>>> parts of its own (body and attachments collection that are parts of own)
> 
> Currently I am facing a number of understanding issues even after weekend
> of
> searching and reading on the web.
> 
> 1. @XmlRootElement is neither "msgCtx" nor "emailMessage" but rather
> wsdl2java-generated wrapper class "SendEmail". This kinda makes sense for
> JAX-WS but I guess it will not work for JAX-RS (as I understand it, I have
> to marshal "msgCtx" and "emailMessage" separatelly and add them to
> MultipartRequestEntity as two separate Parts that can be identified later
> by
> JAX-RS server). Can anyone enlighten me on what's wrong with my idea here
> or
> is it really so that I have to configure JAXB so that it is able to
> marshall
> "msgCtx" and "emailMessage" separatelly (I'd greatly appretiate, if anyone
> could write me how to do that)
> 
>> S.B I'm a little bit confused here. What is the value of 
>> ServiceMessageContext and EmailMessage' XmlRootElements ? As far as I
> 
>>> Reinis: I am afraid I do not understand your question.
>>> "ServiceMessageContext" and "EmailMessage" 
>>> have no @XmlRootElement annotation instead, they are, as you correctly
>>> mention bellow, wraped in 
>>> "SendEmail" wrapper and anotated there. (I can not change this since
>>> they all - "ServiceMess...", 
>>> "EmailMessage" and "SendEmail" are generated by JAXB) "SendEmail" looks
>>> ike this:
> 
>>> @XmlAccessorType(XmlAccessType.FIELD)
>>> @XmlType(name = "", propOrder = {
>>>     "msgCtx",
>>>     "emailMessage"
>>> })
>>> @XmlRootElement(name = "sendEmail")
>>> public class SendEmail {
>>> 
>>>     @XmlElement(required = true)
>>>     protected ServiceMessageContext msgCtx;
>>>     @XmlElement(required = true)
>>>     protected EmailMessage emailMessage;
>>>  ...
> 
>> understand, there's a single SendEmail wrapper instance which is being
>> sent in case of SOAP and it is unwrapped at the server side 
>> into two individual parts, msgCtx and emailMessage. But in case of JAXRS
>> you're sending a multipart/form-data request, with one 
>> part containing the ServiceMessageContext instance and the other part
>> containing an email itself...
> If you could attach a sample request message which you're sending with the
> http client (plus the generated ServiceMessageContext and 
> EmailMessage) then it could help as well, I may be able to do some testing
> on my side...
> 
>>> Reinis: Yes, that is my aim, to send two (or more) individual parts but
>>> apparently I am failing at it 
>>> since I have no elegant solution that would keep the three generated
>>> classes without modifications (if 
>>> I could change generated classes, I would, for example, add JAXB
>>> annotations to 
>>> ServiceMessageContext and EmailMessage and marshal them separatelly). At
>>> the moment I am 
>>> marshalling "SendEmail" and wrapping it into "FilePart" which I know is
>>> wrong.
> 
>>> PostMethod post = new
>>> PostMethod("http://localhost:9080/emailservice/sendemail";);
>>>
>>> //set accept header
>>> post.addRequestHeader("Accept", "application/json");
>>>
>>> ObjectFactory objectFactory = new ObjectFactory();
>>> SendEmail sendEmail = objectFactory.createSendEmail();
>>>             
>>> sendEmail.setMsgCtx(EmailBUSTestUtil.generateTestServiceMessageContext());
>>> sendEmail.setEmailMessage(EmailBUSTestUtil.generateTestEmailMessage());
>>>
>>> JAXBContext context = JAXBContext.newInstance(SendEmail.class);
>>> Marshaller m = context.createMarshaller();
>>>             
>>> File file = new File(UUID.randomUUID().toString());     
>>> FileOutputStream out = new FileOutputStream(file);
>>>
>>> m.marshal(sendEmail, out);
>>>         
>>> FilePart sendEmailPart = new FilePart("sendEmail", file);
>>>
>>> //an multipart request entity is required for the e-mail
>>> RequestEntity requestEntity
>>>    = new MultipartRequestEntity(new Part[]{ sendEmailPart },
>>> post.getParams());
>>> post.setRequestEntity(requestEntity);
>>> ...
>>> int result = httpClient.executeMethod(post);
>>> ...
> 
>>> Reinis: This produce message on the wire that is not usable (since it
>>> has only one part) and thus,
>>> I am guessing, is  not correctly matched to parameters of the webmethod.
>>> Sergey, apparently I am 
>>> confusing you because you may think that I have a more or less clear
>>> idea about how to implement 
>>> this, but really, I am just trying things out since I am very new to the
>>> JAX-RS stuff and simply do not 
>>> understand how it should work.
>>> Please find bellow message from the wire and some other log messages
>>> indicating that JAX-RS server
>>> is able to match resource
> 
>>> LoggingInInterceptor (164)     - Inbound Message
>>> ----------------------------
>>> ID: 1
>>> Address: /emailservice/sendemail
>>> Encoding: ISO-8859-1
>>> Content-Type: multipart/form-data;
>>> boundary=tgH6XEjCAXXdvx4VtuCkPq1LuT_YwGGRGByuGy
>>> Headers: {content-type=[multipart/form-data;
>>> boundary=tgH6XEjCAXXdvx4VtuCkPq1LuT_YwGGRGByuGy], Host=[localhost:9080],
>>> Content-Length=
>>> [1928693], User-Agent=[Jakarta Commons-HttpClient/3.1],
>>> Content-Type=[multipart/form-data; 
>>> boundary=tgH6XEjCAXXdvx4VtuCkPq1LuT_YwGGRGByuGy],
>>> Accept=[application/json]}
>>> Messages: 
>>> Message (saved to tmp file):
>>> Filename: C:\Temp\cxf-tmp-655593\cos15008tmp
>>> (message truncated to 102400 bytes)
>>> 
>>> Payload: --tgH6XEjCAXXdvx4VtuCkPq1LuT_YwGGRGByuGy
>>> Content-Disposition: form-data; name="sendEmail";
>>> filename="fd90d28f-0b55-4d3a-
>>> 84dc-d9f894be3e80"
>>> Content-Type: application/octet-stream; charset=ISO-8859-1
>>> Content-Transfer-Encoding: binary
>>> 
>>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:sendEmail
>>> xmlns="http://...";
>>> xmlns:ns2="http://..."; xmlns:ns3="http://...";><ns2:msgCtx><to>Test
>>> Server</to><from>Test 
>>> Client</from><messageId>Test1</messageId><correlationId>UUID-
>>> 234234-234324-6456-4643</correlationId><priority>1</priority><senderVersion>1.0</senderVersion>
>>> <receiverVersion>1.0</receiverVersion></ns2:msgCtx><ns2:emailMessage><ns3:from>testcli...@...
>>> </ns3:from><ns3:to>testser...@.</ns3:to><ns3:body>
>>> <ns3:content>PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NU...</ns3:content>
>>> </ns3:body><ns3:attachments>
>>> <ns3:content>Qk02+RUAAAAAADYAAAAoAAAAIAMAAFgCAAABABgAAAAAAAAAAADED...</ns3:content>
>>> </ns3:attachments></ns2:emailMessage>
>>> --------------------------------------
>>> PhaseInterceptorChain (240)     - Invoking handleMessage on interceptor
>>> org.apache.cxf.transport.https.certconstraintsintercep...@194ba17
>>> PhaseInterceptorChain (240)     - Invoking handleMessage on interceptor
>>> org.apache.cxf.jaxrs.interceptor.jaxrsinintercep...@128594c
>>> JAXRSUtils (223)     - Trying to select a resource class
>>> /emailservice/sendemail, request path : {1}
>>> JAXRSUtils (279)     - Trying to select a resource operation on the
>>> resource class somepackages.EmailService
>>> JAXRSUtils (332)     - Resource operation sendEmail may get selected
>>> JAXRSUtils (355)     - Resource operation sendEmail on the resource
>>> class somepackages.EmailService has been selected
>>> JAXRSInInterceptor (219)     - Request path is: /emailservice/sendemail
>>> JAXRSInInterceptor (220)     - Request HTTP method is: POST
>>> JAXRSInInterceptor (221)     - Request contentType is:
>>> multipart/form-data; boundary=tgH6XEjCAXXdvx4VtuCkPq1LuT_YwGGRGByuGy
>>> JAXRSInInterceptor (222)     - Accept contentType is: application/json
>>> JAXRSInInterceptor (224)     - Found operation: sendEmail
>>> ...
> 
> -- 
> View this message in context:
> http://old.nabble.com/no-annotations-RESTfull-webservice---a-complex-use-case-tp27685209p27685209.html
> Sent from the cxf-user mailing list archive at Nabble.com.
> 

cheers
Reinis
-- 
View this message in context: 
http://old.nabble.com/no-annotations-RESTfull-webservice---a-complex-use-case-tp27685209p27686868.html
Sent from the cxf-user mailing list archive at Nabble.com.

Reply via email to