You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by XeN0s <ga...@gmail.com> on 2009/05/30 12:24:30 UTC

How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?

Hello guys,

Since cxf 2.2.2 has been released (congratulations for your amazing work and
for your activity !), I would like to try the jaxrs XSLTJaxbProvider to
convert JAXB XML data in RDF.

My current server endpoint (only for XML result) :

	<jaxrs:server id="restServer" address="/">
		<jaxrs:serviceBeans>
			<ref bean="productRestService" />
		</jaxrs:serviceBeans>
	</jaxrs:server>

The "productRestService" spring bean class : 

@Path("/prodservice")
public class ProductRestService {

        //domain service, with JPA stuff...
	private ProductServices productServices;

	@GET
	@Produces("application/xml")
	public ProductsDTO getAll() {
		return new ProductsDTO(productServices.getAllOrderByName());
	}
}

The "ProductsDTO" class (a custom collection wrapper) :

@XmlRootElement(name="list")
public class ProductsDTO {
	
	private List<ProductDTO> products;
	
	public ProductsDTO() {
		
	}
	
	public ProductsDTO(List<Product> list) {
		this.products = new ArrayList<ProductDTO>();
		
		for (Product product : list) {
			products.add(new ProductDTO(product));
		}
	}
	
	@XmlElement(name="object")
	public List<ProductDTO> getProducts() {
		return products;
	}
}


And finally the XML result when calling "/prodservice" : 

<list>
	
		<categoryId>20</categoryId>
		<categoryLabel>Anti-dépresseurs</categoryLabel>
		<dangerous>true</dangerous>
		<description>test 1</description>
		<id>21</id>
		<name>Anti DEPRESS MAX2000+</name>
		<producer>PRODUCTEUR 1</producer>
		<reference>PROD1-ANTIDEPRESS</reference>
	
	
		...
	
</list>


Now, i'd like to convert this in RDF format. I wrote an "rdf-stylesheet.xsl"
which works great with the produced XML result when tested in a standalone
program.

So, I try the new Provider to do the job : 

	<bean id="xsltProvider"
class="org.apache.cxf.jaxrs.provider.XSLTJaxbProvider">
		<property name="outMediaTemplates" ref="outMediaTemplates" />
	</bean>

	<util:map id="outMediaTemplates">
		<entry key="application/xml+rdf" value="classpath:rdf-stylesheet.xsl" />
	</util:map>

Then I updated my endpoint declaration with this provider :

	<jaxrs:server id="restServer" address="/">
		<jaxrs:serviceBeans>
			<ref bean="productRestService" />
		</jaxrs:serviceBeans>
		<jaxrs:providers>
			<ref bean="xsltProvider" />
		</jaxrs:providers>
	</jaxrs:server>

And finally I told my "ProductRestService" to produce xml+rdf  instead of
basic xml : 
	
	@GET
	@Produces("application/xml+rdf")
	public ProductsDTO getAll() {
		return new ProductsDTO(productServices.getAllOrderByName());
	}

when launching my /prodservice again, I got an ".No message body writer
found for response class : ProductsDTO." html error page.

It seems I am missing something here. Since XSLTJaxbProvider is a very new
feature, it isn't well documented yet.

I tried to inject an "outClassNames" list to my provider (with ProductsDTO
and ProductDTO), but it doesn't solve the problem.

Any idea ?

Thanks you in advance :-)


Gael
-- 
View this message in context: http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-feature---tp23792102p23792102.html
Sent from the cxf-user mailing list archive at Nabble.com.


RE: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?

Posted by Sergey Beryozkin <sb...@progress.com>.
Hi, 
great it started working for you, thanks for experimenting...

If you only use this provider to produce application/rdf+xml formats,
then
you might want consider simplifying the configuration, by using
"outTemplate" property :  

<bean id="xsltProvider"
  class="org.apache.cxf.jaxrs.provider.XSLTJaxbProvider">
 <property name="outTemplate" value="classpath:/rdf-stylesheet.xsl"/>
</bean>

though the configuration option you're using is more flexible. 

> XSLTJaxbProvider is definitely very nice :-)

I agree it can be pretty powerful. In principle one can use it instead
all sort of customized providers producing/consuming XML or those which
depend on JAXB to produce say JSON.   
We'll need to think of how to make it work even faster when it deals
with large stylesheets, ensure that Stax readers/writers, when
available, can act at the first chain entry, before delegating to XSLT,
etc...

Cheers, Sergey 

-----Original Message-----
From: XeN0s [mailto:gael.lazzari@gmail.com] 
Sent: 31 May 2009 08:06
To: users@cxf.apache.org
Subject: RE: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?


