0
votes

I got the following error message every time I try to call my REST service

[2016-09-01T16:27:37.782+0200] [Payara 4.1] [SEVERE] []   [org.glassfish.jersey.message.internal.WriterInterceptorExecutor] [tid: _ThreadID=28 _ThreadName=http-listener-1(3)] [timeMillis: 1472740057782] [levelValue: 1000] [[MessageBodyWriter not found for media type=application/json, type=class xxx.JsonClass, genericType=class xxx.JsonClass.]]

Here's the REST service (stripped to the relevant part):

import javax.ejb.EJB;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;


@Path("/service")
public class Service {

  @GET
  @Path("/callme")
  @Produces(MediaType.APPLICATION_JSON)
  public JsonClass callme(//
      @QueryParam("test") final String test, //
       ....) {
    return new JsonClass();
  }
}

The JSON Class

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

public class JsonClass {

  private String test;

  public JsonClass(final String test....) {
   ...
  }

  @JsonProperty
  public String getTest() {
    return this.test;
  }
}

POM.xml (interesting parts)

<!-- DO NOT change the scope for jersey: https://java.net/jira/browse/JERSEY-1941 -->
<dependency>
  <groupId>org.glassfish.jersey.media</groupId>
  <artifactId>jersey-media-json-jackson</artifactId>
  <version>2.8</version>
  <scope>provided</scope>
</dependency>

My setup is:

  • JDK8/JEE7 (build 1.8.0_51-b16)
  • Glassfish 4.1 Payara
  • Maven 3.2.5

This is what I tried so far:

I still think it's a dependency problem here. However I'm out of ideas what could be the problem.

1

1 Answers

2
votes

Unfortunately my last post was marked as duplicate although the problem and the solution was different. Therefore I'm posting a new question with the two solutions to hopefully help you avoid head banging at the table for several hours.

Preferred solution:

Apparently GF4 ships with MoxyJson which I didn't want to use. To integrate your own dependency - in my case Jackson - you need to disable the MoxyJson with the below code.

@ApplicationPath("/")
public class ApplicationConfig extends Application {

  /**
   * {@inheritDoc}
   */
  @Override
  public Map<String, Object> getProperties() {
    final Map<String, Object> properties = new HashMap<String, Object>();
    properties.put("jersey.config.server.disableMoxyJson", true);

    return properties;
  }
}

Then add your own dependencies, e.g. in my case only those two because the others are referenced by another lib I use.

<dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.6.2</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.6.2</version>
</dependency>

Finally I made the mistake of not setting a value to the @JsonProperty annotations which will cause a No MessageBodyWriter found exception. To avoid that use the following ony relevant getters of your class.

@JsonProperty("randomName")
public String getRandomName(){
...
}

Alternative:

Worse than above you'll need to disable MoxyJson, register each service individually, and fix a Bug when using ResourceConfig of GF.

@ApplicationPath("/")
public class ApplicationConfig extends ResourceConfig {

/**
* The default constructor.
*/
public ApplicationConfig() {

// Disable Moxy and use Jackson
this.property(ServerProperties.MOXY_JSON_FEATURE_DISABLE, true);

// Register own provider classes
this.register(Fully.Qualified.Path.To.Your.Service.class);

// Register Jackson provider
// Workaround for GF4.1 bug for details: https://java.net/jira/browse/GLASSFISH-21141
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JaxbAnnotationModule());
this.register(new JacksonJaxbJsonProvider(mapper, JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS));
}
}

You'll need an additional dependency for the ResourceConfig class.

 <dependency>
  <groupId>com.fasterxml.jackson.jaxrs</groupId>
  <artifactId>jackson-jaxrs-json-provider</artifactId>
  <version>2.6.2</version>
</dependency>
<dependency>
  <groupId>com.fasterxml.jackson.dataformat</groupId>
  <artifactId>jackson-dataformat-xml</artifactId>
  <version>2.6.2</version>
</dependency>

<dependency>
  <groupId>org.glassfish.main.extras</groupId>
  <artifactId>glassfish-embedded-all</artifactId>
  <version>4.1.1</version>
  <scope>provided</scope>
</dependency>

Finally the same as above - be aware to use @JsonProperty with a set value.