Jersey body writer errors for java.lang.Boolean wh

2020-06-22 05:30发布

I'm having trouble hunting down the the problem behind SEVERE: A message body writer for Java class java.lang.Boolean, and Java type class java.lang.Boolean, and MIME media type application/json was not found.

Here's what I've tried:

  • using jersey-bundle instead of these individual packages
  • POJOMappingFeature is already enabled
  • Adding Jackson as a dependency

I'm unclear on what else I need to do. This runs fine locally, so I'm unclear on why a dependency or two are not being packaged with the rest of the application.

pom.xml

    <jersey-version>1.17.1</jersey-version>

...

    <!-- Jersey -->
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-server</artifactId>
        <version>${jersey-version}</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-servlet</artifactId>
        <version>${jersey-version}</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-json</artifactId>
        <version>${jersey-version}</version>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-spring</artifactId>
        <version>${jersey-version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

Jersey Servlet

//add jersey servlet support
ServletRegistration jerseyServletRegistration = ctx.addServlet("JerseyServlet", new SpringServlet());
jerseyServletRegistration.setInitParameter("com.sun.jersey.config.property.packages", "com.company.product.resource");
jerseyServletRegistration.setInitParameter("com.sun.jersey.spi.container.ContainerResponseFilters", "com.company.product.resource.ResponseCorsFilter");
jerseyServletRegistration.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", Boolean.TRUE.toString());
jerseyServletRegistration.setInitParameter("com.sun.jersey.config.feature.DisableWADL", Boolean.TRUE.toString());
jerseyServletRegistration.setInitParameter("org.codehaus.jackson.map.DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY", Boolean.TRUE.toString());
jerseyServletRegistration.setLoadOnStartup(1);

My build process

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.1</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals><goal>shade</goal></goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.company.product.Main</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <skip>true</skip>
            </configuration>
        </plugin>

The exception:

SEVERE: A message body writer for Java class java.lang.Boolean, and Java type class java.lang.Boolean, and MIME media type application/json was not found
SEVERE: The registered message body writers compatible with the MIME media type are:
*/* ->
  com.sun.jersey.server.impl.template.ViewableMessageBodyWriter

Code that generates error:

@Path("/system")
public class SystemResource extends BaseResource {
    @GET
    @Path("/isOnline")
    public Boolean isOnline () {
        return Boolean.TRUE;
    }
}

@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
public class BaseResource {

}

I've verified that via the package log that jersey-json is being included in my jar. One area of uncertainty for me is which package/class actually provides the message body writer for Boolean?

Bounty was added because this is preventing me from running in our production environment and we really need this resolved.

标签: java jersey
4条回答
老娘就宠你
2楼-- · 2020-06-22 05:36

Try to include jackson also:

<jackson.version>1.9.12</jackson.version>
...
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-jaxrs</artifactId>
        <version>${jackson.version}</version>
    </dependency>
查看更多
迷人小祖宗
3楼-- · 2020-06-22 05:41

I assume that you're creating a one big jar file that contains your classes and all other dependencies. If this is correct (also the posted exception with only one provider leads me to this assumption) then make sure that all javax.ws.rs.ext.MessageBodyReader (and javax.ws.rs.ext.MessageBodyWriter) files from your dependencies are combined together and not just replaced by ones from the latest jar that has been added to you uber-jar.

Make sure that your javax.ws.rs.ext.MessageBodyWriter file in the uber-jar (in META-INF\services) contains providers from this file that is present in jersey-json:

com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$Wadl
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONJAXBElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$App
com.sun.jersey.json.impl.provider.entity.JSONListElementProvider$General
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$App
com.sun.jersey.json.impl.provider.entity.JSONArrayProvider$General
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$App
com.sun.jersey.json.impl.provider.entity.JSONObjectProvider$General
com.sun.jersey.json.impl.provider.entity.JSONWithPaddingProvider
com.sun.jersey.json.impl.provider.entity.JacksonProviderProxy

The last one is especially important in your case since you're using Jackson as your JSON provider (by setting POJOMappingFeature to true).

EDIT 1

Many modules in Jersey 1.x uses META-INF/services mechanism to lookup for JAX-RS provides (i.e. MessageBodyReaders, ...). This means that you can find a service file in a jar (i.e. jersey-json.jar!META-INF/services/javax.ws.rs.ext.MessageBodyReader) in which are defined classes that Jersey runtime uses (i.e. to read/write entity from/to input/output). The issue with creating an uber-jar is that you also need to combine contents of same services (defined by the files with same name in META-INF/services/ in your dependencies) into one file and bundle it into your executable jar (i.e. combine META-INF/services/javax.ws.rs.ext.MessageBodyReader from jersey-core and jersey-json and store it in META-INF/services/javax.ws.rs.ext.MessageBodyReader in your jar).

In case of Jersey you can use jersey-bundle as mentioned elsewhere but make sure the META-INF/services files from jersey-bundle are in your resulting jar.

查看更多
倾城 Initia
4楼-- · 2020-06-22 05:55

Overwriting of META-INF/services during jar creation seems to be the root cause (as described in the first answer). In my case adding:

<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>

to the <transformers> config of the maven-shade-plugin in pom.xml has fixed the problem. Including a full jersey-bundle seems to be an overkill.

查看更多
虎瘦雄心在
5楼-- · 2020-06-22 05:55

No need to add 3rd-party libs because it has been included in jersey-json package. The code seems not right, and it should be:

@Path("/system")
public class SystemResource extends BaseResource {
    @GET
    @Path("/isOnline")
    @Consumes({MediaType.APPLICATION_JSON})
    @Produces({MediaType.APPLICATION_JSON})
    public Boolean isOnline () {
        return Boolean.TRUE;
    }
}

public class BaseResource {

}
查看更多
登录 后发表回答