4

When I send this request:

{"invalidField": "value", "date": "value"}

to my rest service:

@PUT
@Consumes("application/json")
public void putJson(Test content) {
    System.out.println(content.toString());
}

I expected to get an exception because:

  1. There is no invalidField in my domain model.
  2. Date format is not valid.

But really I get test object with null values. My dmain model is:

public class Test {
    private String name;
    private Date date; 
    //getters and setters here  
}

I think this is not a valid behavior. How can I fix that?

Thanks for help.

Solution:

As Blaise Doughan said, it is required to extend MOXy's MOXyJsonProvider and override the preReadFrom method to set custom javax.xml.bind.ValidationEventHandler. But the problem is that Jersey's ConfigurableMoxyJsonProvider will always be picked first, unless you write a MessageBodyWriter/MessageBodyReader that is parameterized with a more specific type than Object. To solve this problem it is necessary to disable MOXy and then enable CustomMoxyJsonProvider.

Example:

  1. Create your own feature that extends javax.ws.rs.core.Feature:

    @Provider
    public class CustomMoxyFeature implements Feature {
        @Override
        public boolean configure(final FeatureContext context) {
            final String disableMoxy = CommonProperties.MOXY_JSON_FEATURE_DISABLE + '.' + context.getConfiguration().getRuntimeType().name().toLowerCase();
            context.property(disableMoxy, true);
           return true;
        }
    }
    
  2. Create your own provider that extends MOXyJsonProvider:

    @Provider
    public class CustomMoxyJsonProvider extends MOXyJsonProvider {
        @Override
        protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, Unmarshaller unmarshaller) throws JAXBException {
        unmarshaller.setEventHandler(new ValidationEventHandler() {
            @Override
            public boolean handleEvent(ValidationEvent event) {
                return false;
            }
        });
    }
    

    }

  3. Add this resources in Application config:

    package com.vinichenkosa.moxyproblem;
    
    import java.util.Set;
    import javax.ws.rs.core.Application;
    
    @javax.ws.rs.ApplicationPath("webresources")
    public class ApplicationConfig extends Application {
    
        @Override
        public Set<Class<?>> getClasses() {
            Set<Class<?>> resources = new java.util.HashSet<>();
            addRestResourceClasses(resources);
            return resources;
        }
    
        private void addRestResourceClasses(Set<Class<?>> resources) {
            resources.add(com.vinichenkosa.moxyproblem.TestResource.class);
            resources.add(com.vinichenkosa.moxyproblem.custom_provider.CustomMoxyFeature.class);
            resources.add(com.vinichenkosa.moxyproblem.custom_provider.CustomMoxyJsonProvider.class);
        }
    }
    
  • Thanks for the reply. I just wanted to migrate from Jackson to Moxy, as it is now the default library for Glassfish. But because of this behavior as long as it is not possible. – Sergey Vinichenko Dec 29 '14 at 11:16
  • Not sure about this solution, as your ValidationEventHandler will return false for every error, but this is not what you want. You want false only in specific cases. – YevgenyL Jun 08 '20 at 05:20

1 Answers1

2

MOXy will report information about invalid property values, but by default it does not fail on them. The reporting is done to an instance of javax.xml.bind.ValidationEventHandler. You can override the ValidationEventHandler set on the Unmarshaller to do this.

You can create your own MesageBodyReader/MessageBodyWriter that extends MOXy's MOXyJsonProvider and override the preReadFrom method to do this.

@Override
protected void preReadFrom(Class<Object> type, Type genericType,
        Annotation[] annotations, MediaType mediaType,
        MultivaluedMap<String, String> httpHeaders,
        Unmarshaller unmarshaller) throws JAXBException {
    unmarshaller.setEventHandler(yourValidationEventHandler);
}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thank you for your response. I tried this solution but my custom MoxyJsonProvider is not used. I used the solution described here http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html with the only difference, I used @ javax.ws .rs.ApplicationPath annotations instead of a servlet. If I use ContextResolver , as described here http://blog.bdoughan.com/2013/06/moxy-is-new-default-json-binding.html it works, but it seems not suitable for my purpose. My server is Glassfish 4.0 – Sergey Vinichenko Jan 26 '15 at 08:55
  • 1
    Blaise question on this one. It seems as though for json there is no way for the eventHandler to be called. In org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.startUnmappedElement() there is a check to see if the media type is xml prior to issuing a warning to the event handler. For JSON is there a way to warn on unmapped content? – Manuel Quinones Jun 10 '15 at 18:53
  • @ManuelQuinones did you find solution for this? – YevgenyL Jun 08 '20 at 07:47