You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by "Penmatsa, Vinay" <vi...@sap.com> on 2013/05/20 22:28:23 UTC

REST with JAX-WS Provider: attachment support

Hi,
I have a REST service based on JAX-WS Provider and Dispatch (implementing Provider<DataSource>). Until now, I accept/produce only XML. Now, I have to support attachments. 
Now, it seems like request should be "multipart/related" as only AttachmentInInterceptor is part of the chain by default. I could probably change that to use AttachmentInputInterceptor instead. The question is how can I can I return MultipartBody? Is there in-built support for that or should I create my own DataSource and handle with an custom out interceptor?


Thanks,
Vinay



Re: REST with JAX-WS Provider: attachment support

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 21/05/13 18:42, Penmatsa, Vinay wrote:
> Yes, basically I followed the restful_dispatch sample, but built over it somewhat complex.
> I try to show an example:
>
> @XmlRootElement(name="customer")
> @XmlAccessorType(XmlAccessType.FIELD)
> public class Customer {
> 		
> 	@XMLElement
> 	private String id;
> 	
> 	// other fields
> 	...
> 	...	
> 	
> 	// say email attachment
> 	@XmlAttachmentRef
> 	private DataHandler email;
> 	...
> }
>
> I generate schema from this and that becomes basis for a request/response below.
> To simplify let's say the service accepts customer and returns customer.
>
> // Use dispatch provider that accepts/returns application/xml. As far as I understand here, I cannot use the high-level
> // JAXB utilities that CXF provides.
> // Here's what I've got without the email attachment. with just xml body.
>
> public class CustomerServiceProvider implements Provider<DataSource> {
> 	
> 	
> 	public DataSource invoke(DataSource ds) {
> 		...// do all required validation
> 		
> 		// Create Customer object from request
> 		JAXBContext jaxbCtx = JAXBContext.newInstance(< Customer and other classes>);
> 		Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
>                  unmarshaller.setSchema(<generated schema>);
>                  JAXBElement<?> jaxbElem = unmarshaller.unmarshal(...);
>                  Object obj = jaxbElem.getValue();
>                  // obj is now Customer
>
>                  // do biz logic here
>
>                  // Now write back a new Customer object.					
> 		Marshaller marshaller = jaxbCtx.createMarshaller();	
> 		marshaller.setSchema(schema);
> 		StringWriter sw = new StringWriter();
> 		marshaller.marshal(< JAXBElement for Customer >,sw);
> 		
> 		return <DataSource from sw>
> 	}
> }
>
> Now, to add the email attachment, I need to support multipart/related or multipart/mixed. I guess if client sends such a request, CXF provides all the necessary attachments in the ds.
> My problem is how I could return a DataSource containing the customer as root and the e-mail as related/mixed type attachment.
> Should I create something similar to MessageModeInInterceptor$MultiPartDataSource and convert to byte source myself or does CXF have something to make it easier?
>
I see what you mean now. You create a complete DataSource manually... 
I'm not sure you can get CXF represent this DataSource as a multipart 
payload, you'd need to manually create it,

Perhaps you can create a JAXB bean instead, and not use DataSource at 
all. This bean will represent all the Customer data. And then simply 
depend on CXF to do either MTOM (WS path) or XOP (RS path), with the 
simpler and still portable code

