Rectangle 27 5

Interception Exceptions with JAXB

A ValidationEventHandler is used to intercept the exceptions that occur during unmarshalling. If you want to collect all the errors that occur you can use a ValidationEventCollector.

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        throw new RuntimeException("Always throw an error");
    }

}
import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.bind.util.ValidationEventCollector;

public class Demo {

    private static String XML = "<foo><bar>Hello World</bar></foo>";

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.unmarshal(new StringReader(XML));

        ValidationEventCollector vec = new ValidationEventCollector();
        unmarshaller.setEventHandler(vec);
        unmarshaller.unmarshal(new StringReader(XML));
        System.out.println(vec.getEvents().length);
    }

}
MessageBodyReader

You could create an instance of MessageBodyReader where you can leverage a ValidationEventHandler during the unmarshal process. Below is a link giving an example of how to implement a MessageBodyReader.

Slightly higher level, you could implement ContextResolver<Unmarshaller> and have the Unmarshaller returned have the appropriate ValidationEventHandler on it. It would look something like the following:

import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
import javax.xml.bind.helpers.DefaultValidationEventHandler;

@Provider
public class UnmarshallerResolver implements ContextResolver<Unmarshaller> {

    @Context Providers providers;

    @Override
    public Unmarshaller getContext(Class<?> type) {
        try {
            ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, MediaType.APPLICATION_XML_TYPE);
            JAXBContext jaxbContext;
            if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
                jaxbContext = JAXBContext.newInstance(type);
            }
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            return unmarshaller;
        } catch(JAXBException e) {
            throw new RuntimeException(e);
        }
    }

}

is there another option which doesn't include the implementation of a MessageBodyReader? I would like to use the automatic unmarshalling and just send, somehow, the thrown exception to the client.

ContextResolver<Unmarshaller>

we are using TomEE and, unfortunately, Apache CXF does not support @Provider... a colleague with more experience than me tried to register the provider programmatically and he failed...

RestEasy 3.0.7.FINAL does not understand ContextResolver<Unmarshaller> See: grepcode.com/file/repo1.maven.org/maven2/org.jboss.resteasy/ The MessageBodyReader approach works though

java - How to treat exception thrown by setter on JAXB automatic unmar...

java web-services rest jaxb jax-rs
Rectangle 27 0

Interception Exceptions with JAXB

A ValidationEventHandler is used to intercept the exceptions that occur during unmarshalling. If you want to collect all the errors that occur you can use a ValidationEventCollector.

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

    private String bar;

    public String getBar() {
        return bar;
    }

    public void setBar(String bar) {
        throw new RuntimeException("Always throw an error");
    }

}
import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.bind.util.ValidationEventCollector;

public class Demo {

    private static String XML = "<foo><bar>Hello World</bar></foo>";

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.unmarshal(new StringReader(XML));

        ValidationEventCollector vec = new ValidationEventCollector();
        unmarshaller.setEventHandler(vec);
        unmarshaller.unmarshal(new StringReader(XML));
        System.out.println(vec.getEvents().length);
    }

}
MessageBodyReader

You could create an instance of MessageBodyReader where you can leverage a ValidationEventHandler during the unmarshal process. Below is a link giving an example of how to implement a MessageBodyReader.

Slightly higher level, you could implement ContextResolver<Unmarshaller> and have the Unmarshaller returned have the appropriate ValidationEventHandler on it. It would look something like the following:

import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
import javax.xml.bind.helpers.DefaultValidationEventHandler;

@Provider
public class UnmarshallerResolver implements ContextResolver<Unmarshaller> {

    @Context Providers providers;

    @Override
    public Unmarshaller getContext(Class<?> type) {
        try {
            ContextResolver<JAXBContext> resolver = providers.getContextResolver(JAXBContext.class, MediaType.APPLICATION_XML_TYPE);
            JAXBContext jaxbContext;
            if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
                jaxbContext = JAXBContext.newInstance(type);
            }
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            return unmarshaller;
        } catch(JAXBException e) {
            throw new RuntimeException(e);
        }
    }

}

is there another option which doesn't include the implementation of a MessageBodyReader? I would like to use the automatic unmarshalling and just send, somehow, the thrown exception to the client.

ContextResolver<Unmarshaller>

we are using TomEE and, unfortunately, Apache CXF does not support @Provider... a colleague with more experience than me tried to register the provider programmatically and he failed...

java - How to treat exception thrown by setter on JAXB automatic unmar...

java web-services rest jaxb jax-rs