[
https://issues.apache.org/jira/browse/CXF-4064?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13193906#comment-13193906
]
Sergey Beryozkin commented on CXF-4064:
---------------------------------------
This is CXF 2.3.3... Can you try CXF 2.3.8 please ? May be there were some
issues with the annotation inheritance in 2.3.3, definitely should work now
> Problem with JAX-RS annotated interface between client and service
> -------------------------------------------------------------------
>
> Key: CXF-4064
> URL: https://issues.apache.org/jira/browse/CXF-4064
> Project: CXF
> Issue Type: Bug
> Components: JAX-RS
> Affects Versions: 2.3.3
> Environment: $ uname -a
> Darwin dented.local 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36
> PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
> $ java -version
> java version "1.6.0_29"
> Java(TM) SE Runtime Environment (build 1.6.0_29-b11-402-10M3527)
> Java HotSpot(TM) Client VM (build 20.4-b02-402, mixed mode)
> Reporter: David Liszewski
>
> When one is developing both server and client components, it is highly
> desirable to adhere to DRY principles and declare a JAX-RS resource interface
> exactly once. The User Guide (Index > RESTful Services > JAX-RS > JAX-RS
> Client API) explicitly says that it should be possible to share an annotated
> interface between client and server:
> {quote}
> With the proxy-based API, one can reuse on the client side the interfaces or
> even the resource classes which have already been designed for processing the
> HTTP requests on the server side (note that a {{cglib}}-nodeps dependency
> will need to be available on the classpath for proxies created from concrete
> classes). When reused on the client side, they simply act as remote proxies.
> {quote}
> However, when I modified the basic JAX-RS sample to do exactly that, two
> (GETs) of the four methods do not work. In fact, the only modification made
> was to refactor the interface with annotations out of the server
> implementation class, without even attempting a proxy client.
> _Note_: I definitely reproduced this with {{2.3.3}} but I think same occurs
> in 2.5.x releases.
> This is what {{mvn -Pclient}} prints out running {{./samples/jax_rs/basic}}:
> {noformat}
> Sent HTTP GET request to query customer info
> java.io.FileNotFoundException:
> http://localhost:9000/customerservice/customers/123
> at
> sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1434)
> at java.net.URL.openStream(URL.java:1010)
> at demo.jaxrs.client.Client.main(Client.java:53)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.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:680)
> Sent HTTP GET request to query sub resource product info
> java.io.FileNotFoundException:
> http://localhost:9000/customerservice/orders/223/products/323
> at
> sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1434)
> at java.net.URL.openStream(URL.java:1010)
> at demo.jaxrs.client.Client.main(Client.java:64)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
> at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.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:680)
> Sent HTTP PUT request to update customer info
> Response status code: 200
> Response body:
> Sent HTTP POST request to add customer
> Response status code: 200
> Response body:
> <?xml version="1.0" encoding="UTF-8"
> standalone="yes"?><Customer><id>124</id><name>Jack</name></Customer>
> {noformat}
> The added interface {{ICustomerService.java}} and modified {{Client.java}}
> and {{CustomerService.java}} classes are shown below. {{Client.java}} was
> modified to catch any exceptions thrown and continue with the next function
> point:
> {code:title=ICustomerService.java|borderStyle=solid}
> package demo.jaxrs;
> import javax.ws.rs.DELETE;
> import javax.ws.rs.GET;
> import javax.ws.rs.POST;
> import javax.ws.rs.PUT;
> import javax.ws.rs.Path;
> import javax.ws.rs.PathParam;
> import javax.ws.rs.core.Response;
> import demo.jaxrs.server.Customer;
> import demo.jaxrs.server.Order;
> @Path("/customerservice/")
> public interface ICustomerService {
> @GET
> @Path("/customers/{id}/")
> public Customer getCustomer(@PathParam("id") String id);
> @PUT
> @Path("/customers/")
> public Response updateCustomer(Customer customer);
> @POST
> @Path("/customers/")
> public Response addCustomer(Customer customer);
> @DELETE
> @Path("/customers/{id}/")
> public Response deleteCustomer(@PathParam("id") String id);
> @Path("/orders/{orderId}/")
> public Order getOrder(@PathParam("orderId") String orderId);
> }
> {code}
> {code:title=Client.java|borderStyle=solid}
> package demo.jaxrs.client;
> import java.io.File;
> import java.io.InputStream;
> import java.net.URL;
> import org.apache.commons.httpclient.HttpClient;
> import org.apache.commons.httpclient.methods.FileRequestEntity;
> import org.apache.commons.httpclient.methods.PostMethod;
> import org.apache.commons.httpclient.methods.PutMethod;
> import org.apache.commons.httpclient.methods.RequestEntity;
> import org.apache.cxf.helpers.IOUtils;
> import org.apache.cxf.io.CachedOutputStream;
> public final class Client {
> private Client() {
> }
> public static void main(String args[]) {
> // Sent HTTP GET request to query all customer info
> /*
> * URL url = new URL("http://localhost:9000/customers");
> * System.out.println("Invoking server through HTTP GET to query all
> * customer info"); InputStream in = url.openStream(); StreamSource
> * source = new StreamSource(in); printSource(source);
> */
> // Sent HTTP GET request to query customer info
> try {
> System.out.println("Sent HTTP GET request to query customer
> info");
> URL url = new
> URL("http://localhost:9000/customerservice/customers/123");
> InputStream in = url.openStream();
> System.out.println(getStringFromInputStream(in));
> } catch (Exception e) {
> e.printStackTrace();
> }
> // Sent HTTP GET request to query sub resource product info
> try{
> System.out.println("\n");
> System.out.println("Sent HTTP GET request to query sub resource
> product info");
> URL url = new
> URL("http://localhost:9000/customerservice/orders/223/products/323");
> InputStream in = url.openStream();
> System.out.println(getStringFromInputStream(in));
> } catch (Exception e) {
> e.printStackTrace();
> }
> // Sent HTTP PUT request to update customer info
> System.out.println("\n");
> System.out.println("Sent HTTP PUT request to update customer info");
> Client client = new Client();
> String inputFile =
> client.getClass().getResource("update_customer.xml").getFile();
> File input = new File(inputFile);
> PutMethod put = new
> PutMethod("http://localhost:9000/customerservice/customers");
> RequestEntity entity = new FileRequestEntity(input, "text/xml;
> charset=ISO-8859-1");
> put.setRequestEntity(entity);
> HttpClient httpclient = new HttpClient();
> try {
> int result = httpclient.executeMethod(put);
> System.out.println("Response status code: " + result);
> System.out.println("Response body: ");
> System.out.println(put.getResponseBodyAsString());
> } catch (Exception e) {
> e.printStackTrace();
> } finally {
> // Release current connection to the connection pool once you are
> // done
> put.releaseConnection();
> }
> // Sent HTTP POST request to add customer
> System.out.println("\n");
> System.out.println("Sent HTTP POST request to add customer");
> inputFile =
> client.getClass().getResource("add_customer.xml").getFile();
> input = new File(inputFile);
> PostMethod post = new
> PostMethod("http://localhost:9000/customerservice/customers");
> post.addRequestHeader("Accept" , "text/xml");
> entity = new FileRequestEntity(input, "text/xml; charset=ISO-8859-1");
> post.setRequestEntity(entity);
> httpclient = new HttpClient();
> try {
> int result = httpclient.executeMethod(post);
> System.out.println("Response status code: " + result);
> System.out.println("Response body: ");
> System.out.println(post.getResponseBodyAsString());
> } catch (Exception e) {
> e.printStackTrace();
> } finally {
> // Release current connection to the connection pool once you are
> // done
> post.releaseConnection();
> }
> System.out.println("\n");
> System.exit(0);
> }
> private static String getStringFromInputStream(InputStream in) throws
> Exception {
> CachedOutputStream bos = new CachedOutputStream();
> IOUtils.copy(in, bos);
> in.close();
> bos.close();
> return bos.getOut().toString();
> }
> }
> {code}
> {code:title=CustomerService.java|borderStyle=solid}
> package demo.jaxrs.server;
> import java.util.HashMap;
> import java.util.Map;
> import javax.ws.rs.DELETE;
> import javax.ws.rs.GET;
> import javax.ws.rs.POST;
> import javax.ws.rs.PUT;
> import javax.ws.rs.Path;
> import javax.ws.rs.PathParam;
> import javax.ws.rs.core.Response;
> import demo.jaxrs.ICustomerService;
> public class CustomerService implements ICustomerService {
> long currentId = 123;
> Map<Long, Customer> customers = new HashMap<Long, Customer>();
> Map<Long, Order> orders = new HashMap<Long, Order>();
> public CustomerService() {
> init();
> }
> public Customer getCustomer(@PathParam("id") String id) {
> System.out.println("----invoking getCustomer, Customer id is: " + id);
> long idNumber = Long.parseLong(id);
> Customer c = customers.get(idNumber);
> return c;
> }
> public Response updateCustomer(Customer customer) {
> System.out.println("----invoking updateCustomer, Customer name is: "
> + customer.getName());
> Customer c = customers.get(customer.getId());
> Response r;
> if (c != null) {
> customers.put(customer.getId(), customer);
> r = Response.ok().build();
> } else {
> r = Response.notModified().build();
> }
> return r;
> }
> public Response addCustomer(Customer customer) {
> System.out.println("----invoking addCustomer, Customer name is: " +
> customer.getName());
> customer.setId(++currentId);
> customers.put(customer.getId(), customer);
> return Response.ok(customer).build();
> }
> public Response deleteCustomer(@PathParam("id") String id) {
> System.out.println("----invoking deleteCustomer, Customer id is: " +
> id);
> long idNumber = Long.parseLong(id);
> Customer c = customers.get(idNumber);
> Response r;
> if (c != null) {
> r = Response.ok().build();
> customers.remove(idNumber);
> } else {
> r = Response.notModified().build();
> }
> return r;
> }
> public Order getOrder(@PathParam("orderId") String orderId) {
> System.out.println("----invoking getOrder, Order id is: " + orderId);
> long idNumber = Long.parseLong(orderId);
> Order c = orders.get(idNumber);
> return c;
> }
> final void init() {
> Customer c = new Customer();
> c.setName("John");
> c.setId(123);
> customers.put(c.getId(), c);
> Order o = new Order();
> o.setDescription("order 223");
> o.setId(223);
> orders.put(o.getId(), o);
> }
> }
> {code}
> Here is a {{diff}} output, should that be more helpful:
> {noformat}
> $ diff -r basic/src basic_interface/src
> Only in basic_interface/src/demo/jaxrs: ICustomerService.java
> diff -r basic/src/demo/jaxrs/client/Client.java
> basic_interface/src/demo/jaxrs/client/Client.java
> 40c40
> < public static void main(String args[]) throws Exception {
> ---
> > public static void main(String args[]) {
> 50,53c50,57
> < System.out.println("Sent HTTP GET request to query customer info");
> < URL url = new
> URL("http://localhost:9000/customerservice/customers/123");
> < InputStream in = url.openStream();
> < System.out.println(getStringFromInputStream(in));
> ---
> > try {
> > System.out.println("Sent HTTP GET request to query customer
> > info");
> > URL url = new
> > URL("http://localhost:9000/customerservice/customers/123");
> > InputStream in = url.openStream();
> > System.out.println(getStringFromInputStream(in));
> > } catch (Exception e) {
> > e.printStackTrace();
> > }
> 56,60c60,68
> < System.out.println("\n");
> < System.out.println("Sent HTTP GET request to query sub resource
> product info");
> < url = new
> URL("http://localhost:9000/customerservice/orders/223/products/323");
> < in = url.openStream();
> < System.out.println(getStringFromInputStream(in));
> ---
> > try{
> > System.out.println("\n");
> > System.out.println("Sent HTTP GET request to query sub resource
> > product info");
> > URL url = new
> > URL("http://localhost:9000/customerservice/orders/223/products/323");
> > InputStream in = url.openStream();
> > System.out.println(getStringFromInputStream(in));
> > } catch (Exception e) {
> > e.printStackTrace();
> > }
> 72d79
> <
> 77a85,86
> > } catch (Exception e) {
> > e.printStackTrace();
> 99a109,110
> > } catch (Exception e) {
> > e.printStackTrace();
> 105d115
> <
> diff -r basic/src/demo/jaxrs/server/CustomerService.java
> basic_interface/src/demo/jaxrs/server/CustomerService.java
> 32,33c32,34
> < @Path("/customerservice/")
> < public class CustomerService {
> ---
> > import demo.jaxrs.ICustomerService;
> >
> > public class CustomerService implements ICustomerService {
> 42,43d42
> < @GET
> < @Path("/customers/{id}/")
> 51,52d49
> < @PUT
> < @Path("/customers/")
> 67,68d63
> < @POST
> < @Path("/customers/")
> 78,79d72
> < @DELETE
> < @Path("/customers/{id}/")
> 96d88
> < @Path("/orders/{orderId}/")
> {noformat}
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators:
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira