I am using Mule XML module jaxb-object-to-xml-transformer to convert my object to XML. Then this XML is embedded into another XML using templates.
But the issue here is the object to XML transformer is giving an XML output with prolog:
<?xml version="1.0" encoding="UTF-8"?>
I need an XML without this. So that it can be embedded into another template without issues.
<flow name="main.flow">
....
....
<mule-xml:jaxb-object-to-xml-transformer name="obj2xml" jaxbContext-ref="myJaxbContext" returnClass="java.lang.String" />
<custom-transformer ..... >
....
....
</flow>
In plain JAXB there is a way to do this. But in Mule XML module I couldn't find any property to do this. Please advise if there is any property to achieve this behaviour.
The documentation indicates that you can intercept JAXB transforms (see: http://www.mulesoft.org/documentation/display/current/JAXB+Bindings). The following example is taken from that documentation.
#Transformer(sourceTypes = {String.class, InputStream.class})
public Person toPerson(Document doc, JAXBContext context) throws JAXBException
{
return (Person) context.createUnmarshaller().unmarshal(doc);
}
Assuming there is a corresponding thing you can do for marshalling you would be able to set the necessary JAXB property.
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
Related
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)
I have a maven project, and I'm trying to marshal a file using jaxb and camel with the command:
from("file://...").marshal("myDataFormat").to("file://...");
When I run the project, I get the following error:
Cannot find data format in registry with ref: myDataFormat
First, does anyone know what the "registry" is? I've searched Google, but can't find anything. I'm guessing it might be another name for the camel-context file. Second, how can I register a data format using camel? Is there a default data format that I can use?
Sorry if the answer is simple, but I'm relatively new to camel and the online docs that I can find haven't been too helpful.
You should use something like this
DataFormat jaxb = new JaxbDataFormat("com.acme.model");
from("activemq:My.Queue").
unmarshal(jaxb).
to("mqseries:Another.Queue");
In other words, first create dataformat object then try to unmarshal it.
About Camel registry http://camel.apache.org/registry.html
For simple, test task Simple registry will be fine.
Spring or Blueprint is good for more complex tasks. http://camel.apache.org/using-osgi-blueprint-with-camel.html , http://camel.apache.org/spring.html , http://camel.apache.org/data-format.html (see Spring example below page)
Blueprint context example, with some data formats.
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
xsi:schemaLocation=
"http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<camelContext id="camelTest"
xmlns="http://camel.apache.org/schema/blueprint" >
<propertyPlaceholder id="properties" location="blueprint:server.placeholder"/>
<package>camel.test</package>
<dataFormats>
<beanio id="cashWarrantFormat" mapping="beanio/mapping.xml" streamName="CashWarrant" encoding="UTF-8"/>
<beanio id="metaDocFormat" mapping="beanio/mapping.xml" streamName="MetaDoc" encoding="UTF-8"/>
<beanio id="accStatementFormat" mapping="beanio/mapping.xml" streamName="AccStatement" encoding="UTF-8"/>
<beanio id="advanceReport" mapping="beanio/mapping.xml" streamName="AdvanceReport" encoding="UTF-8"/>
</dataFormats>
</camelContext>
<bean id="javaUuidGenerator" class="org.apache.camel.impl.JavaUuidGenerator"/>
</blueprint>
Simple registry example.
public static SimpleRegistry createRegistry() {
SimpleRegistry simpleRegistry = new SimpleRegistry();
simpleRegistry.put("transformerFactory", com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl.class);
simpleRegistry.put("javaUuidGenerator", org.apache.camel.impl.JavaUuidGenerator.class);
return simpleRegistry;
}
public void createCamelContext() {
logger.info("Create Camel context");
simpleRegistry = createRegistry();
defaultCamelContext = new DefaultCamelContext(simpleRegistry);
}
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.