Thank you very much Sergey, it works great with

	<util:map id="outMediaTemplates">
		<entry key="application/rdf+xml"
value="classpath:/rdf-stylesheet.xsl" />
	</util:map>

and @Produce({...application/rdf+xml})


application/xml+rdf actually wasn't correct, so I didn't have to
register
custom media types.

 
XSLTJaxbProvider is definitely very nice :-)




Sergey Beryozkin-2 wrote:
> 
> Hi,
> 
> I was using a forward slash in all my tests, for example : 
> classpath:/rdf-stylesheet.xsl
> 
> but perhaps, given that a classloader is asked to load a resource
> explicitly there is no need for this extra slash - but please use '/'
> for a while.
> 
>> application/xml+rdf
> 
> XSLTJaxbProvider has static Produces/Consumes values, particularly,
> @Produces has no "application/xml+rdf" in the list.
> 
> To make XSLTJaxbProvider recognize it you can customize its Produces
> values, when registering a provider, for :
> 
> <util:list id="mediaTypes">
> <value>application/xml</value>
> <value>application/xml+rdf</value>
> </util:list>
> 
> <bean id="xsltProvider"
> class="org.apache.cxf.jaxrs.provider.XSLTJaxbProvider">
> <property name="produceMediaTypes" ref="mediaTypes"/>
> </bean>
> 
> Actually, XSLTJaxbProvider has "application/*+xml" so it has to
work...
> I just checked, it should be
> 
> application/rdf+xml rather than
> 
> application/xml+rdf ?
> 
> But if you do need application/xml+rdf
> 
> then please use the explicit customization ...
> 
> In meantime, may be I should also add "application/xml+*" to
> XSLTJaxbProvider
> 
> Hope it helps, Sergey
> 
>  
> 
> -----Original Message-----
> From: XeN0s [mailto:gael.lazzari@gmail.com] 
> Sent: 30 May 2009 14:11
> To: users@cxf.apache.org
> Subject: Re: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?
> 
> 
> I just investigate a little.
> 
> In application log, I found :
> 
> 2009-05-30 14:54:59 [org.apache.cxf.jaxrs.provider.XSLTJaxbProvider]
> WARN  -
> No template is available at : classpath:rdf-stylesheet.xsl
> 
> In XSLTJaxbProvider, there is a bug : 
> 
>  protected Templates createTemplates(String loc) {
>         try {
>             InputStream is = null;
>             if (loc.startsWith("classpath:")) {
>                 String path = loc.substring("classpath:".length() +
1);
>     
>                 // ===> path actually is set with "df-stylesheet.xsl"
> 
>                 is =
> this.getClass().getClassLoader().getResourceAsStream(path);
>             } else {
>                 File f = new File(loc);
>                 if (f.exists()) {
>                     is = new FileInputStream(f);
>                 }
>             }
>             if (is == null) {
>                 LOG.warning("No template is available at : " + loc);
>                 return null;
>             }
>             
>             Reader r = new BufferedReader(
>                            new InputStreamReader(is, "UTF-8"));
>             Source source = new StreamSource(r);
>             if (factory == null) {
>                 factory =
> (SAXTransformerFactory)TransformerFactory.newInstance();
>                 if (uriResolver != null) {
>                     factory.setURIResolver(uriResolver);
>                 }
>             }
>             return factory.newTemplates(source);
>             
>         } catch (Exception ex) {
>             LOG.warning("No template can be created : " +
> ex.getMessage());
>         }
>         return null;
>     }
> 
> 
> To avoid this bug, I modified my endpoint configuration : 
> 
> 	<util:map id="outMediaTemplates">
> 		<entry key="application/xml+rdf" value="classpath:
> rdf-stylesheet.xsl" />
> 	</util:map>
> 
> With this, Templates object is correctly created (maybe a JIRA issue
> will be
> needed ?)
> 
> But it doesn't solve my base problem : when calling the service
> /prodservice, I still get a ".No message body writer found for
response
> class : ProductsDTO." html error page. 
> -- 
> View this message in context:
>
http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-featur
> e---tp23792102p23793284.html
> Sent from the cxf-user mailing list archive at Nabble.com.
> 
> 
> 

-- 
View this message in context:
http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-featur
e---tp23792102p23800447.html
Sent from the cxf-user mailing list archive at Nabble.com.


RE: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?

Posted by XeN0s <ga...@gmail.com>.
Thank you very much Sergey, it works great with

	<util:map id="outMediaTemplates">
		<entry key="application/rdf+xml" value="classpath:/rdf-stylesheet.xsl" />
	</util:map>

and @Produce({...application/rdf+xml})


application/xml+rdf actually wasn't correct, so I didn't have to register
custom media types.

 
XSLTJaxbProvider is definitely very nice :-)




Sergey Beryozkin-2 wrote:
> 
> Hi,
> 
> I was using a forward slash in all my tests, for example : 
> classpath:/rdf-stylesheet.xsl
> 
> but perhaps, given that a classloader is asked to load a resource
> explicitly there is no need for this extra slash - but please use '/'
> for a while.
> 
>> application/xml+rdf
> 
> XSLTJaxbProvider has static Produces/Consumes values, particularly,
> @Produces has no "application/xml+rdf" in the list.
> 
> To make XSLTJaxbProvider recognize it you can customize its Produces
> values, when registering a provider, for :
> 
> <util:list id="mediaTypes">
> <value>application/xml</value>
> <value>application/xml+rdf</value>
> </util:list>
> 
> <bean id="xsltProvider"
> class="org.apache.cxf.jaxrs.provider.XSLTJaxbProvider">
> <property name="produceMediaTypes" ref="mediaTypes"/>
> </bean>
> 
> Actually, XSLTJaxbProvider has "application/*+xml" so it has to work...
> I just checked, it should be
> 
> application/rdf+xml rather than
> 
> application/xml+rdf ?
> 
> But if you do need application/xml+rdf
> 
> then please use the explicit customization ...
> 
> In meantime, may be I should also add "application/xml+*" to
> XSLTJaxbProvider
> 
> Hope it helps, Sergey
> 
>  
> 
> -----Original Message-----
> From: XeN0s [mailto:gael.lazzari@gmail.com] 
> Sent: 30 May 2009 14:11
> To: users@cxf.apache.org
> Subject: Re: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?
> 
> 
> I just investigate a little.
> 
> In application log, I found :
> 
> 2009-05-30 14:54:59 [org.apache.cxf.jaxrs.provider.XSLTJaxbProvider]
> WARN  -
> No template is available at : classpath:rdf-stylesheet.xsl
> 
> In XSLTJaxbProvider, there is a bug : 
> 
>  protected Templates createTemplates(String loc) {
>         try {
>             InputStream is = null;
>             if (loc.startsWith("classpath:")) {
>                 String path = loc.substring("classpath:".length() + 1);
>     
>                 // ===> path actually is set with "df-stylesheet.xsl"
> 
>                 is =
> this.getClass().getClassLoader().getResourceAsStream(path);
>             } else {
>                 File f = new File(loc);
>                 if (f.exists()) {
>                     is = new FileInputStream(f);
>                 }
>             }
>             if (is == null) {
>                 LOG.warning("No template is available at : " + loc);
>                 return null;
>             }
>             
>             Reader r = new BufferedReader(
>                            new InputStreamReader(is, "UTF-8"));
>             Source source = new StreamSource(r);
>             if (factory == null) {
>                 factory =
> (SAXTransformerFactory)TransformerFactory.newInstance();
>                 if (uriResolver != null) {
>                     factory.setURIResolver(uriResolver);
>                 }
>             }
>             return factory.newTemplates(source);
>             
>         } catch (Exception ex) {
>             LOG.warning("No template can be created : " +
> ex.getMessage());
>         }
>         return null;
>     }
> 
> 
> To avoid this bug, I modified my endpoint configuration : 
> 
> 	<util:map id="outMediaTemplates">
> 		<entry key="application/xml+rdf" value="classpath:
> rdf-stylesheet.xsl" />
> 	</util:map>
> 
> With this, Templates object is correctly created (maybe a JIRA issue
> will be
> needed ?)
> 
> But it doesn't solve my base problem : when calling the service
> /prodservice, I still get a ".No message body writer found for response
> class : ProductsDTO." html error page. 
> -- 
> View this message in context:
> http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-featur
> e---tp23792102p23793284.html
> Sent from the cxf-user mailing list archive at Nabble.com.
> 
> 
> 

-- 
View this message in context: http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-feature---tp23792102p23800447.html
Sent from the cxf-user mailing list archive at Nabble.com.


RE: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?

Posted by Sergey Beryozkin <sb...@progress.com>.
Hi,

I was using a forward slash in all my tests, for example : 
classpath:/rdf-stylesheet.xsl

but perhaps, given that a classloader is asked to load a resource
explicitly there is no need for this extra slash - but please use '/'
for a while.

> application/xml+rdf

XSLTJaxbProvider has static Produces/Consumes values, particularly,
@Produces has no "application/xml+rdf" in the list.

To make XSLTJaxbProvider recognize it you can customize its Produces
values, when registering a provider, for :

<util:list id="mediaTypes">
<value>application/xml</value>
<value>application/xml+rdf</value>
</util:list>

