You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cxf.apache.org by rbinion <rb...@gmail.com> on 2011/07/26 01:57:26 UTC

XSLTJaxbProvider and json

I'm looking for suggestions on how best to approach a problem. 

I'm currently working on a project where we are using CXF to expose REST
services which will be consumed both by direct service consumers as well as
a co-developed spring MVC/javascript based application. 

I suspect that we are doing fairly typical stuff in that we are annotating
our services to produce both xml and json (driven by jaxb annotations), and
this is working fine for simple marshaling. However I now have the need to
also handle some fairly simple transformations (omitting and renaming
elements) both coming in and out of a particular service. 

The reason for the transformation is that I essentially have a POJO that
represents somewhat of a "union of types", and I have no compelling reason
to realize this "union" as a class hierarchy, other than to make the service
interface "clean" (the underlying business service prefers to operate on
this "union" as does the data access layer). More or less, I am trying to
avoid creating DTOs, or rather I am attempting to realize the DTO's only
through XML transformation.

So, I would like to provide a simple set of rules (xslt) to do the
transformation for both XML and json output, but that is where I am not
conceptualizing the simple solution. XSLTJaxbProvider seems to be very close
to what I want (and indeed I have been able to get this to work for
marshaling XML), but I'm not sure how to extend this approach to also work
for JSON transformations without having to write two XSLT's (one for
handling XML and the other for handling json).

Am I thinking about the problem wrong, i.e. two templates is the way to
handle this (regardless of the maintenance overhead), and/or I should just
stop being lazy and implement the darn POJO's (again irrespective of the
maintenance overhead) ...

If I am on the right track but some sample code would be helpful in seeing
where I am going astray, I can provide that as well ...

Any suggestions/revelations would be greatly appreciated.



--
View this message in context: http://cxf.547215.n5.nabble.com/XSLTJaxbProvider-and-json-tp4632954p4632954.html
Sent from the cxf-dev mailing list archive at Nabble.com.

Re: XSLTJaxbProvider and json

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi
> Well, this might be getting a bit involved for this forum, but if anyone has
> any thoughts I would very much so appreciate hearing them.
>
> I am close to getting the XsltJsonProvider working. I actually have it
> working for writing, but I've run into a conceptual roadblock getting it to
> work for reading.
>
> I basically merged XsltJaxbProvider with JsonProvider (at least to get it
> working), and in the marshalToOutputStream method I just passed in the
> streamwriter for handling json.
>
>
> 	protected void marshalToOutputStream(Marshaller ms, Object obj,
> 			OutputStream os, MediaType mt, XMLStreamWriter writer)
> 			throws Exception {
> 		TransformerHandler th = factory.newTransformerHandler(createTemplates(
> 				getOutTemplates(mt), outParamsMap, outProperties));
> 		// Result result = new StreamResult(os);
> 		Result result = new StaxResult(writer);
> 		if (systemId != null) {
> 			result.setSystemId(systemId);
> 		}
> 		th.setResult(result);
> 		ms.marshal(obj, th);
> 	}
>
> So the xslt is applied and then is written using jettison. Works great! :)
>
> I'm actually not familiar enough with these API's to know for sure what is
> going on in the marshal method, but my guess is that the Object is being
> converted to xml with jaxb, the xslt is then applied, then it is written it
> to the output stream using the jettison writer which converts the xml to
> json as it is being written.
>
It is correct, yes.

> If this is correct then the reverse, reading/unmarshaling, would first have
> to convert the json to xml, apply the xslt, and then use jaxb to construct
> the object. Unlike with writing though, I am not seeing a way to hand a
> jettison reader and a filter to the unmarshaller all at once.'Plain' JAXBElementProvider and JSONProvider extend AbstractJAXBProvider.
I guess XSLT

>
> I am trying something like the following (with multiple variations), to no
> avail ...
>
> XMLFilter filter = factory.newXMLFilter(createTemplates(
> 		getInTemplates(mt), inParamsMap, inProperties));
>
> StaxSource source2 = new StaxSource(xsw); //where xsw is a XmlStreamReader
> for handling json
>
> response = unmarshaller.unmarshal(??);
>
> Unlike with marshaling I am just not seeing a way to get those two concepts
> together. Is there not a way to do this in one step, and so I should
> manually convert the json to xml first? Am I misunderstanding how this whole
> thing works?
>
> Again, I can provide more code if it would be useful, and any insight is
> greatly appreciated. :)
>
Have a look at XSLTJaxbProvider. At the moment, the reader is copied to 
CashedOutputStream and only then the template is applied to the 
InputStream obtained from the cashed output stream. May be there's even 
a more effective way to achieve the transformation.
Let us know please if that approach works for you

Cheers, Sergey

> -Bob
>
>
>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/XSLTJaxbProvider-and-json-tp4632954p4637126.html
> Sent from the cxf-dev mailing list archive at Nabble.com.


Re: XSLTJaxbProvider and json

Posted by rbinion <rb...@gmail.com>.
Well, this might be getting a bit involved for this forum, but if anyone has
any thoughts I would very much so appreciate hearing them.

I am close to getting the XsltJsonProvider working. I actually have it
working for writing, but I've run into a conceptual roadblock getting it to
work for reading.

