1

I have been stuck on this problem for a number of days and am now looking for some guidance to help solve the issue. I have considerable experience with jax-ws under Metro, but this is my first adventure into jax-rs with Jersey. To simplify the moving parts I took the jersey-examples-moxy code as a starting point.

I modified the example project to accept both XML and JSON. I thought this would be simple, but I seem to be missing something because it has been a painful experience. The code runs without issue when I am requesting "application/xml", and the GET will work for "application/json", but when I try to do a PUT with the JSON the server is returning a 500 status code. I can see the JSON being sent in the PUT request, but the server seems to be having an issue accepting the JSON.

Here is the modified CustomerResource.java file segment. All I did was add the MediaType.APPLICATION_JSON parameter to the Produces and Consumes annotations.

@Path("/customer")
public class CustomerResource {

  private static Customer customer = createInitialCustomer();

  @GET
  @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
  public Customer getCustomer() {
    return customer;
  }

  @PUT
  @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
  public void setCustomer(Customer c) {
    customer = c;
  }

  private static Customer createInitialCustomer() {
    Customer result = new Customer();

    result.setName("Jane Doe");
    result.setAddress(new Address("123 Any Street", "My Town"));
    result.getPhoneNumbers().add(new PhoneNumber("work", "613-555-1111"));
    result.getPhoneNumbers().add(new PhoneNumber("cell", "613-555-2222"));

    return result;
  }
}

I modified the MoxyAppTest.java file to request XML and JSON MediaTypes in separate tests:

@Test
public void testJaxBCustomer() throws Exception {
    final WebTarget webTarget = target().path("customer");

    Customer customer = webTarget.request(MediaType.APPLICATION_XML).get(Customer.class);
    assertEquals("Jane Doe", customer.getName());

    customer.setName("Tom Dooley");
    Response response = webTarget.request(MediaType.APPLICATION_XML).put(Entity.xml(customer));
    assertEquals(204, response.getStatus());

    Customer updatedCustomer = webTarget.request(MediaType.APPLICATION_XML).get(Customer.class);
    assertEquals(customer, updatedCustomer);
}

@Test
public void testJsonCustomer() throws Exception {
    final WebTarget webTarget = target().path("customer");

    Customer customer = webTarget.request(MediaType.APPLICATION_JSON).get(Customer.class);
    assertEquals("Tom Dooley", customer.getName());

    customer.setName("Bobby Boogie");
    Response response = webTarget.request(MediaType.APPLICATION_JSON).put(Entity.json(customer));
    assertEquals(204, response.getStatus());

    Customer updatedCustomer = webTarget.request(MediaType.APPLICATION_JSON).get(Customer.class);
    assertEquals(customer, updatedCustomer);
}

In the App.java file I added the JsonMoxyConfigurationContextResolver class and a registerInstances() call in the createApp() method. (Note taking this out does not change result).

public static ResourceConfig createApp() {
    return new ResourceConfig().packages("org.glassfish.jersey.examples.xmlmoxy")
            .register(new MoxyXmlFeature())
            .registerInstances(new JsonMoxyConfigurationContextResolver());      
}

@Provider
final static class JsonMoxyConfigurationContextResolver implements ContextResolver<MoxyJsonConfig> {

    @Override
    public MoxyJsonConfig getContext(Class<?> objectType) {
        final MoxyJsonConfig configuration = new MoxyJsonConfig();

        Map<String, String> namespacePrefixMapper = new HashMap<String, String>(1);
        namespacePrefixMapper.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");

        configuration.setNamespacePrefixMapper(namespacePrefixMapper);
        configuration.setNamespaceSeparator(':');

        return configuration;
    }
}

Here is the log segment showing the "application/xml" PUT was successful with a status of 204:

Aug 23, 2013 1:23:50 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 3 * LoggingFilter - Request received on thread main
3 > PUT http://localhost:9998/customer
3 > Accept: application/xml
3 > Content-Type: application/xml
<?xml version="1.0" encoding="UTF-8"?>
<customer><personal-info><name>Tom Dooley</name></personal-info><contact-info><address><city>My Town</city><street>123 Any Street</street></address><phone-number type="work">613-555-1111</phone-number><phone-number type="cell">613-555-2222</phone-number></contact-info></customer>

Aug 23, 2013 1:23:50 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 4 * LoggingFilter - Response received on thread main
4 < 204
4 < Date: Fri, 23 Aug 2013 05:23:50 GMT

Now for the "application/json" logs:

Aug 23, 2013 1:23:51 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 3 * LoggingFilter - Request received on thread main
3 > PUT http://localhost:9998/customer
3 > Accept: application/json
3 > Content-Type: application/json
{"personal-info":{"name":"Bobby Boogie"},"contact-info":{"address":{"city":"My Town","street":"123 Any Street"},"phone-number":[{"type":"work","value":"613-555-1111"},{"type":"cell","value":"613-555-2222"}]}}

Aug 23, 2013 1:23:51 AM org.glassfish.jersey.filter.LoggingFilter log
INFO: 4 * LoggingFilter - Response received on thread main
4 < 500
4 < Date: Fri, 23 Aug 2013 05:23:50 GMT
4 < Content-Length: 0
4 < Connection: close

As you can see the server is returning a status code of 500. The Grizzly test container is not generating a log capturing any exception information, and it looks like nothing is returned in the 500 response. Is there a way I can get the additional exception details?

Any suggestions on how to proceed?

Thank you!

Hacksaw
  • 69
  • 1
  • 13
  • Please consider making your question shorter. You will be more probable to get an answer. – IvanH Aug 23 '13 at 07:19

1 Answers1

1

Actually what causes this issue is a combination of:

  • @XmlPath annotation on Customer bean, and
  • namespacePrefixMapper that you're setting into MoxyJsonConfig

which causes a NullPointerException during (un)marshalling JSON. This has been fixed in nightly versions (2.5.1 and 2.6.1) of MOXy. You can download it from Nightly Builds page.

If you don't want to change the version of MOXy at the moment, simply remove this line

configuration.setNamespacePrefixMapper(namespacePrefixMapper);

from JsonMoxyConfigurationContextResolver and you should be fine.

Regarding the logging issue - we know about it and it's beings fixed (should be resolved in Jersey 2.3).

Michal Gajdos
  • 10,339
  • 2
  • 43
  • 42
  • In the time I have been stuck I have rewritten the example without the @XmlPath annotations and the problem still exists, however, removing the **configuration.setNamespacePrefixMapper(namespacePrefixMapper)** line fixed the issue. I could have sworn I tried that in my previous attempts, but looks like I did not. Thank you very much, your help is greatly appreciated! – Hacksaw Aug 23 '13 at 14:37