jakartaee / jaxb-api

BSD 3-Clause "New" or "Revised" License
61 stars 42 forks source link

JAXB Validation Without Schema #259

Open Tomas-Kraus opened 17 years ago

Tomas-Kraus 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]

Tomas-Kraus commented 6 years ago
Tomas-Kraus commented 17 years ago

@glassfishrobot Commented Reported by shelleyb

Tomas-Kraus commented 13 years ago

@glassfishrobot Commented 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?

Tomas-Kraus commented 13 years ago

@glassfishrobot Commented 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

Tomas-Kraus commented 13 years ago

@glassfishrobot Commented 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.

Tomas-Kraus commented 12 years ago

@glassfishrobot Commented 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.

Tomas-Kraus commented 12 years ago

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

Tomas-Kraus commented 11 years ago

@glassfishrobot Commented 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...

Tomas-Kraus commented 11 years ago

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

Tomas-Kraus commented 11 years ago

@glassfishrobot Commented yaroska said: May be MOXy JAXB implementation can help.

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

Tomas-Kraus commented 11 years ago

@glassfishrobot Commented 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.

Tomas-Kraus commented 9 years ago

@glassfishrobot Commented 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 ?

Tomas-Kraus commented 17 years ago

@glassfishrobot Commented Was assigned to snajper

Tomas-Kraus commented 7 years ago

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

Tomas-Kraus commented 6 years ago

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

ugteker commented 9 months ago

this topic survived the pandemic. its 2024.