Hi Reinis
<snip/>
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;
...
S.B : ok, thanks... So ServiceMessageContext and EmailMessage are just @XmlType(s)...See, JAXRS does not really like multiple
request parameters referring to request bodies (as in sendEmail) thus CXF JAXRS does not unwrap the way CXF JAXWS does (which is
very JAXWS compliant) but here we're dealing with a multipart request so even thought it is not standardized in JAXRS, it makes
sense to refer to individual parts through the use of multiple parameters. But the problem is that ServiceMessageContext and
EmailMessage have no @XmlRootElement - I think you can just register a JAXRS JAXBElementProvider and set an 'unmarshalAsJaxbElement'
property on it and it should fix the JAXB-related issue...
S.B. Next, given that CXF JAXRS does not unwrap (well, at the moment at least), one needs to 'attach' @Multipart annotations to
individual method parameters for the MultipartProvider to figure out which part needs be deserialized. Given that you've chosen to
use a user model this may seem like a step back but lets just make it work and then I can look at extending the model support... So
now we have :
sendEmail(@Multipart("context") ServiceMessageContext ctx, @Multipart("email")
EmailMessage message)
where "context" refers to the first part and "email" contains the other one
Reinis, can you give me a favor and also send me generated ServiceMessageContext & EmailMessage ? I'll do a quick test and see what
needs to be done to ensure JAXBElementProvider can also handle the binary content...I'll let you know then and you'll be able to
register a custom JAXBWElementProvider.
S.B : Now, if you had just a wrapper SendEmail parameter (perhaps named as EmailRequest instead) then it woull things easier to deal
with for a number of reasons, you'd definitely not have to register a custom JAXBProvider as suggested above...Perhaps you might
want to consider running wsdl2java in a mode which produces methods with wrapped signatures ?
.
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.
S.B : No problems. Thanks for experimenting - we'll get it done/fixed. More
comments below...
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>
S.B : Indeed, it won't work for a number of reasons. Note that if you had just sendEmail(SendEmail) (or rather
sendEmail(EmailRequest)) then it would probably work (but as I said I'll need to test and check if JAXBElementProvider needs to be
enhanced a bit).
S.B : In meantime, please ensure you have two parts, the above fragment just uses a single part but a real multipart/form-data
would have one part containing a service context, the other one containing the body with this second body part containing
embedded/recursive parts, one per every email attachment. You probably just do not need this kind of complexity (yet), just create a
multipart/mixed or may be multipart/related (and update @Produces) request containing two parts, one will 'hold' the context another
one an email message including the binary content.
S.B : If you didn't have to use JAXB to unmarshal emailMessage then we would
have more options like :
sendEmail(Body emailBody, List<Attachment> attachments), etc...But I'd like to ensure JAXBElementProvider is also capable of dealing
with such requests. So, to summarize, please send me ServiceContextImpl and EmailExchnage and resend the above request with all the
namespaces in place so that I could just use it in test (sample namespaces will do fine)
thanks, Sergey
--------------------------------------
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}
S.B: will get this {1} fixed...It might be fixed in 2.2.6 ?
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.