users@jersey.java.net

Re: [Jersey] XSD validation during unmarshalling

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Wed, 23 Jul 2008 10:50:50 +0200

Hi Andrew,

Great! Glad you managed to resolve it. So in this case you did not
require a schema and i presume are relying on the underlying data-type
validation of JAXB (which provides very loose validation of structure
and data types).

Paul.

Andrew Cole wrote:
> Thanks for your dedication to the list, Paul. We have resolved this
> issue without needing to maintain a map of JAXB classes. We implemented
> a ValidationEventCollector, and set this to handle validation events
> coming from the unmarshaller. Our ValidationEventCollector throws an
> unchecked exception (JAXBParserException) which we then handle with
> ExceptionMapper. The code is below.
>
> @Provider
> public class ValidatingJAXBContextResolver implements
> ContextResolver<JAXBContext> {
> public JAXBContext getContext(Class<?> type) {
> try {
> return new ValidatingJAXBContext(type);
> } catch (JAXBException e) {
> System.out.println("Caught an exception validation jaxb
> context");
> return null;
> }
> }
> }
>
> public class ValidatingJAXBContext extends JAXBContext {
> private final JAXBContext jaxbContext;
>
>
> private static class MyValidationEventCollector extends
> ValidationEventCollector
> {
> @Override
> public boolean handleEvent(ValidationEvent event) throws
> RuntimeException
> {
> ValidationEventLocator vel = event.getLocator();
> if (event.getSeverity() == event.ERROR ||
> event.getSeverity() == event.FATAL_ERROR)
> {
> String error = "XML Validation Exception: " +
> event.getMessage() + " at row: " + vel.getLineNumber() + " column: " +
> vel.getColumnNumber();
> throw new JAXBParserException(error); // this is just a
> simple unchecked exception
> // use ExceptionMapper to do whatever you want with it
> }
> return true;
> }
> }
>
>
> public ValidatingJAXBContext(Class... classesToBeBound) throws
> JAXBException {
> jaxbContext = JAXBContext.newInstance(classesToBeBound);
> }
>
> public ValidatingJAXBContext(Class[] classesToBeBound, Map<String,
> Object> properties) throws JAXBException {
> jaxbContext = JAXBContext.newInstance(classesToBeBound, properties);
> }
>
> @Override
> public Unmarshaller createUnmarshaller() throws JAXBException {
> Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
> MyValidationEventCollector vec = new MyValidationEventCollector();
> unmarshaller.setEventHandler( vec );
> return unmarshaller;
> }
>
>
> @Override
> public Marshaller createMarshaller() throws JAXBException {
> return jaxbContext.createMarshaller();
> }
>
> @Override
> public Validator createValidator() throws JAXBException {
> return jaxbContext.createValidator();
> }
>
> }
>
> On Tue, Jul 22, 2008 at 8:26 AM, Paul Sandoz <Paul.Sandoz_at_sun.com
> <mailto:Paul.Sandoz_at_sun.com>> wrote:
>
> Hi Andrew,
>
> Unmarshaller.setValidating is indeed deprecated and you need to set
> the Schema object to validate against.
>
> In this respect i am unsure how you can create a general validating
> mechanism unless you keep a map of known JAXB class to Schema instance.
>
> You will have to create the Schema instances from the
> correspondingly available XSD, more info can be found here [1].
>
> Rather than creating a general validating mechanism it might be
> better to have a general mechanism you inherit from for specific
> validating purposes i.e. provides the JAXB context and a set of schema.
>
> Paul.
>
> [1]
> http://www.java-tips.org/java-ee-tips/java-architecture-for-xml-binding/what-is-new-in-jaxb-2.0.html
>
> Andrew Cole wrote:
>
> Now that Paul is back, I would like to promote this thread
> again. Paul-- any help you can provide will be greatly appreciated.
>
> Thanks,
> Andrew
>
> On Mon, Jul 7, 2008 at 2:22 PM, Andrew Cole <andrew_at_9summer.com
> <mailto:andrew_at_9summer.com> <mailto:andrew_at_9summer.com
> <mailto:andrew_at_9summer.com>>> wrote:
>
> While Paul is on vacation, can somebody help illuminate his
> response
> to my query below? Trying to follow his instructions, I have
> implemented a ContextResolver as follows:
>
> @Provider
> public class ValidatingJAXBContextResolver implements
> ContextResolver<JAXBContext> {
> public JAXBContext getContext(Class<?> type) {
> try {
> return new ValidatingJAXBContext(type);
> } catch (JAXBException e) {
> return null;
> }
> }
> }
>
> and a JAXBContext (modeled after the JSONJAXBContext in the
> jersey
> source) as:
>
> public class ValidatingJAXBContext extends JAXBContext {
> private final JAXBContext jaxbContext;
>
> public ValidatingJAXBContext(Class... classesToBeBound)
> throws JAXBException {
> jaxbContext =
> JAXBContext.newInstance(classesToBeBound);
> }
>
> public ValidatingJAXBContext(Class[] classesToBeBound,
> Map<String,
> Object> properties) throws JAXBException {
> jaxbContext = JAXBContext.newInstance(classesToBeBound,
> properties);
> }
>
> @Override
> public Unmarshaller createUnmarshaller() throws
> JAXBException {
> Unmarshaller unmarshaller =
> jaxbContext.createUnmarshaller();
> unmarshaller.setValidating(true);
> return unmarshaller;
> }
>
> @Override
> public Marshaller createMarshaller() throws JAXBException {
> return jaxbContext.createMarshaller();
> }
>
> @Override
> public Validator createValidator() throws JAXBException {
> return jaxbContext.createValidator();
> }
>
> }
>
> Now, when I hit a method that would require unmarshalling
> content from
> XML, I receive an exception at my call to setValidating:
> java.lang.UnsupportedOperationException
> at
>
> com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.setValidating(UnmarshallerImpl.java:483)
> at
>
> myCode.ValidatingJAXBContext.createUnmarshaller(ValidatingJAXBContext.java:33)
> at
>
> com.sun.ws.rest.impl.provider.entity.XMLRootElementProvider.readFrom(XMLRootElementProvider.java:58)
> at
>
> com.sun.ws.rest.spi.container.AbstractContainerRequest.getEntity(AbstractContainerRequest.java:179)
> [stack trace truncated]
>
> Am I on the right track here? As I understand it, the call to
> setValidating is deprecated in JAXB 2.0 and I should use
> setSchema.
> Is this correct? If so, how can I have my
> ValidatingJAXBContext class
> create an appropriate javax.xml.validation.Schema object for this
> call, based on the classToBeBound passed in to the constructor?
>
> On Thu, Jul 3, 2008 at 10:20 PM, Paul Sandoz
> <Paul.Sandoz_at_sun.com <mailto:Paul.Sandoz_at_sun.com>
> <mailto:Paul.Sandoz_at_sun.com <mailto:Paul.Sandoz_at_sun.com>>> wrote:
> >
> > On Jul 4, 2008, at 1:05 AM, Andrew Cole wrote:
> >
> > Hi all
> >
> > I'm using Jersey 0.7 and have a number of methods that accept
> objects unmarshalled from XML via JAXB bindings. It does not
> appear
> that the unmarshalling process is validating the XML against the
> schema used to create the JAXB bindings. For instance, I have a
> pattern restriction on a string element that is not being
> respected,
> and I can leave out elements that have a minOccurs of 1. How
> can I
> configure the unmarshaller to validate against my schema?
> >
> >
> > Currently you need to supply your own JAXBContext that
> returns a
> validating unmarshaller for unmarshalling the JAXB types that
> require validation.
> > See ContextResolver [1].
> > In this case you would do:
> > public class MyContextResolver implements
> ContextResolver<JAXBContext> {
> > JAXBContext getContext(Class<?> type) { ... }
> > }
> > I plan to make this easier so you can use ContextResolver
> with an
> Unmarshaller/Marshaller thus you don't have to wrap JAXBContext.
> > Paul.
> > [1]
>
> https://jsr311.dev.java.net/nonav/releases/0.8/javax/ws/rs/ext/ContextResolver.html
>
>
>
> --
> | ? + ? = To question
> ----------------\
> Paul Sandoz
> x38109
> +33-4-76188109
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> <mailto:users-unsubscribe_at_jersey.dev.java.net>
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
> <mailto:users-help_at_jersey.dev.java.net>
>
>

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109