xstream is not parsing root element - java

I am using 'com.thoughtworks.xstream:xstream:1.4.10' library and trying to parse xml files.
Broker is the root element and there are other tags inside
<broker>
<othertags/>
</broker>
The problem is when I am generating an xml file it is generating properly but it is not able read a file.
#XStreamAlias("broker")
public static class Broker {
While file generation it is able to convert Broker class to but not the other way around. All other classes and list are getting correctly mapped but the root #XStreamAlias is not working while reading.
Any pointers as to why will be very helpful.
The exception I am getting:
com.thoughtworks.xstream.mapper.CannotResolveClassException: broker
One more question: while calling xStream.fromXML(responseString) how does xStream know which class to use? Say I have two classes with same alias

XStream does not process annotations by default.
Add the following before the deserialization of your xml content.
XStream xstream = new XStream();
xstream.processAnnotations(Broker.class);

Related

Camel route logic / Output expectations

Background:
I'm trying to unmarshal an xml file using jaxb and camel. I think I'm having a hard time with it because I don't know exactly what to expect filewise.
For example, I have:
from("file://C:/test.xml").unmarshal(jaxb).to("file://C:/testEnd.java");
With that, I'm expecting to see the result of the unmarshalling in the .java file (i.e. parameters and values from the xml file elements). However, when I run the program, nothing shows up in the .java file, but I don't receive any errors.
The same thing happens with marshalling. When I have a .java file as the from function and a .xml file in the to function, nothing happens.
For example, I have:
from("file://C:/test.java").marshal(jaxb).to("file://C:/testEnd.xml");
From this, I would expect to see values from my annotated java file appear in the xml file.
Question:
Is my expectation in both of these cases correct? Or is there something wrong with that logic?
Please try this:
If in your code you want to save java object in the form of an xml and then again use that xml to retrieve the state of the java object saved earlier, we do marshalling and unmarshalling
1) Marshalling: convert java object to xml based and save it to file
Create a producerTemplate sending java object to the producerendpoint, marshal it against jaxb dataformat and it would be converted to xml using the pojo bean marked with XmlRootElement and referred as contextPath in jaxb tag.
public class ClientEight {
#Produce(uri="direct:invoice")
ProducerTemplate template;
public static void main(String rgs[]) throws InterruptedException{
AbstractApplicationContext ctx= new ClassPathXmlApplicationContext("resources/camel-configTen.xml");
InvoiceXml invoice= new InvoiceXml("fdf3443",3454, 435345.44f, "hfhfddfdg"); //any java object we are passing
ClientEight client = (ClientEight) ctx.getBean("client");
Object xmlObj= client.template.requestBody(invoice);
System.out.println(xmlObj);
}
Above is a client code which u are using to send java object to a producer endpoint and since u are using template.requestBody, u are getting back the object returned.
<camel:camelContext>
<camel:dataFormats>
<!-- path to jaxb annotated class -->
<camel:jaxb id="invoiceJaxb" contextPath="com.java.bean"
prettyPrint="true" />
</camel:dataFormats>
<camel:route>
<camel:from uri="direct:invoice" />
<camel:marshal ref="invoiceJaxb" />
<camel:log message=" ${body}" />
<camel:to uri="file://src/resources?fileName=One.xml"/>
</camel:route>
</camel:camelContext>
This would be your camel config file. Hope this helps
The file component take a directory, and process all files in this directory. it doesn't handle file by default, you have to use options, or the stream component.
see http://camel.apache.org/file2.html
Only directories
Camel supports only endpoints configured with a
starting directory. So the directoryName must be a directory. If you
want to consume a single file only, you can use the fileName option,
e.g. by setting fileName=thefilename. Also, the starting directory
must not contain dynamic expressions with ${ } placeholders. Again use
the fileName option to specify the dynamic part of the filename.

xstream: only parsing child element

I have following xml
<root>
<child-1>
</child-1>
<child-2>
<subchild-21>
</subchild-22>
</child-2>
</root>
My requirement is such that I only want to parse child-2. I am unaware of root and child-1.
Is it possible with xstream because I couldn't find a way to ignore root.
There are several ways to go, depending on your requirements.
If you know the name of the class to parse (child-2 here), you could look for the <child-2> and </child-2> entry in the XML, copy them along with the content in-between to a new temporary XML file (you can create temporary files using createTempFile() from the standard File class). This is the way I would suggest.
If you want to take out the child-2 instance without knowing its name, but you know the names of the surrounding classes, you could mock their classes, that is create classes of the same name, but without their specific content. In your example there is no content (might have been ignored at export time), but it's important to have the same member data in the mock classes for the import to succeed. (unless you use ignoreUnknownElements() as stated by Philipi Willemann)
Of course, if you're the one creating the XML, you should be able to export only the child-2 instance in the first place.
If you know the root name you can create a simple class has an attribute of the class you have mapped to child-2:
#XStreamAlias("root")
class Root {
#XStreamAlias("child-2")
private Child2 child;
//get and set
}
Then when you are processing the XML you can set XStream to ignore unknown elements with xstream.ignoreUnknownElements();

how to detect unexpected element in jaxb

I use JAXB 2.2.7 to get data from my XML files, the problem is I need to check if there are some unexpected element in my XML files but JAXB don't care and work perfectly without any error.
Example :
<classe>
<detail>
<knowElementFromXSD>value</knowElementFromXSD>
<unknowElementFromXSD>OtherValue</unknowElementFromXSD>
</detail>
</classe>
For example I need JAXB to throw an error for the in this XML file because isn't define in my XSD.
If someone have an idea, I can't find any solution on the internet.
There are a couple of different ways to accomplish your use case:
Option #1 - ValidationEventHandler
You can set a ValidationEventHandler on your Unmarshaller to be notified of things like unexpected elements. By default a JAXB (JSR-222) implementation will just ignore unmapped elemeents.
Option #2 - Schema Validation
If you set an instance of javax.xml.validation.Schema on the Unmarshaller then the XML input will be validated as it is unmarshalled.
http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html

Can JAXB store the class name in the XML so that the the deserialize code doesn't need knowledge of the class?

It seems the standard approach for deserializing JAXB XML is to specify the package name when creating the context. Then, JAXB looks up the class based on the root element:
JAXBContext jc = JAXBContext.newInstance("com.foo");
Unmarshaller u = jc.createUnmarshaller();
Object o = u.unmarshal(new StringReader("<?xml version="1.0" encoding="UTF-8" standalone="yes"?><MyJaxb>..."));
I'm looking for a more flexible approach where I don't have to specify the package name and could still deserialize any object. This would be as simple as JAXB storing the package in the XML, but I can't seem to find out how to do this. I can write the code to do it myself but that would be unpleasant. It would like JAXB to do it, if possible. BTW, I am not using schemas, just Annotations and marshal/unmarshal. Any ideas?
Actually you can not deserialize "any" object with pure JAXB. You have to specify either packages (where ObjectFactory.class will be sought) or list of classes like JAXBContext.newInstance(Class1.class, Class2.class, Class3.class); That's how jaxb works, it's a part of agreement.
If your tasks are wider that that, e.g. building java classes from arbitrary xml data structure - it's also possible, but you have to be a bit more concrete - what do you mean under "more flexible approach".
You should be able to add more than one package when you get the instance of the jaxbcontext object. You can add as many packages as you want like below.
JAXBContext jc = JAXBContext.newInstance("com.foo.package1:com.foo.package2" );
however, I am not sure how you are gonna use it if you deserialize it into an Object instance?
Are you not gonna use what you have just deserialized?
Also Unmarshaller is not a thread safe class if your application is a multithreaded one.

How should I use Stax2 Validation API against a W3 Schema

I am using com.ctc.wstx.stax.WstxOutputFactory to generate XML.
I am running wstx-asl-3.2.4
I need to start validating the generated XML against a W3 Schema.
When I create an instance of org.codehaus.stax2.validation.XMLValidationSchemaFactory like this
private final static XMLValidationSchemaFactory xsdFact=
XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA);
I get the error
javax.xml.stream.FactoryConfigurationError: No XMLValidationSchemaFactory implementation class specified or accessible (via system property 'org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c', or service definition under 'META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c')
at org.codehaus.stax2.validation.XMLValidationSchemaFactory.newInstance(XMLValidationSchemaFactory.java:208)
at org.codehaus.stax2.validation.XMLValidationSchemaFactory.newInstance(XMLValidationSchemaFactory.java:98)
I can see that woodstox is bundled with a DTD parser only.
I found this article
which contains the unhelpful instruction
Get an instance of XMLValidationSchemaFactory that knows how to parse schemas of the type you need (RelaxNG == rng for this example).
I have been looking at the Sun Multi-Schema XML Validator which is supposed to contain the bits necessary to bolt on to the XMLSchemaValidation factory.
It looks like I might be able to use com.sun.msv.reader.xmlschema.XMLSchemaReader
to write my own instance of XMLValidationSchemaFactory and get it to work this way.
My question is; do I really have to do this, or is there a pre-existing w3c schema factory that I have failed to find?
Perhaps it would be simpler just to validate the XML after I have generated it.
What are the views on this ?
I've upgraded to Woodstox 4.0.8, W3CSchemaFactory comes bundled and its all good.

Categories