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> 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>> 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>> 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
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>