Hello Sergey,
Here is my test on a simple GET service example in a project with interface
+ implementation classes:
@XmlSeeAlso({MyObjectFactory.class})
@Path("/service/")
public interface ServiceInterface {
@GET
@Path("/resources/{id}/")
public Resource getResource(@PathParam("id") int id);
}
-------------------------------------------------------------------------------------
@XmlSeeAlso({MyObjectFactory.class})
@Path("/service/")
public class Service implements ServiceInterface {
Map<Integer, Resource> resources= new HashMap<Integer, Resource>();
public Service(){
Resource r = new ResourceImpl1();
this.resources.put(r.getId(), r);
}
@GET
@Path("/resources/{id}/")
public Resource getResource(@PathParam("id") int id) {
System.out.println(this.resources.get(id).printInfo() );
return this.resources.get(id);
}
}
----------------------------------------------------------------------------------
@XmlRegistry
public class MyObjectFactory {
public MyObjectFactory() {
}
public Resource createResource() {
// return createInstance(Resource.class);
return createInstance(Resource.class);
//return new ResourceImpl1();
}
private <T> T createInstance(Class<T> anInterface) {
return (T) Proxy.newProxyInstance(anInterface.getClassLoader(), new
Class[] {anInterface}, new InterfaceInvocationHandler());
}
private static class InterfaceInvocationHandler implements
InvocationHandler {
private Map<String, Object> values = new HashMap<String, Object>();
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
if(methodName.startsWith("get")) {
return values.get(methodName.substring(3));
}
else {
values.put(methodName.substring(3), args[0]);
return null;
}
}
}
}
-------------------------------------------------------------------------------------------------
@XmlSeeAlso({ResourceImpl1.class, ResourceImpl2.class,
MyObjectFactory.class})
@XmlRootElement(name = "Resource")
@XmlType(propOrder={"name", "info"})
public interface Resource {
public int getId();
public void setId(int id);
public String getName();
public void setName(String name);
public String printInfo();
}
----------------------------------------------------------------------------------
@XmlRootElement(name = "ResourceImpl1")
public class ResourceImpl1 implements Resource{
private int id;
private String name;
public ResourceImpl1(int id, String name){
this.name=name;
}
public ResourceImpl1(){
this(0, "Impl1-default");
}
public String getName() {
// TODO Auto-generated method stub
return this.name;
}
public void setName(String name) {
// TODO Auto-generated method stub
this.name=name;
}
public String printInfo() {
// TODO Auto-generated method stub
return "This is a ResourceImpl1, id: " + this.id + "name: " +
this.name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
-------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="
http://cxf.apache.org/jaxrs"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxrs:server id="test" address="/">
<jaxrs:serviceBeans>
<ref bean="myWebService" />
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="MOXYProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="MOXYProvider" class="commun.MoxyJaxbContextResolver" />
<bean id="myWebService" class="server.Service" />
</beans>
---------------------------------------------------------------------------------
@Provider
public class MoxyJaxbContextResolver implements
ContextResolver<JAXBContext> {
public JAXBContext getContext(Class<?> type) {
try {
JAXBContext jc = JAXBContextFactory.createContext(new Class[]
{Resource.class}, null);
return jc;
} catch (JAXBException e) {
e.printStackTrace();
}
return null;
}
}
----------------------------------------------------------------------------
I get the following error when I try to call my get method from the
browser, by typing:
http://localhost:8080/rs-testServiceWithInterfaces1/service/resources/0
--------------------------
XML Parsing Error: syntax error
Location:
http://localhost:8080/rs-testServiceWithInterfaces1/service/resources/0
Line Number 1, Column 1:Error serializing the response, please check the
server logs, response class : ResourceImpl1
---------------------------
At the server, I get the following exceptions:
java.lang.NoClassDefFoundError:
org/eclipse/persistence/jaxb/JAXBContextFactory
at
commun.MoxyJaxbContextResolver.getContext(MoxyJaxbContextResolver.java:16)
at
commun.MoxyJaxbContextResolver.getContext(MoxyJaxbContextResolver.java:1)
at
org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.getJAXBContext(AbstractJAXBProvider.java:362)
at
org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.createMarshaller(AbstractJAXBProvider.java:476)
at
org.apache.cxf.jaxrs.provider.JAXBElementProvider.marshal(JAXBElementProvider.java:349)
at
org.apache.cxf.jaxrs.provider.JAXBElementProvider.writeTo(JAXBElementProvider.java:237)
at
org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:257)
at
org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:144)
at
org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:83)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at
org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77)
at
org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at
org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at
org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:206)
at
org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:218)
at
org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:161)
at
org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:114)
at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:184)
at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:112)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at
org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:163)
at
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
at
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
at
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:964)
at
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
at
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.ClassNotFoundException:
org.eclipse.persistence.jaxb.JAXBContextFactory
at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1523)
... 37 more
Feb 22, 2013 3:24:42 PM
org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor
writeResponseErrorMessage
WARNING: Error serializing the response, please check the server logs,
response class : ResourceImpl1.
Regards,
Diana
On Thu, Feb 21, 2013 at 11:17 AM, Sergey Beryozkin <[email protected]>wrote:
> Hi Diana,
>
> On 21/02/13 10:05, diana allam wrote:
>
>> Hello,
>>
>> I would like just to add more information about the utility of using
>> interfaces in cxf without implementation classes.
>> For my previous example about Resource, ResourceImpl1 and ResourceImpl2,
>> my
>> proposed solution by using an adapter of Resource class in order to allow
>> JAXB to use interfaces is not a very nice solution.
>> It will be nice if for example I define three interfaces, Resource,
>> Resource1 and Resource2, while Resource1 and Resource2 extends Resource.
>> That way, by using MOXY, I can avoid the use of adapters and I can
>> distinguish the treatment of messages at reception according to Resource1
>> or Resource2 types. This approach is very similar to what is actually
>> possible in cxf when for example a subclass instance is sent to a service
>> waiting a superclass of it.
>>
>> Can somebody help me to find the way to do it in cxf please?
>>
>> I'd like to help but at the moment I'm still not sure where exactly the
> problem is :-). I'd like to propose to simplify the setup a bit in order to
> narrow down the issue.
>
> Can you please type a single root resource, with a single @GET method, the
> way you'd expect it to be in your project (interface + implementation, or
> just implementation) and also type a very basic JAXB Bean class, with
> @XMLRootElement, register Moxy-aware ContextResolver and access this method
> from a browser - will you get it working ?
>
> If yes - try the same with a CXF RS code, just make sure you also register
> Moxy-aware ContextResolver on the client side, and try to read the response
> there - this should work too.
>
> Can you try the above first please and if that works - then lets move to
> your current issue, if not - lets try to figure out first why the simple
> case does not work
>
> Cheers, Sergey
>
>
> Regards,
>>
>> Diana
>>
>>
>>
>> On Wed, Feb 20, 2013 at 6:22 PM, diana allam<[email protected]>
>> wrote:
>>
>> thanks for your fast reply.
>>> I tested it because actually I am interested in deploying services with
>>> an
>>> interface type as input or output.
>>> I already tested on cxf how to do it by using implementation classes, for
>>> example, I defined a Resource interface and two implementations
>>> ResourceImpl1 and ResourceImpl2 such that all my REST methods are
>>> declared
>>> with a Resource type and I consider to differentiate the treatment at a
>>> reception of a ResourceImpl1 or ResourceImpl2. In order to do that I
>>> added
>>> the following two annotations to my Resource interface, and my
>>> AdaptedResource class (which is the adapted java instance for
>>> serialization
>>> and deserialization) contains an attribute which refers to the
>>> corresponding implementation (ResourceImpl1 or ResourceImpl2).
>>>
>>> ------------------------------**------------------------------**
>>> ------------------------
>>> @XmlSeeAlso({ResourceImpl1.**class, ResourceImpl2.class})
>>> @XmlJavaTypeAdapter(**MyResourceAdapter.class)
>>> public interface Resource {...}
>>>
>>> ------------------------------**------------------------------**
>>> ------------------------
>>>
>>>
>>> By curiosity, I tested MOXY without implementation classes and it works,
>>> but not for cxf, I didn't understand the problem
>>>
>>>
>>> On Wed, Feb 20, 2013 at 5:59 PM, Sergey Beryozkin<[email protected]**
>>> >wrote:
>>>
>>> Hi
>>>>
>>>> The appears to be some issue with your invocation handler, why do you
>>>> need it all ? If users had to write InvocationHandlers in order to be
>>>> able
>>>> to work with CXF RS client runtime then it would not be ideal at all :-)
>>>>
>>>> Thanks, Sergey
>>>>
>>>>
>>>> On 20/02/13 16:49, allam-di wrote:
>>>>
>>>> Hello all,
>>>>>
>>>>> I would like to use MOXY in order to handle interfaces as input
>>>>> arguments on
>>>>> my service methods.
>>>>> First, I tested MOXY data binding with interfaces as it is given in the
>>>>> following blog:
>>>>> http://blog.bdoughan.com/2010/****07/moxy-jaxb-map-interfaces-****<http://blog.bdoughan.com/2010/**07/moxy-jaxb-map-interfaces-**>
>>>>> to-xml.html<http://blog.**bdoughan.com/2010/07/moxy-**
>>>>> jaxb-map-interfaces-to-xml.**html<http://blog.bdoughan.com/2010/07/moxy-jaxb-map-interfaces-to-xml.html>
>>>>> >
>>>>>
>>>>>
>>>>> It works oK for me, thus I can serialize and deserialize messages by
>>>>> declaring a service method with an interface argument, without defining
>>>>> any
>>>>> implementation classes of this interface.
>>>>> In order to do a similar think integrated to cxf, I followed the
>>>>> discussion
>>>>> at this link:
>>>>> http://cxf.547215.n5.nabble.****com/How-to-configure-CXF-to-**
>>>>> use-different-****JAXBContextFactory-td5281773.****html<
>>>>> http://cxf.547215.n5.**nabble.com/How-to-configure-**
>>>>> CXF-to-use-different-**JAXBContextFactory-td5281773.**html<http://cxf.547215.n5.nabble.com/How-to-configure-CXF-to-use-different-JAXBContextFactory-td5281773.html>
>>>>> >
>>>>>
>>>>>
>>>>> Here is my ContextResolver Class:
>>>>> ------------------------------****-----------
>>>>>
>>>>>
>>>>> package project;
>>>>>
>>>>> @Provider
>>>>> public class MyContextResolver implements ContextResolver<JAXBContext>
>>>>> {
>>>>> private JAXBContext jc;
>>>>>
>>>>> public MyContextResolver() {
>>>>> try {
>>>>>
>>>>> jc = JAXBContext.newInstance(****MyObjectFactory.class);
>>>>>
>>>>> } catch(JAXBException e) {
>>>>> throw new RuntimeException(e);
>>>>> }
>>>>> }
>>>>>
>>>>> public JAXBContext getContext(Class<?> type) {
>>>>> try {
>>>>> jc = JAXBContextFactory.****createContext(new
>>>>>
>>>>> Class[]
>>>>> {MyObjectFactory.class}, null);
>>>>>
>>>>> return jc;
>>>>> } catch (JAXBException e) {
>>>>> e.printStackTrace();
>>>>> }
>>>>> return null;
>>>>> }
>>>>>
>>>>> }
>>>>>
>>>>> Here is my ObjectFactory class:
>>>>> ------------------------------****-----------
>>>>>
>>>>> @XmlRegistry
>>>>> public class MyObjectFactory {
>>>>>
>>>>>
>>>>> public Customer createCustomer() {
>>>>> return createInstance(Customer.class)****;
>>>>>
>>>>>
>>>>> }
>>>>> ...
>>>>>
>>>>>
>>>>> private<T> T createInstance(Class<T> anInterface) {
>>>>> return (T) Proxy.newProxyInstance(****
>>>>> anInterface.getClassLoader(),
>>>>>
>>>>> new
>>>>> Class[] {anInterface}, new InterfaceInvocationHandler());
>>>>> }
>>>>>
>>>>> private static class InterfaceInvocationHandler implements
>>>>> InvocationHandler {
>>>>>
>>>>> private Map<String, Object> values = new HashMap<String,
>>>>> Object>();
>>>>>
>>>>> public Object invoke(Object proxy, Method method, Object[]
>>>>> args)
>>>>> throws Throwable {
>>>>> String methodName = method.getName();
>>>>> if(methodName.startsWith("get"****)) {
>>>>> return values.get(methodName.****substring(3));
>>>>>
>>>>> }
>>>>> else {
>>>>> values.put(methodName.****substring(3), args[0]);
>>>>>
>>>>> return null;
>>>>> }
>>>>> }
>>>>>
>>>>> }
>>>>> }
>>>>>
>>>>> Here is my bean.xml file:
>>>>> ------------------------------****-----
>>>>>
>>>>> <?xml version="1.0" encoding="UTF-8"?>
>>>>> <beans
>>>>> xmlns="http://www.**springfram**ework.org/schema/**beans<http://springframework.org/schema/**beans>
>>>>> <http:**//www.springframework.org/**schema/beans<http://www.springframework.org/schema/beans>
>>>>> >
>>>>> "
>>>>>
>>>>> xmlns:xsi="http://www.w3.org/****2001/XMLSchema-instance<http://www.w3.org/**2001/XMLSchema-instance>
>>>>> <http:**//www.w3.org/2001/XMLSchema-**instance<http://www.w3.org/2001/XMLSchema-instance>
>>>>> >
>>>>> "
>>>>> xmlns:jaxrs="http://cxf.**apac**he.org/jaxrs <http://apache.org/jaxrs>
>>>>> <http://cxf.**apache.org/jaxrs <http://cxf.apache.org/jaxrs>>
>>>>> "
>>>>> xsi:schemaLocation="
>>>>> http://www.springframework.****org/schema/beans<http://www.**
>>>>> springframework.org/schema/**beans<http://www.springframework.org/schema/beans>
>>>>> >
>>>>> http://www.springframework.****org/schema/beans/spring-beans.****xsd<
>>>>> http://www.**springframework.org/schema/**beans/spring-beans.xsd<http://www.springframework.org/schema/beans/spring-beans.xsd>
>>>>> >
>>>>> http://cxf.apache.org/jaxrs
>>>>> http://cxf.apache.org/schemas/****jaxrs.xsd<http://cxf.apache.org/schemas/**jaxrs.xsd>
>>>>> <http://cxf.apache.**org/schemas/jaxrs.xsd<http://cxf.apache.org/schemas/jaxrs.xsd>
>>>>> >
>>>>> ">
>>>>> <import resource="classpath:META-INF/****cxf/cxf.xml" />
>>>>> <import resource="classpath:META-INF/****cxf/cxf-servlet.xml"
>>>>> />
>>>>>
>>>>> <jaxrs:server id="test" address="/">
>>>>> <jaxrs:serviceBeans>
>>>>> <ref bean="myWebService" />
>>>>> </jaxrs:serviceBeans>
>>>>> <jaxrs:providers>
>>>>> <ref bean="MOXYProvider" />
>>>>> </jaxrs:providers>
>>>>> </jaxrs:server>
>>>>>
>>>>> <bean id="MOXYProvider" class="project.****MyContextResolver"
>>>>> />
>>>>>
>>>>> <bean id="myWebService" class="project.Service" />
>>>>> </beans>
>>>>>
>>>>> Here is a the constructor of my service class:
>>>>> ------------------------------****----------------------
>>>>>
>>>>> public Service(){
>>>>>
>>>>> ObjectFactory objectFactory = new ObjectFactory();
>>>>> Customer c = objectFactory.createCustomer()****;
>>>>>
>>>>> c.setName("defaultName");
>>>>> Address address = objectFactory.createAddress();
>>>>> address.setCity("****defaultAddress");
>>>>> address.setStreet("****defaultStreet");
>>>>> c.setAddress(address);
>>>>>
>>>>> this.resources.put(c.getName()****, s);
>>>>>
>>>>>
>>>>> }
>>>>>
>>>>> and here is my GET method:
>>>>>
>>>>> @GET
>>>>> @Path("/resources/{name}/")
>>>>> public Customer getCustomer(@PathParam("name") String name) {
>>>>> return this.resources.get(name);
>>>>> }
>>>>>
>>>>> When I call my service, I get the following error:
>>>>>
>>>>> Exception in thread "main" Status : 500
>>>>> Headers :
>>>>> Date : Wed, 20 Feb 2013 16:02:30 GMT
>>>>> Content-Length : 65
>>>>> Content-Type : text/plain
>>>>> Connection : close
>>>>> Server : Apache-Coyote/1.1
>>>>> Error message :
>>>>> No message body writer has been found for response class $Proxy5.
>>>>>
>>>>> at
>>>>> org.apache.cxf.jaxrs.client.****ClientProxyImpl.checkResponse(****
>>>>> ClientProxyImpl.java:250)
>>>>> at
>>>>> org.apache.cxf.jaxrs.client.****ClientProxyImpl.****handleResponse(**
>>>>> ClientProxyImpl.java:517)
>>>>> at
>>>>> org.apache.cxf.jaxrs.client.****ClientProxyImpl.****
>>>>> doChainedInvocation(**
>>>>> ClientProxyImpl.java:487)
>>>>> at
>>>>> org.apache.cxf.jaxrs.client.****ClientProxyImpl.invoke(**
>>>>>
>>>>> ClientProxyImpl.java:188)
>>>>> at $Proxy18.getResource(Unknown Source)
>>>>> at project.Client.main(Client.****java:35)
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> Any idea about this error please?
>>>>>
>>>>> Regards,
>>>>>
>>>>> Diana
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> View this message in context: http://cxf.547215.n5.nabble.**
>>>>> com/How-to-configure-cxf-to-****use-MOXY-Jaxb-for-RESTful-****
>>>>> tp5723506.html<http://cxf.**547215.n5.nabble.com/How-to-**
>>>>> configure-cxf-to-use-MOXY-**Jaxb-for-RESTful-tp5723506.**html<http://cxf.547215.n5.nabble.com/How-to-configure-cxf-to-use-MOXY-Jaxb-for-RESTful-tp5723506.html>
>>>>> >
>>>>>
>>>>> Sent from the cxf-user mailing list archive at Nabble.com.
>>>>>
>>>>>
>>>>
>>>> --
>>>> Sergey Beryozkin
>>>>
>>>> Talend Community Coders
>>>> http://coders.talend.com/
>>>>
>>>> Blog: http://sberyozkin.blogspot.com
>>>>
>>>>
>>>
>>>
>>
>
>