Talend Service Factory example: jaxrs-jaxws-java-first extension

Employee

Talend Service Factory example: jaxrs-jaxws-java-first extension

Environment:
talend-sf-2.4.2.0
Windows 7
Java version 1.60.0_26-b03
Jetty 6.1.15 servlet container

Description:
Extended jaxrs-jaxws-java-first example (from talend-sf-2.4.2.0-examples.zip, http://www.talend.com/download.php#SF) to add a simple new method.
It is produces an exception on the client side on an existing method.
Added the following new method to common/src/main/java/common/codefirst/HelloWorld.java, see the code snippet below and screen shot:
<code>
// ** New call
@GET
@Produces("text/xml")
User byId(@QueryParam("text") String id);
// ** Existing call
@GET
@Produces("text/plain")
String sayHi(@QueryParam("text") String text);
</code>
Added the following code in Service/src/main/java/service/codefirst/HellooWorldImpl.java file, see the code snippet below and screen shot"
<code>
public User byId(String id) {
return new UserImpl(id);
}
</code>
Added the following code in client/src/main/java/client/RESTClient.java, see the code snippet below and the screen shot:
<code>
private void useHelloService(HelloWorld service, String user) {
// New call
System.out.println("entering byId");
User us = service.byId("test User");
System.out.println(us.getName());
// Existing call
System.out.println("Getting the list of existing users");
printUsers(service.getUsers());
</code>

Problem:
Did a full clean build of the example code. Ran both the Server code and the Client code through maven.
The following is the stack trace on the client. There is no stack trace on the server. It appears to be a client marshaling problem.
Also see the attached screen shot:
Using CXF JAX-RS proxy to invoke on HelloWorld service
entering byId
test User
Getting the list of existing users
java.lang.ClassCastException: common.codefirst.UserImpl cannot be cast to common
.codefirst.IntegerUserMap
at common.codefirst.IntegerUserMapAdapter.unmarshal(IntegerUserMapAdapte
r.java:11)
at org.apache.cxf.jaxrs.utils.JAXBUtils.useAdapter(JAXBUtils.java:107)
at org.apache.cxf.jaxrs.utils.JAXBUtils.useAdapter(JAXBUtils.java:90)
at org.apache.cxf.jaxrs.provider.AbstractJAXBProvider.checkAdapter(Abstr
actJAXBProvider.java:512)
at org.apache.cxf.jaxrs.provider.JAXBElementProvider.readFrom(JAXBElemen
tProvider.java:158)
at org.apache.cxf.jaxrs.client.AbstractClient.readBody(AbstractClient.ja
va:435)
at org.apache.cxf.jaxrs.client.ClientProxyImpl.handleResponse(ClientProx
yImpl.java:520)
at org.apache.cxf.jaxrs.client.ClientProxyImpl.doChainedInvocation(Clien
tProxyImpl.java:480)
at org.apache.cxf.jaxrs.client.ClientProxyImpl.invoke(ClientProxyImpl.ja
va:188)
at $Proxy16.getUsers(Unknown Source)
at client.RESTClient.useHelloService(RESTClient.java:83)
at client.RESTClient.sayHelloRest(RESTClient.java:55)
at client.RESTClient.main(RESTClient.java:117)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:291)
at java.lang.Thread.run(Thread.java:662)

NOTE: this problem disappears if the new byId() method is stubbed out in HelloWorld.java.
I have tried a number of ways to workaround this problem but so far without any success. Any comments or suggestions are very appreciated.
Employee

Re: Talend Service Factory example: jaxrs-jaxws-java-first extension

Hi
it appears the JAX-RS provider is finding the wrong adapter in case of byId(). I think explicitly adding @XmlJavaTypeAdapter(UserAdapter.class) to byId() annotations will fix it.
I'll check in meantime why a wrong adapter is picked up
Thanks, Sergey
Employee

Re: Talend Service Factory example: jaxrs-jaxws-java-first extension

Actually, the problem is that byId() and getUsers() are equal selection candidates on the server side (thanks to Dan Kulp who spotted it first), note they share @GET, @Path and @Produces thus the spec says the selections basically random in this case. A proxy is unaware about it though and expects UserAdaper to unmarshall the response.
Updating byid like this should fix it:
@Path("{id}")
@Produces("text/xml")
@GET
User byId(String id) {...}
Employee

Re: Talend Service Factory example: jaxrs-jaxws-java-first extension

Hi Sergey,
Thanks for your suggestion. I tried it, however it is now throws "Unresolved variables; only 0 value(s) given for 1 unique variable(s)" on the call to the byId method in the RESTClient. Below are code snippets:
HelloWorld.java:
// ** New call
@GET
@Produces("text/xml")
@Path("{id}")
User byId(long id);
RESTClient.java
HelloWorld service = JAXRSClientFactory.create(address, HelloWorld.class);
....
// New call
System.out.println("entering byId");
// Now fails with "Unresolved variables; only 0 value(s) given for 1 unique variable(s)" message
User us = service.byId(1);
System.out.println(us.getName());

Any suggestions are very appreciated.
One Star

Re: Talend Service Factory example: jaxrs-jaxws-java-first extension

I have the same problem. Did you find a solution?