Как отправить сложный объект с помощью клиента Джерси на сервер jax-rc?

Я разработал клиент и сервер REST. Сервер использует Spring и CXF и некоторые сервисы, которые @Procoduces и @Consumes некоторые объекты. Это прототип услуг:

@GET
@Produces("application/xml")
@Path("/Order/Id/{orderId}")
public Order getOrder(@PathParam("orderId") String officeId);

@GET
@Produces("application/xml")
@Path("/Order/All")
public OrderList getAllOrders();

@POST
@Consumes("application/xml")
@Path("/Order/")
public String sendOrder(Order order);

Запрос GET с путем /Order/All отвечает правильно, но когда я отправляю POST на путь /Order/ с помощью клиента Джерси, он не работает. это код клиента:

Client client = Client.create();
WebResource webResource = client.resource("server address/Order/");
ClientResponse response = webResource.accept(MediaType.APPLICATION_XML).type(MediaType.APPLICATION_XML)
        .post(ClientResponse.class, `an order object`);

И я получил это исключение на сервере:

2014-01-26 12:22:33 WARN  JAXRSUtils:499 - No operation matching request path "/services/Order/Hey" is found, Relative Path: /Order/, HTTP Method: POST, ContentType: application/xml, Accept: application/xml,. Please enable FINE/TRACE log level for more details.
2014-01-26 12:22:33 WARN  WebApplicationExceptionMapper:73 - javax.ws.rs.ClientErrorException
    at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:503)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:218)
    at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:90)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239)
    at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222)
    at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153)
    at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:206)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
    at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
    at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:154)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
    at org.eclipse.jetty.server.Server.handle(Server.java:366)
    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
    at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:971)
    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:1033)
    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:644)
    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
    at java.lang.Thread.run(Thread.java:724)

person Pooya    schedule 26.01.2014    source источник


Ответы (2)


Вы нацеливаете запрос POST не на /services/Order/, а на /services/Order/Hey (это исключение). Этот ресурс не существует в вашем приложении. Проверьте, использует ли клиент правильный URI и не содержит ли ваше приложение какого-либо фильтра, способного изменить URI запроса.

person Michal Gajdos    schedule 26.01.2014

Ваш шаблон REST не соответствует наиболее распространенному соглашению. Это вызывает недоумение! В частности, нормально моделировать набор заказов как один ресурс, например, /Orders, а отдельные заказы использовать как подресурсы, /Orders/{id}. Чтобы получить это, вы должны аннотировать свои методы следующим образом:

@GET
@Produces("application/xml")
@Path("/Order/{orderId}")
public Order getOrder(@PathParam("orderId") String orderId);

@GET
@Produces("application/xml")
@Path("/Order")
public OrderList getAllOrders();

@POST
@Consumes("application/xml")
@Produces("text/plain")
@Path("/Order")
public String sendOrder(Order order);

(Вы вероятно хотите вернуть туда Response из обработчика POST и, возможно, также передать параметр @Context UriInfo ui, который позволит вам отправить перенаправление на созданный ресурс заказа. Но это не так критично. )

Как только вы это сделаете, ваш GET-запрос к /services/Order/Hey станет осмысленным, в результате чего метод реализации getOrder будет вызываться с orderId, установленным в "Hey".

person Donal Fellows    schedule 26.01.2014