<bean id="xsltProvider"
class="org.apache.cxf.jaxrs.provider.XSLTJaxbProvider">
<property name="produceMediaTypes" ref="mediaTypes"/>
</bean>

Actually, XSLTJaxbProvider has "application/*+xml" so it has to work...
I just checked, it should be

application/rdf+xml rather than

application/xml+rdf ?

But if you do need application/xml+rdf

then please use the explicit customization ...

In meantime, may be I should also add "application/xml+*" to
XSLTJaxbProvider

Hope it helps, Sergey

 

-----Original Message-----
From: XeN0s [mailto:gael.lazzari@gmail.com] 
Sent: 30 May 2009 14:11
To: users@cxf.apache.org
Subject: Re: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?


I just investigate a little.

In application log, I found :

2009-05-30 14:54:59 [org.apache.cxf.jaxrs.provider.XSLTJaxbProvider]
WARN  -
No template is available at : classpath:rdf-stylesheet.xsl

In XSLTJaxbProvider, there is a bug : 

 protected Templates createTemplates(String loc) {
        try {
            InputStream is = null;
            if (loc.startsWith("classpath:")) {
                String path = loc.substring("classpath:".length() + 1);
    
                // ===> path actually is set with "df-stylesheet.xsl"

                is =
this.getClass().getClassLoader().getResourceAsStream(path);
            } else {
                File f = new File(loc);
                if (f.exists()) {
                    is = new FileInputStream(f);
                }
            }
            if (is == null) {
                LOG.warning("No template is available at : " + loc);
                return null;
            }
            
            Reader r = new BufferedReader(
                           new InputStreamReader(is, "UTF-8"));
            Source source = new StreamSource(r);
            if (factory == null) {
                factory =
(SAXTransformerFactory)TransformerFactory.newInstance();
                if (uriResolver != null) {
                    factory.setURIResolver(uriResolver);
                }
            }
            return factory.newTemplates(source);
            
        } catch (Exception ex) {
            LOG.warning("No template can be created : " +
ex.getMessage());
        }
        return null;
    }


To avoid this bug, I modified my endpoint configuration : 

	<util:map id="outMediaTemplates">
		<entry key="application/xml+rdf" value="classpath:
rdf-stylesheet.xsl" />
	</util:map>

With this, Templates object is correctly created (maybe a JIRA issue
will be
needed ?)

But it doesn't solve my base problem : when calling the service
/prodservice, I still get a ".No message body writer found for response
class : ProductsDTO." html error page. 
-- 
View this message in context:
http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-featur
e---tp23792102p23793284.html
Sent from the cxf-user mailing list archive at Nabble.com.


Re: How to use cxf 2.2.2 jaxrs XSLTJaxbProvider feature ?

Posted by XeN0s <ga...@gmail.com>.
I just investigate a little.

In application log, I found :

2009-05-30 14:54:59 [org.apache.cxf.jaxrs.provider.XSLTJaxbProvider] WARN  -
No template is available at : classpath:rdf-stylesheet.xsl

In XSLTJaxbProvider, there is a bug : 

 protected Templates createTemplates(String loc) {
        try {
            InputStream is = null;
            if (loc.startsWith("classpath:")) {
                String path = loc.substring("classpath:".length() + 1);
    
                // ===> path actually is set with "df-stylesheet.xsl"

                is =
this.getClass().getClassLoader().getResourceAsStream(path);
            } else {
                File f = new File(loc);
                if (f.exists()) {
                    is = new FileInputStream(f);
                }
            }
            if (is == null) {
                LOG.warning("No template is available at : " + loc);
                return null;
            }
            
            Reader r = new BufferedReader(
                           new InputStreamReader(is, "UTF-8"));
            Source source = new StreamSource(r);
            if (factory == null) {
                factory =
(SAXTransformerFactory)TransformerFactory.newInstance();
                if (uriResolver != null) {
                    factory.setURIResolver(uriResolver);
                }
            }
            return factory.newTemplates(source);
            
        } catch (Exception ex) {
            LOG.warning("No template can be created : " + ex.getMessage());
        }
        return null;
    }


To avoid this bug, I modified my endpoint configuration : 

	<util:map id="outMediaTemplates">
		<entry key="application/xml+rdf" value="classpath: rdf-stylesheet.xsl" />
	</util:map>

With this, Templates object is correctly created (maybe a JIRA issue will be
needed ?)

But it doesn't solve my base problem : when calling the service
/prodservice, I still get a ".No message body writer found for response
class : ProductsDTO." html error page. 
-- 
View this message in context: http://www.nabble.com/How-to-use-cxf-2.2.2-jaxrs-XSLTJaxbProvider-feature---tp23792102p23793284.html
Sent from the cxf-user mailing list archive at Nabble.com.