Sergey
>
> -Vinay
>
>
>
> -----Original Message-----
> From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
> Sent: Tuesday, May 21, 2013 4:56 AM
> To: users@cxf.apache.org
> Subject: Re: REST with JAX-WS Provider: attachment support
>
> Hi
> On 21/05/13 00:10, Penmatsa, Vinay wrote:
>> Hi Sergey,
>> Do these annotations apply to Provider based REST services? I have used these in JAX-RS services, but not for JAX-WS provider based stuff.
>> What I've done with XML payloads (payload mode) is
>> 1. take the request xml, manually unmarshal using JAXB
>> 2. process
>> 3. create and return marshaled string as DataSource.
>>
>> With attachments (I guess message mode), in your example, if I have a result in the form of JAXB root model object, how would I return a DataSource so that CXF can process the response into Multipart? I was thinking I have to build something like MultiPartDataSource manually.
>>
>
> Hmm... May be I've misunderstood your question.
> I'm presuming you have the same interface exposed as JAX-WS and JAX-RS
> endpoints ? Can you type some code and show what exactly do you have in
> mind ?
>
> Thanks, Sergey
>
>> -Vinay
>>
>>
>>
>> -----Original Message-----
>> From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
>> Sent: Monday, May 20, 2013 4:59 PM
>> To: users@cxf.apache.org
>> Subject: Re: REST with JAX-WS Provider: attachment support
>>
>> Hi
>> On 20/05/13 21:28, Penmatsa, Vinay wrote:
>>> Hi,
>>> I have a REST service based on JAX-WS Provider and Dispatch (implementing Provider<DataSource>). Until now, I accept/produce only XML. Now, I have to support attachments.
>>> Now, it seems like request should be "multipart/related" as only AttachmentInInterceptor is part of the chain by default. I could probably change that to use AttachmentInputInterceptor instead. The question is how can I can I return MultipartBody? Is there in-built support for that or should I create my own DataSource and handle with an custom out interceptor?
>>
>> Adding @Consumes("multipart/related") should be enough to get DataSource
>> representing the root attachment, and similarly adding
>>
>> @Produces("multipart/related") is nearly enough to get out DataSource
>> converted to the multipart payload, except that you also need to specify
>> the content type of this root type, so it can look like this:
>>
>> @Produces("multipart/related;type=application/xml")
>> @Consumes("multipart/related")
>> public DataSource a(DataSource ds) {
>>        return ds;
>> }
>>
>> My understanding you'd like to have a 100% portable code, right ?
>>
>> Note that up to CXF 3.0-SNAPSHOT, the input 'ds' parameter will
>> represent the root part of the incoming payload. The response DataSource
>> also represents the root part of the outgoing attachment.
>> I think it is rarely that someone will want to have 'ds' (in this case)
>> representing the actual non-parsed multipart payload or manually build
>> the actual multipart body, so originally I went that path.
>>
>> In CXF 3.0, due to JAX-RS 2.0 TCK 'insistence' on the types like
>> DataSource, InputStream, byte[] be supported by basic pre-packaged
>> providers, the above will slightly change to:
>>
>> @Produces("multipart/related;type=application/xml")
>> @Consumes("multipart/related")
>> @Multipart
>> public DataSource a(@Multipart DataSource ds) {
>>        return ds;
>> }
>>
>> Where CXF @Multipart annotation marks in and out parameters as multipart
>> bodies. Without @Multipart the 1st example above will produce a portable
>> but more complex code (meaning DataSource will have to be manually
>> parsed or used to create the out payload manually)
>>
>> Sergey
>>
>>
>>>
>>>
>>> Thanks,
>>> Vinay
>>>
>>>
>>
>>
>



RE: REST with JAX-WS Provider: attachment support

Posted by "Penmatsa, Vinay" <vi...@sap.com>.
Yes, basically I followed the restful_dispatch sample, but built over it somewhat complex.
I try to show an example:

@XmlRootElement(name="customer")
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
		
	@XMLElement
	private String id;
	
	// other fields
	...
	...	
	
	// say email attachment
	@XmlAttachmentRef
	private DataHandler email;
	...
}

I generate schema from this and that becomes basis for a request/response below.
To simplify let's say the service accepts customer and returns customer.

// Use dispatch provider that accepts/returns application/xml. As far as I understand here, I cannot use the high-level
// JAXB utilities that CXF provides.
// Here's what I've got without the email attachment. with just xml body.

public class CustomerServiceProvider implements Provider<DataSource> {
	
	
	public DataSource invoke(DataSource ds) {
		...// do all required validation
		
		// Create Customer object from request
		JAXBContext jaxbCtx = JAXBContext.newInstance(< Customer and other classes>);
		Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
                unmarshaller.setSchema(<generated schema>);
                JAXBElement<?> jaxbElem = unmarshaller.unmarshal(...);
                Object obj = jaxbElem.getValue();
                // obj is now Customer
                
                // do biz logic here
                
                // Now write back a new Customer object.					
		Marshaller marshaller = jaxbCtx.createMarshaller();	
		marshaller.setSchema(schema);
		StringWriter sw = new StringWriter();
		marshaller.marshal(< JAXBElement for Customer >,sw);
		
		return <DataSource from sw>
	}
}

