Using default Providers/MessageBodyWriters in Jersey 2

前端 未结 3 556
天涯浪人
天涯浪人 2020-12-09 20:29

Just starting with Jersey, I\'ve been trying to reproduce the simple example in the latest Jersey documentation \'building responses\'. This part, as far as I understand, sh

相关标签:
3条回答
  • 2020-12-09 20:51

    As far as the text/plain format, does this work?

    return Response.created(createdUri).type(MediaType.TEXT_PLAIN).entity("someContent").build();
    

    For JSON output, I have these dependencies

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
    

    as well as a jaxb implementation. Any will do, I use

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
        </dependency>
    

    I also define an object mapper provider, though I'm not 100% sure that it's required (unless you want to customize):

    import javax.ws.rs.ext.ContextResolver;
    import javax.ws.rs.ext.Provider;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.SerializationFeature;
    import com.fasterxml.jackson.databind.type.TypeFactory;
    import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
    
    @Provider
    public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
        ObjectMapper mapper;
    
        public ObjectMapperProvider() {
            mapper = new ObjectMapper();
            mapper.configure( SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false );
            mapper.configure( SerializationFeature.INDENT_OUTPUT, true );
            mapper.configure( SerializationFeature.WRITE_NULL_MAP_VALUES, true );
            mapper.configure( SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, true );
            mapper.setAnnotationIntrospector( new JaxbAnnotationIntrospector(TypeFactory.defaultInstance()) );
        }
    
        @Override
        public ObjectMapper getContext(Class<?> type) {
            return mapper;
        }
    }
    

    Also, I think you need to register the Jackson feature:

    @ApplicationPath("")
    public class Application extends ResourceConfig {
        public Application() {
            register( JacksonFeature.class );
        }
    }
    

    I should note that this is all configured using Jersey 2.11.

    0 讨论(0)
  • 2020-12-09 21:08

    First Issue:

    javax.ws.rs.client.Entity is a client side class. The JAX-RS spec doesn't say anything about its usage on the server side. But I can confirm with many different tests, that the result will be similar to what you are seeing (with Jersey at least). With Resteasy, it will just send out the Entity.toString()

    Since this doesn't work for either Resteasy or Jersey, I won't say it's a bug, but possible a mistake in the Jersey documentation, which exampled it usage as follows:

    @POST
    @Consumes("application/xml")
    public Response post(String content) {
      URI createdUri = ...
      String createdContent = create(content);
      return Response.created(createdUri)
                             .entity(Entity.text(createdContent)).build();
    }
    

    The above failed for me also. But you are not wrong in saying

    ...several data types are by default supported

    as they are. To get your example to work, simply change the Entity.text("someContent") to simply "someContent"

    return Response.created(createdUri).entity("someContent").build();
    

    And just for completeness, client side usage might look something like

    Response response = webTarget.request().post(Entity.text("Hello World"));
    

    which works just fine.

    Second Issue:

    Up until (I believe) Jersey 2.9, the jersey-media-json-jackson module is not auto-configured. So with 2.6, we need to set up the configuration either through package scanning in the web.xml or in the Application subclass. Either way, a web.xml is required. As stated here in regards to a 2.x servlet environment, which Tomcat 6 is.

    In Servlet 2.5 environment, you have to explicitly declare the Jersey container Servlet in your Web application's web.xml deployment descriptor file.

    So to scan for the JSON provider classes, you should specify the package in the jersey.config.server.provider.packages init-param. An example web.xml would be something like this

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
                           http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
        <servlet>
            <servlet-name>Jersey Web Application</servlet-name>
            <servlet-class>
                org.glassfish.jersey.servlet.ServletContainer
            </servlet-class>
            <init-param>
                <param-name>jersey.config.server.provider.packages</param-name>
                <param-value>
                    thepackage.of.your.resources,
                    org.codehaus.jackson.jaxrs      <!-- Jackson providers -->
                </param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Jersey Web Application</servlet-name>
            <url-pattern>/api/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    You are also allowed to use an Application subclass (which ResourceConfig extends from). We just need to specify it in the web.xml. An example configuration might be something like

    public class MyApplication extends ResourceConfig {  
        public MyApplication() {
            register(JacksonFeature.class);
            packages("thepackage.of.your.resources");
        }
    }
    
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
                           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                           xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                           http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
        <servlet>
            <servlet-name>MyApplication</servlet-name>
            <servlet-class>
                org.glassfish.jersey.servlet.ServletContainer
            </servlet-class>
            <init-param>
                <param-name>javax.ws.rs.Application</param-name>
                <param-value>jersey2.tomcat6.MyApplication</param-value>
            </init-param>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>MyApplication</servlet-name>
            <url-pattern>/api/*</url-pattern>
        </servlet-mapping>
    </web-app>
    

    Note: All of this was tested against your same environment, besides using Eclipse. I am using Netbeans, though it shouldn't make any difference. Also the only Maven dependencies I needed were

    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>${jersey.version}</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${jersey.version}</version>
        </dependency>
    </dependencies>
    
    <jersey.version>2.6</jersey.version>
    

    On another note, to simplify development, I just created a simple Maven archetype with the following coordinates

    GroupId:     org.glassfish.jersey.archetypes
    ArtifactId:  jersey-quickstart-webapp
    Version:     2.6
    

    You can also see Creating a New Project from Maven Archetype

    0 讨论(0)
  • 2020-12-09 21:12

    In my case, I added the jersey-media-json-jackson dependency. It worked for me.

    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.20</version>
    </dependency>
    
    0 讨论(0)
提交回复
热议问题