Search code examples
javajbossjax-rsjboss7.xjava-ee-8

Consuming Json in JAX-RS: Prohibiting null values


I'm writing a simple REST service which expects a POST containing a Json. The service should refuse any Json not containing exactly the keys it expects. I'm using JAX-RS on a JBoss EAP 7.1 and have been unable to do this. Code example:

import javax.ejb.Stateless;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/")
@Stateless
@Produces("text/plain")
public class TestAccess
{
  @POST
  @Path("test/")
  @Consumes(MediaType.APPLICATION_JSON)
  public String consumeJson(TestClass c)
  {
    return c.toString();
  }

}
public class TestClass
{
  public String first;
  public String second;

  public String toString()
  {
    return (first + ", " + second);
  }
}

Previously I wrote consumeJson to expect expect a JsonObject and parsed that using a Jackson ObjectMapper. Doing this resulted in an error when receiving a Json missing keys. I think the way I'm doing it now is a "cleaner" way to do it as now the parameter list clearly shows what kind of Object the Json should describe. However, I don't want to check every single field first thing in the method nor do I want to add a isValid() method to every Object I get this way.

The example {"first" : "contentOfFirst"} returns "contentOfFirst, null" instead of failing.

EDIT: To clarify, I attempted something like this:

import javax.validation.constraints.NotNull;

public class TestClass
{
  @NotNull
  public String first;
  @NotNull
  public String second;

  public String toString()
  {
    return (first + ", " + second);
  }
}

This did not change the outcome, instead of failing (as it was supposed to) the POST still got the response "contentOfFirst, null". I'm aware these annotations still need a validator to validate them. I was (falsely?) under the impression that Jboss provides such a validator.


Solution

  • Turns out I missed that you need another annotation to enforce the checks:

      @POST
      @Path("test/")
      @Consumes(MediaType.APPLICATION_JSON)
      public String consumeJson(@Valid TestClass c)
      {
        return c.toString();
      }
    

    That's all that's needed for JBoss to actually enforce the checks.

    It should be noted that JBoss doesn't like the use of @Valid and generic classes (like List<PathSegment>) in the same parameter list.