Now, to add the email attachment, I need to support multipart/related or multipart/mixed. I guess if client sends such a request, CXF provides all the necessary attachments in the ds.
My problem is how I could return a DataSource containing the customer as root and the e-mail as related/mixed type attachment.
Should I create something similar to MessageModeInInterceptor$MultiPartDataSource and convert to byte source myself or does CXF have something to make it easier?


-Vinay



-----Original Message-----
From: Sergey Beryozkin [mailto:sberyozkin@gmail.com] 
Sent: Tuesday, May 21, 2013 4:56 AM
To: users@cxf.apache.org
Subject: Re: REST with JAX-WS Provider: attachment support

Hi
On 21/05/13 00:10, Penmatsa, Vinay wrote:
> Hi Sergey,
> Do these annotations apply to Provider based REST services? I have used these in JAX-RS services, but not for JAX-WS provider based stuff.
> What I've done with XML payloads (payload mode) is
> 1. take the request xml, manually unmarshal using JAXB
> 2. process
> 3. create and return marshaled string as DataSource.
>
> With attachments (I guess message mode), in your example, if I have a result in the form of JAXB root model object, how would I return a DataSource so that CXF can process the response into Multipart? I was thinking I have to build something like MultiPartDataSource manually.
>

Hmm... May be I've misunderstood your question.
I'm presuming you have the same interface exposed as JAX-WS and JAX-RS 
endpoints ? Can you type some code and show what exactly do you have in 
mind ?

Thanks, Sergey

> -Vinay
>
>
>
> -----Original Message-----
> From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
> Sent: Monday, May 20, 2013 4:59 PM
> To: users@cxf.apache.org
> Subject: Re: REST with JAX-WS Provider: attachment support
>
> Hi
> On 20/05/13 21:28, Penmatsa, Vinay wrote:
>> Hi,
>> I have a REST service based on JAX-WS Provider and Dispatch (implementing Provider<DataSource>). Until now, I accept/produce only XML. Now, I have to support attachments.
>> Now, it seems like request should be "multipart/related" as only AttachmentInInterceptor is part of the chain by default. I could probably change that to use AttachmentInputInterceptor instead. The question is how can I can I return MultipartBody? Is there in-built support for that or should I create my own DataSource and handle with an custom out interceptor?
>
> Adding @Consumes("multipart/related") should be enough to get DataSource
> representing the root attachment, and similarly adding
>
> @Produces("multipart/related") is nearly enough to get out DataSource
> converted to the multipart payload, except that you also need to specify
> the content type of this root type, so it can look like this:
>
> @Produces("multipart/related;type=application/xml")
> @Consumes("multipart/related")
> public DataSource a(DataSource ds) {
>       return ds;
> }
>
> My understanding you'd like to have a 100% portable code, right ?
>
> Note that up to CXF 3.0-SNAPSHOT, the input 'ds' parameter will
> represent the root part of the incoming payload. The response DataSource
> also represents the root part of the outgoing attachment.
> I think it is rarely that someone will want to have 'ds' (in this case)
> representing the actual non-parsed multipart payload or manually build
> the actual multipart body, so originally I went that path.
>
> In CXF 3.0, due to JAX-RS 2.0 TCK 'insistence' on the types like
> DataSource, InputStream, byte[] be supported by basic pre-packaged
> providers, the above will slightly change to:
>
> @Produces("multipart/related;type=application/xml")
> @Consumes("multipart/related")
> @Multipart
> public DataSource a(@Multipart DataSource ds) {
>       return ds;
> }
>
> Where CXF @Multipart annotation marks in and out parameters as multipart
> bodies. Without @Multipart the 1st example above will produce a portable
> but more complex code (meaning DataSource will have to be manually
> parsed or used to create the out payload manually)
>
> Sergey
>
>
>>
>>
>> Thanks,
>> Vinay
>>
>>
>
>


