Hi CXF Team,
I have a problem with JAXBContext with type of class MyClass<T>. When I
have MyClass<MySecondClass>, JAXBContext is poupulated with only MyClass
and not with MySecondClass.
I have resolved my problem, but I find it's not a clean solution.
Let's me explain more my case.
I have a service wich uses Spring Data Page+Pageable (to manage pagination
with Spring Data JPA) in OSGi context :
------------------------------------------------------------------------------------------------------------------------
package org.akrogen.services;
import org.akrogen.domain.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface UserService {
Page<User> findAll(Pageable pageable);
}
------------------------------------------------------------------------------------------------------------------------
I wish call this services with remoting by using DOSGi with REST (I'm using
JSONProvider). So I have created XmlAdapter for Spring Data Page+Pageable
+ add REST annotations :
------------------------------------------------------------------------------------------------------------------------
package org.akrogen.services;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.akrogen.domain.User;
import org.akrogen.services.adapater.PageXmlAdapter;
import org.akrogen.services.adapater.PageableXmlAdapter;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
@Path("/user")
public interface UserService {
@GET
@Path("/findAll/{pageable}")
@Produces("application/json")
@XmlJavaTypeAdapter(PageXmlAdapter.class)
Page<User> findAll(@XmlJavaTypeAdapter(PageableXmlAdapter.class)
@PathParam("pageable")
Pageable pageable);
}
------------------------------------------------------------------------------------------------------------------------
To export my service (with REST) I use DOSGi :
------------------------------------------------------------------------------------------------------------------------
<osgi:reference id="userService"
interface="org.akrogen.services.UserService" />
<osgi:service interface="org.akrogen.services.UserService">
<osgi:service-properties>
<entry key="service.exported.interfaces" value="*" />
<entry key="service.exported.configs" value="org.apache.cxf.rs"
/>
<entry key="service.exported.intents" value="HTTP" />
<entry key="org.apache.cxf.rs.address" value="
http://localhost:9090/a" />
<entry key="org.apache.cxf.rs.databinding" value="jaxb" />
</osgi:service-properties>
<ref bean="userService" />
</osgi:service>
------------------------------------------------------------------------------------------------------------------------
So the provider used is the default Jettison JSONProvider.
When I access to my service I have this error :
------------------------------------------------------------------------------------------------------------------------
JAXBException occurred : class org.akrogen.domain.User nor any of its
super class is known to this context.. class org.akrogen.domain.User
nor any of its super class is known to this context..
------------------------------------------------------------------------------------------------------------------------
Which means that JAXBContext is not populate with User class. To resolve my
problem, I has to create My own JSONProvider wich add extra classes :
------------------------------------------------------------------------------------------------------------------------
package org.akrogen.cxf;
import org.akrogen.domain.User;
import org.apache.cxf.jaxrs.provider.JSONProvider;
public class MyJSONProvider extends JSONProvider {
public MyJSONProvider() {
Class[] userExtraClass = new Class[1];
userExtraClass[0] = User.class;
super.setExtraClass(userExtraClass);
}
}
------------------------------------------------------------------------------------------------------------------------
And I use it like this :
-----------------------------------------------------------------------------------------
<osgi:service interface="org.akrogen.services.UserService">
<osgi:service-properties>
<entry key="service.exported.interfaces" value="*" />
<entry key="service.exported.configs"
value="org.apache.cxf.rs" />
*<entry key="org.apache.cxf.rs.provider"
value="org.akrogen.cxf.MyJSONProvider"
/> *
<entry key="service.exported.intents" value="HTTP" />
<entry key="org.apache.cxf.rs.address"
value="http://localhost:9090/a" />
<entry key="org.apache.cxf.rs.databinding" value="jaxb"
/>
<!-- <entry key="org.apache.cxf.rs.httpservice.context"
value="/rest"
/> -->
</osgi:service-properties>
<ref bean="userService" />
</osgi:service>
-----------------------------------------------------------------------------------------
And it works great. But I find it's not a clean solution.
Here the 2 problems :
1) Cannot controlling JAXBCOntext with DOSGi
With DOSgi, it seems we cannot configure JAXBContent liek explained in
the doc :
------------------------------
<bean id="jaxbProvider" class="org.apache.cxf.jaxrs.provider.JSONProvider">
<property name="singleJaxbContext" value="true" />
<property name="extraClass">
<list>
<value>org.akrogen.domain.User</value>
</list>
</property>
</bean>
------------------------------
Because value is class name and nor Spring bean:
------------------------------
*<entry key="org.apache.cxf.rs.provider"
value="org.akrogen.cxf.MyJSONProvider" /> *
------------------------------
I think it should be cool, if we can set a Spring bean is the property
o*rg.apache.cxf.rs.provider
*2) *AbstractJAXBProvider* should populate Generic Type?
But I think to resolve the problem, it should be cool if
------------------------------
AbstractJAXBProvider#JAXBContext getJAXBContext(Class<?> type, Type
genericType) throws JAXBException
------------------------------
populate the JAXBContext with the genericType too. Is it a reason that
genericType is never used?
Thank a lot for your help.
Regards Angelo