javaee / jaxb-v2

Other
210 stars 100 forks source link

JAXB Validation Without Schema #430

Open glassfishrobot opened 17 years ago

glassfishrobot commented 17 years ago

Enhance JAXB to allow validation based on annotations, without requiring a schema.

One of the benefits of JAXB 2 is that a schema is not required; annotating Java classes alone allows for XML serialization/deserialization. With the deprecation of the Unmarshaller.setValidating() in favor of the unmarshaller.setSchema() method, however, validation is only available when an XSD is present. Ideally, validation can occur during unarshalling (or marshalling) without a physical schema file.

Environment

Operating System: All Platform: All

Affected Versions

[2.1.5]

glassfishrobot commented 17 years ago

Reported by shelleyb

glassfishrobot commented 13 years ago

tuukkamustonen said: It's now year 2011 and this ticket was created roughly 2,5 years ago. No comments here, but seems like it has been discussed "many times". See at least http://stackoverflow.com/questions/3844701/jaxb-validation-of-xml-during-unmarshalling and http://old.nabble.com/Using-JAXB2-Commons-with-the-jaxws-maven-plugin--td29108017.html

Despite of this feature being (maybe) not implemented, updating the ticket with the current status of consideration wouldn't be a bad thing?

glassfishrobot commented 13 years ago

pastafarian said: +1 on the need for better annotation-based validation. Every time we make a change to our data objects, we (re)generate our XSDs from code and share them with other projects / clients.

Without better XML schema validation options, we might as well be using JSON

glassfishrobot commented 13 years ago

lennartj said: This is a rather important issue, since everyone using annotated POJOs - rather than XML schema - as the model source at present need to create their own custom validation for generated objects due to the lack of validation facilities for this scenario within JAXB.

Validation of JAXB structures should really be part of the JAXB family of tasks; otherwise we condemn project to using XSDs (as opposed to POJOs) as the data model source. POJO entities should also be first-class citizens, without the need to generate intermediary XML Schemas simply to enable some kind of validation).

... which implies we need to provide validation facilities without XML Schema.

glassfishrobot commented 12 years ago

cruelfate said: Indeed. I'm not looking for much .. heck I'd take something that only regarded XmlElement(required=true) so I wouldn't have to resort to this horror show:

Use Case

import javax.xml.bind.annotation.XmlElement;
import JaxbValidator.ValidationException;
import org.testng.annotations.Test;

public class JaxbValidatorTest {

    static class Llama {
        @XmlElement(required = false)
        private final String no;

        @XmlElement(required = true)
        private final String yes;

        public Llama(String no, String yes) {
            super();
            this.no = no;
            this.yes = yes;
        }
    }
    @Test
    public void validateRequired() {
        try {
            Llama o = new Llama("a", "b");
            // THE MAIN EVENT - see if 'required' is honored
            JaxbValidator.validateRequired(o, Llama.class);
        } catch (ValidationException e) {
            assert false : "Should not have thrown validation exception.";
        }
        try {
            Llama o = new Llama(null, null);
            // Again - see if 'required' is honored
            JaxbValidator.validateRequired(o, Llama.class);
            assert false : "Should have thrown validation exception for 'yes'";
        } catch (ValidationException e) {
            assert e.getMessage() != null: "Expected validation message, got null." ;
        }
    }
}

Implementation

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.xml.bind.annotation.XmlElement;
import org.apache.log4j.Logger;

/**
 * oh so minimal consideration of JAXB annotation
 */
public class JaxbValidator {

    private static final Logger LOG = Logger.getLogger(JaxbValidator.class);

    public static class ValidationException extends Exception {
        public ValidationException(String message, Throwable cause) {
            super(message, cause);
        }
        public ValidationException(String message) {
            super(message);
        }
    }

    /**
     * Enforce 'required' attibute.
     *
     * Requires either no security manager is used or the default security manager is employed. 
     * @see {@link Field#setAccessible(boolean)}.
     */
    public static <T> void validateRequired(T target, Class<T> targetClass)
        throws ValidationException {
        StringBuilder errors = new StringBuilder();
        Field[] fields = targetClass.getDeclaredFields();
        for (Field field : fields) {
            XmlElement annotation = field.getAnnotation(XmlElement.class);
            if (annotation != null && annotation.required()) {
try {
    field.setAccessible(true);
    if (field.get(target) == null) {
        if (errors.length() != 0) {
            errors.append(" ");
        }
        String message = String.format("%s: required field '%s' is null.",
       targetClass.getSimpleName(),
       field.getName());
        LOG.error(message);
        errors.append(message);
    }
} catch (IllegalArgumentException e) {
    LOG.error(field.getName(), e);
} catch (IllegalAccessException e) {
    LOG.error(field.getName(), e);
}
            }
        }
        if (errors.length() != 0) {
            throw new ValidationException(errors.toString());
        }
    }

And yes ... it doesn't do deep inspection. I wasn't sure if JAXB handles cyclic graphs, so I didn't attempt recursion without knowing if I needed to detect loops.

glassfishrobot commented 12 years ago

roos said: Its 10/2012 now and still nothing.

glassfishrobot commented 11 years ago

ovy9086 said: now it's 2013... and still no updates on this. I just started with JAXB and in the first day I needed this and... BUMMER. Not available...

glassfishrobot commented 11 years ago

areami said: please have a look at https://github.com/whummer/jaxb-facets; they may have implemented this there

glassfishrobot commented 11 years ago

yaroska said: May be MOXy JAXB implementation can help.

http://www.eclipse.org/eclipselink/moxy.php

glassfishrobot commented 11 years ago

lennartj said: Actually, being able to validate XSDs generated from annotated POJOs in a simple and useable form is still very important for JAXB. It is puzzling that this is not a trivial operation in the year 2013.

My workaround has been the implementation in

<dependency>
    <groupId>se.jguru.nazgul.core.xmlbinding.spi.jaxb</groupId>
    <artifactId>nazgul-core-xmlbinding-spi-jaxb</artifactId>
    <version>1.5.0</version>
</dependency>

It generates schema from annotated POJOs and performs validation during marshalling and unmarshalling.

glassfishrobot commented 9 years ago

olmath said: It's now year 2015. This jira issue is open since 2007. Is there a chance to have this improvement implemented in a near future ? Could you please update this ticket with the current status of consideration ?

glassfishrobot commented 17 years ago

Was assigned to snajper

glassfishrobot commented 7 years ago

This issue was imported from java.net JIRA JAXB-430

miaaaooow commented 6 years ago

Aaand, it in year 2018 we are still looking for a solution here.