Re: REST with JAX-WS Provider: attachment support

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 21/05/13 00:10, Penmatsa, Vinay wrote:
> Hi Sergey,
> Do these annotations apply to Provider based REST services? I have used these in JAX-RS services, but not for JAX-WS provider based stuff.
> What I've done with XML payloads (payload mode) is
> 1. take the request xml, manually unmarshal using JAXB
> 2. process
> 3. create and return marshaled string as DataSource.
>
> With attachments (I guess message mode), in your example, if I have a result in the form of JAXB root model object, how would I return a DataSource so that CXF can process the response into Multipart? I was thinking I have to build something like MultiPartDataSource manually.
>

Hmm... May be I've misunderstood your question.
I'm presuming you have the same interface exposed as JAX-WS and JAX-RS 
endpoints ? Can you type some code and show what exactly do you have in 
mind ?

Thanks, Sergey

> -Vinay
>
>
>
> -----Original Message-----
> From: Sergey Beryozkin [mailto:sberyozkin@gmail.com]
> Sent: Monday, May 20, 2013 4:59 PM
> To: users@cxf.apache.org
> Subject: Re: REST with JAX-WS Provider: attachment support
>
> Hi
> On 20/05/13 21:28, Penmatsa, Vinay wrote:
>> Hi,
>> I have a REST service based on JAX-WS Provider and Dispatch (implementing Provider<DataSource>). Until now, I accept/produce only XML. Now, I have to support attachments.
>> Now, it seems like request should be "multipart/related" as only AttachmentInInterceptor is part of the chain by default. I could probably change that to use AttachmentInputInterceptor instead. The question is how can I can I return MultipartBody? Is there in-built support for that or should I create my own DataSource and handle with an custom out interceptor?
>
> Adding @Consumes("multipart/related") should be enough to get DataSource
> representing the root attachment, and similarly adding
>
> @Produces("multipart/related") is nearly enough to get out DataSource
> converted to the multipart payload, except that you also need to specify
> the content type of this root type, so it can look like this:
>
> @Produces("multipart/related;type=application/xml")
> @Consumes("multipart/related")
> public DataSource a(DataSource ds) {
>       return ds;
> }
>
> My understanding you'd like to have a 100% portable code, right ?
>
> Note that up to CXF 3.0-SNAPSHOT, the input 'ds' parameter will
> represent the root part of the incoming payload. The response DataSource
> also represents the root part of the outgoing attachment.
> I think it is rarely that someone will want to have 'ds' (in this case)
> representing the actual non-parsed multipart payload or manually build
> the actual multipart body, so originally I went that path.
>
> In CXF 3.0, due to JAX-RS 2.0 TCK 'insistence' on the types like
> DataSource, InputStream, byte[] be supported by basic pre-packaged
> providers, the above will slightly change to:
>
> @Produces("multipart/related;type=application/xml")
> @Consumes("multipart/related")
> @Multipart
> public DataSource a(@Multipart DataSource ds) {
>       return ds;
> }
>
> Where CXF @Multipart annotation marks in and out parameters as multipart
> bodies. Without @Multipart the 1st example above will produce a portable
> but more complex code (meaning DataSource will have to be manually
> parsed or used to create the out payload manually)
>
> Sergey
>
>
>>
>>
>> Thanks,
>> Vinay
>>
>>
>
>


RE: REST with JAX-WS Provider: attachment support

Posted by "Penmatsa, Vinay" <vi...@sap.com>.
Hi Sergey,
Do these annotations apply to Provider based REST services? I have used these in JAX-RS services, but not for JAX-WS provider based stuff.
What I've done with XML payloads (payload mode) is
1. take the request xml, manually unmarshal using JAXB
2. process
3. create and return marshaled string as DataSource.

With attachments (I guess message mode), in your example, if I have a result in the form of JAXB root model object, how would I return a DataSource so that CXF can process the response into Multipart? I was thinking I have to build something like MultiPartDataSource manually.

-Vinay



-----Original Message-----
From: Sergey Beryozkin [mailto:sberyozkin@gmail.com] 
Sent: Monday, May 20, 2013 4:59 PM
To: users@cxf.apache.org
Subject: Re: REST with JAX-WS Provider: attachment support

