In Jaxb 1.0 the xml validation is turned on by calling 'setValidating' on unmarshaller object:
JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setValidating(true);
In Jaxb 2.0 the validation is enhanced and setting up a schema is required:
Schema schema = schemaFactory.newSchema(file);
unmarshaller.setSchema(schema);
Looks like to use JAXB 2.0 validation the schema xsd file is a neccessary, requisite resource that must be provided in the application context.
While in JAXB 1.0 to turn on validation the schema file is not required (at least explicitly)
Question 1:
Does JAXB 1.0 really stores validation capabilities in its implementation (which comes from xjc) and xsd file is not required in the app/package/classpath runtime context?
Question 2:
In JAXB 2.0 is it possible to 'unsetSchema' for the unmarshaller - just give up validation (for performance purposes ... when I see that incoming xml payload is the same like the one I already validated earlier)?
Answer to question #2:
To turn off unmarshaller validation it is enough to reset schema to null:
unmarshaller.setSchema(null);
Question #1 remains open:
Does JAXB 2.0 need a schema file to be provided at runtime to perform validation during marshalling/unmarshalling ? ... or maybe we can force xjc complier with some options (like -nv) to generate implementation that has validation capabilities like JAXB 1.0 used to have. (just not to disclose xsd schema)
Related
I get a JAXB marshalling error (cycle infinite loop) - posted at end of this question.
I know it's due to a 2 way object reference and I have used EclipseLink MOXy JAXB marshaller in a test case to resolve this specifying ID and IDREF and specified the JAXB provider using a jaxb.properties file containing
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
However the production code uses Spring OXM and I cannot see how to achieve a similar result using this.
I have added a jaxb.properties file but it isn't being used - I know this because I add an empty file as a test and it doesn't complain (like it did on the prototype test case).
How do I specify the JAXB marshaller to use?
It appears to be using:
org.eclipse.persistence.oxm.XMLMarshaller
whereas my working test case uses :
org.eclipse.persistence.jaxb.JAXBMarshaller
Exception:
javax.xml.bind.MarshalException
- with linked exception:
[Exception [EclipseLink-25037] (Eclipse Persistence Services -
2.6.1.v20150916-55dc7c3):
org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A cycle is detected in the object graph. This will
cause an infinite loop:
at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal
(JAXBMarshaller.java:487)
OK - to resolve this I specified (in the Spring OXM file)
<xml-inverse-reference mapped-by="myObject"
<xml-element xml-idref="true"
I only added the xml-idref="true" relationship
I generate some beans from a couple of xsd via ant-build.
When unmarshalling an xml, I would like to validate that one. As far as I know, there is now way to do this with the beans themself, one has to do something like this:
JAXBContext context = JAXBContext.newInstance(Bean.class);
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(new File("whatever.xsd"));
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);
unmarshaller.setEventHandler(validationHandler);
return (Bean) unmarshaller.unmarshal(givenXmlString);
My problem is that new File("whatever.xsd"). I don't want to hardcode an URL to the xsd, that might change later (i.e. by refactoring the project) and will break at runtime, because one forgot (or didn't know) to change that url.
Idea:
The only idea I have for that is to copy the xsd to the same folder as the generated beans and to use the packagename of one bean to generate the url at runtime.
Any better ideas?
Instead of sf.newSchema(File) you can use sf.newSchema(Source[]) with one of the javax.xml.transform.Source implementations, e.g. javax.xml.transform.stream.StreamSource.
I saw many solutions using XMLInputFactory, SAXParser and DocumentBuilderFactory. Our project is spring web service and the only thing we do is:
#Bean
public Jaxb2Marshaller unmarshaller() {
Jaxb2Marshaller unmarshaller = new Jaxb2Marshaller();
unmarshaller.setContextPath("foo");
unmarshaller.setProcessExternalEntities(false);
return unmarshaller;
}
And then we pass this marshaller and unmarshaller to MarshallingPayloadMethodProcessor. So my question is if there is some property for Jaxb2Marshaller that will prevent DTD. Something like: unmarshaller.setProperty(foo.SUPPORT_DTD, false);
We have .xsd schema but in case of xml bomb the entity needs to be exanded for purpose of validation, so it seems like this is not the solution.
As far as I can see from the code, this must be the default behaviour.
In the JAXB RI there is a context property com.sun.xml.bind.disableXmlSecurity which is reasonably set to false by default. JAXB RI the uses this property when it creates the parser. So, at the end it configures the FEATURE_SECURE_PROCESSING feature of the parser:
SAXParserFactory factory = SAXParserFactory.newInstance();
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "SAXParserFactory instance: {0}", factory);
}
factory.setNamespaceAware(true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, !isXMLSecurityDisabled(disableSecureProcessing));
return factory;
You can also use the system property javax.xml.accessExternalDTD.
See also this answer:
How to disable DTD fetching using JAXB2.0
If you want to make it ever more secure, you may write and configure your own entity resolver.
I have a legacy web service project that receives two different XML schemas, but with the same attribute name (including the root element). I'm using Spring, OXM and JAXB2 for marshalling/unmarshalling.
I've solved a previous issue with another question, so I use SAX parser to determine which unmarshaller to use. When a XML is parsed, I check a value and then I can use an unmarshaller or other unmarshaller.
My problem comes when I try to define marshallers/unmarhsallers with Spring OXM. If I set the classpath with two packages, it fails beacause unmarshaller finds two classes with the same XMLRootElement. If I set a list of class-to-be-bound it fails too beacause unmarshaller always unmarshall to the last item in the class list (same XMLRootElement, unmarshaller doesn't know which class to unmarshall).
But It works correctly If I use JaxbContext:
JAXBContext jc = JAXBContext.newInstance(MyClass1.class);
myClass1Object = (MyClass1) jc.createUnmarshaller().unmarshal(new StreamSource(new StringReader(xml)));
And
JAXBContext jc = JAXBContext.newInstance(MyClass2.class);
myClass2Object = (MyClass2) jc.createUnmarshaller().unmarshal(new StreamSource(new StringReader(xml)));
How can I transform this to a more Spring (OXM) approach?
First of all I tried to declare the JAXBContext instance in the application context file, but finally I went for changing the namespace of one XML schema. Now I'm using Spring OXM to marshall/unmarshall my two XML schemas without any problem.
I am trying to set features for Xerces XML validation. I am having a hard time finding / understanding which features are valid for the SchemaFactory and for the Validator.
I have the following code:
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_US_URI);
factory.setFeature("http://xml.org/sax/features/validation", true);
Schema schema = factory.newSchema(mySchemaList);
Validator validator = schema.newValidator;
validator.setFeature("http://xml.org/sax/features/validation", true);
If I do the above I get:
SAXNotRecognizedException: Feature 'http://xml.org/sax/features/validation
However if I comment out the setFeature for the SchemaFactory, setting the feature works for the Validator.
So questions:
Why can I set the feature on the Validator but not on the SchemaFactory?
Where can I find documentation of which features are valid for Validator and SchemaFactory?
FYI: the SchemaFactory I am getting is com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory
EDIT
Some of the other features I have tried to set with no success are:
http://xml.org/sax/features/namespaces
http://xml.org/sax/features/namespace-prefixes
From the JavaDoc of setFeature
Set a feature for this SchemaFactory, Schemas created by this factory,
and by extension, Validators and ValidatorHandlers created by those
Schemas.
Implementors and developers should pay particular attention to how the
special Schema object returned by newSchema() is processed. In some
cases, for example, when the SchemaFactory and the class actually
loading the schema come from different implementations, it may not be
possible for SchemaFactory features to be inherited automatically.
Developers should make sure that features, such as secure processing,
are explicitly set in both places.
As you can see, some of the features might not be inherited due to some limitations. Having said that, the Xerces 2.7.x version seems to have a bug around this which was fixed from the 2.8.x onwards.