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"> > <param name="msgCtx" type="REQUEST_BODY" /> > <param name="emailMessage" type="REQUEST_BODY" /> > </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.