Hi
On 20/05/13 21:28, Penmatsa, Vinay wrote:
> Hi,
> I have a REST service based on JAX-WS Provider and Dispatch (implementing Provider<DataSource>). Until now, I accept/produce only XML. Now, I have to support attachments.
> Now, it seems like request should be "multipart/related" as only AttachmentInInterceptor is part of the chain by default. I could probably change that to use AttachmentInputInterceptor instead. The question is how can I can I return MultipartBody? Is there in-built support for that or should I create my own DataSource and handle with an custom out interceptor?

Adding @Consumes("multipart/related") should be enough to get DataSource 
representing the root attachment, and similarly adding

@Produces("multipart/related") is nearly enough to get out DataSource 
converted to the multipart payload, except that you also need to specify 
the content type of this root type, so it can look like this:

@Produces("multipart/related;type=application/xml")
@Consumes("multipart/related")
public DataSource a(DataSource ds) {
     return ds;
}

My understanding you'd like to have a 100% portable code, right ?

Note that up to CXF 3.0-SNAPSHOT, the input 'ds' parameter will 
represent the root part of the incoming payload. The response DataSource 
also represents the root part of the outgoing attachment.
I think it is rarely that someone will want to have 'ds' (in this case) 
representing the actual non-parsed multipart payload or manually build 
the actual multipart body, so originally I went that path.

In CXF 3.0, due to JAX-RS 2.0 TCK 'insistence' on the types like 
DataSource, InputStream, byte[] be supported by basic pre-packaged 
providers, the above will slightly change to:

@Produces("multipart/related;type=application/xml")
@Consumes("multipart/related")
@Multipart
public DataSource a(@Multipart DataSource ds) {
     return ds;
}

Where CXF @Multipart annotation marks in and out parameters as multipart 
bodies. Without @Multipart the 1st example above will produce a portable 
but more complex code (meaning DataSource will have to be manually 
parsed or used to create the out payload manually)

Sergey


>
>
> Thanks,
> Vinay
>
>



Re: REST with JAX-WS Provider: attachment support

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
On 20/05/13 21:28, Penmatsa, Vinay wrote:
> Hi,
> I have a REST service based on JAX-WS Provider and Dispatch (implementing Provider<DataSource>). Until now, I accept/produce only XML. Now, I have to support attachments.
> Now, it seems like request should be "multipart/related" as only AttachmentInInterceptor is part of the chain by default. I could probably change that to use AttachmentInputInterceptor instead. The question is how can I can I return MultipartBody? Is there in-built support for that or should I create my own DataSource and handle with an custom out interceptor?

Adding @Consumes("multipart/related") should be enough to get DataSource 
representing the root attachment, and similarly adding

@Produces("multipart/related") is nearly enough to get out DataSource 
converted to the multipart payload, except that you also need to specify 
the content type of this root type, so it can look like this:

@Produces("multipart/related;type=application/xml")
@Consumes("multipart/related")
public DataSource a(DataSource ds) {
     return ds;
}

My understanding you'd like to have a 100% portable code, right ?

Note that up to CXF 3.0-SNAPSHOT, the input 'ds' parameter will 
represent the root part of the incoming payload. The response DataSource 
also represents the root part of the outgoing attachment.
I think it is rarely that someone will want to have 'ds' (in this case) 
representing the actual non-parsed multipart payload or manually build 
the actual multipart body, so originally I went that path.

In CXF 3.0, due to JAX-RS 2.0 TCK 'insistence' on the types like 
DataSource, InputStream, byte[] be supported by basic pre-packaged 
providers, the above will slightly change to:

@Produces("multipart/related;type=application/xml")
@Consumes("multipart/related")
@Multipart
public DataSource a(@Multipart DataSource ds) {
     return ds;
}

Where CXF @Multipart annotation marks in and out parameters as multipart 
bodies. Without @Multipart the 1st example above will produce a portable 
but more complex code (meaning DataSource will have to be manually 
parsed or used to create the out payload manually)

Sergey


>
>
> Thanks,
> Vinay
>
>