Статьи

Работа с MessageException на сервере Джерси

 За последние пару дней я снова познакомился  со своим хорошим другом  Джерси, и когда я начал  подниматься и бегать, мне напомнили, что вещи, которые казались легкими в то время, не так просты, когда начинали с нуля.

В конце концов я остановился на использовании  Солнечный Глисона «s  Д4-минимальное  хранилище , какие провода до Джерси с Джексоном, Guice и молы , которые , казалось , как хорошее место для начала.

Я предпочитаю создавать объекты JSON явно, а не настраивать автоматическое сопоставление, поэтому первым делом я изменил  JacksonResource,  чтобы у него была конечная точка, которая возвращала созданный вручную объект JSON:

@Path("/jackson")
public class JacksonResource {
    @GET
    @Produces( { MediaType.APPLICATION_JSON })
    @Path("/awesome/{who}")
    public Response sayOtherGreeting(@PathParam("who") String name) {
        ObjectNode result = JsonNodeFactory.instance.objectNode();
        result.put("name", name);
        return Response.ok().entity(result).build();
    }
}

Когда я попытался поразить это в браузере, я получил следующее исключение:

SEVERE: The registered message body writers compatible with the MIME media type are:
application/json ->
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
  com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONWithPaddingProvider
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
  com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy
 
Jul 21, 2013 11:11:17 AM com.sun.jersey.spi.container.ContainerResponse logException
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class org.codehaus.jackson.node.ObjectNode, and Java type class org.codehaus.jackson.node.ObjectNode, and MIME media type application/json was not found
	at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:285)
	at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1451)
	at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1363)
	at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1353)
	at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:414)
	at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
	at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:708)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
	at com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:263)
	at com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:178)
	at com.google.inject.servlet.ManagedServletPipeline.service(ManagedServletPipeline.java:91)
	at com.google.inject.servlet.FilterChainInvocation.doFilter(FilterChainInvocation.java:62)
	at com.google.inject.servlet.ManagedFilterPipeline.dispatch(ManagedFilterPipeline.java:118)
	at com.google.inject.servlet.GuiceFilter.doFilter(GuiceFilter.java:113)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1338)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:484)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
	at org.eclipse.jetty.server.Server.handle(Server.java:350)
	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
	at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:630)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:606)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
	at java.lang.Thread.run(Thread.java:722)
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class org.codehaus.jackson.node.ObjectNode, and Java type class org.codehaus.jackson.node.ObjectNode, and MIME media type application/json was not found
	... 35 more

Это та же самая проблема, о которой я  писал в прошлом году в отношении Клиента Джерси .

Это заняло у меня некоторое время, но в конце концов я нашел решение проблемы, скрытой примерно на полпути вниз  по посту StackOverflow за похожее исключение .

Нам нужно добавить следующее свойство в нашу конфигурацию Джерси:

Map<String, Object> config = new HashMap<String, Object>();
config.put("com.sun.jersey.api.json.POJOMappingFeature", true);

Если мы  отредактируем SampleConfig из шаблона,  он теперь будет выглядеть так:

public class SampleConfig extends GuiceServletContextListener {
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {
            @Override
            protected void configureServlets() {
                /* bind the REST resources */
                bind(BenchResource.class);
                bind(SampleResource.class);
                bind(JacksonResource.class);
 
                /* bind jackson converters for JAXB/JSON serialization */
                bind(MessageBodyReader.class).to(JacksonJsonProvider.class);
                bind(MessageBodyWriter.class).to(JacksonJsonProvider.class);
                Map<String, String> initParams = new HashMap<String, String>();
                initParams.put("com.sun.jersey.config.feature.Trace",
                        "true");
                initParams.put("com.sun.jersey.api.json.POJOMappingFeature", "true");
                serve("*").with(
                        GuiceContainer.class,
                        initParams);
            }
        });
    }
 
}

Если мы нажмем «/ jackson / awesome / mark», теперь он вернет JSON, как и ожидалось:

$ curl http://localhost:8080/jackson/awesome/mark -w "\n"
{"name":"mark"}