I basically merged XsltJaxbProvider with JsonProvider (at least to get it
working), and in the marshalToOutputStream method I just passed in the
streamwriter for handling json.


	protected void marshalToOutputStream(Marshaller ms, Object obj,
			OutputStream os, MediaType mt, XMLStreamWriter writer)
			throws Exception {
		TransformerHandler th = factory.newTransformerHandler(createTemplates(
				getOutTemplates(mt), outParamsMap, outProperties));
		// Result result = new StreamResult(os);
		Result result = new StaxResult(writer);
		if (systemId != null) {
			result.setSystemId(systemId);
		}
		th.setResult(result);
		ms.marshal(obj, th);
	}

So the xslt is applied and then is written using jettison. Works great! :)

I'm actually not familiar enough with these API's to know for sure what is
going on in the marshal method, but my guess is that the Object is being
converted to xml with jaxb, the xslt is then applied, then it is written it
to the output stream using the jettison writer which converts the xml to
json as it is being written.

If this is correct then the reverse, reading/unmarshaling, would first have
to convert the json to xml, apply the xslt, and then use jaxb to construct
the object. Unlike with writing though, I am not seeing a way to hand a
jettison reader and a filter to the unmarshaller all at once.

I am trying something like the following (with multiple variations), to no
avail ...

XMLFilter filter = factory.newXMLFilter(createTemplates(
		getInTemplates(mt), inParamsMap, inProperties));

StaxSource source2 = new StaxSource(xsw); //where xsw is a XmlStreamReader
for handling json

response = unmarshaller.unmarshal(??);

Unlike with marshaling I am just not seeing a way to get those two concepts
together. Is there not a way to do this in one step, and so I should
manually convert the json to xml first? Am I misunderstanding how this whole
thing works?

Again, I can provide more code if it would be useful, and any insight is
greatly appreciated. :)

-Bob


 

--
View this message in context: http://cxf.547215.n5.nabble.com/XSLTJaxbProvider-and-json-tp4632954p4637126.html
Sent from the cxf-dev mailing list archive at Nabble.com.

Re: XSLTJaxbProvider and json

Posted by rbinion <rb...@gmail.com>.

> I think it would be nice to get a similar XSLTJsonProvider which would
> create a
> writer sitting between JAXB and Jettison and that would basically
> enable reusing the same single template for producing XML & JSON
> transformed output. Please feel free to create an enhancement request
> - and a patch would help :-)
> 

Hah :) ...  well I did start working on a merge of the existing JsonProvider
and the XSLTJaxbProvider, but had hoped I might find something already
existing ... I'll see if I can get something working though :)

Thanks for the confirmation!

--
View this message in context: http://cxf.547215.n5.nabble.com/XSLTJaxbProvider-and-json-tp4632954p4633268.html
Sent from the cxf-dev mailing list archive at Nabble.com.

Re: XSLTJaxbProvider and json

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi

On Tue, Jul 26, 2011 at 12:57 AM, rbinion <rb...@gmail.com> wrote:
> I'm looking for suggestions on how best to approach a problem.
>
> I'm currently working on a project where we are using CXF to expose REST
> services which will be consumed both by direct service consumers as well as
> a co-developed spring MVC/javascript based application.
>
> I suspect that we are doing fairly typical stuff in that we are annotating
> our services to produce both xml and json (driven by jaxb annotations), and
> this is working fine for simple marshaling. However I now have the need to
> also handle some fairly simple transformations (omitting and renaming
> elements) both coming in and out of a particular service.
>
> The reason for the transformation is that I essentially have a POJO that
> represents somewhat of a "union of types", and I have no compelling reason
> to realize this "union" as a class hierarchy, other than to make the service
> interface "clean" (the underlying business service prefers to operate on
> this "union" as does the data access layer). More or less, I am trying to
> avoid creating DTOs, or rather I am attempting to realize the DTO's only
> through XML transformation.
>
> So, I would like to provide a simple set of rules (xslt) to do the
> transformation for both XML and json output, but that is where I am not
> conceptualizing the simple solution. XSLTJaxbProvider seems to be very close
> to what I want (and indeed I have been able to get this to work for
> marshaling XML), but I'm not sure how to extend this approach to also work
> for JSON transformations without having to write two XSLT's (one for
> handling XML and the other for handling json).
>
> Am I thinking about the problem wrong, i.e. two templates is the way to
> handle this (regardless of the maintenance overhead), and/or I should just
> stop being lazy and implement the darn POJO's (again irrespective of the
> maintenance overhead) ...
>
> If I am on the right track but some sample code would be helpful in seeing
> where I am going astray, I can provide that as well ...
>
I think you are on the right track. The only complication with
XSLTJaxbProvider and a dedicated template producing JSON is that
this template will need to deal with creating a JSON sequence itself.
I think it would be nice to get a similar XSLTJsonProvider which would
create a
writer sitting between JAXB and Jettison and that would basically
enable reusing the same single template for producing XML & JSON
transformed output. Please feel free to create an enhancement request
- and a patch would help :-)
The other option is to try TransformFeature: it will work for both XML
and JSON (JAXB-driven):
http://cxf.apache.org/docs/transformationfeature.html

Cheers, Sergey





> Any suggestions/revelations would be greatly appreciated.
>
>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/XSLTJaxbProvider-and-json-tp4632954p4632954.html
> Sent from the cxf-dev mailing list archive at Nabble.com.
>



-- 
Sergey Beryozkin

http://sberyozkin.blogspot.com
Talend - http://www.talend.com