I am using JAXB 2.0 for the Application Deveopment which is using RestFul Webservices .
Now there is a modification in the request , that is i will be getting another filed/variable in the request XML .
<Root Id="567" att="758" />
Modified Request will be
<Root Id="567" att="758" anotherfiledadded ="kiran" />
My question is , is it possible to automatically append that field (anotherfiledadded)in the UserData class (Without modifying the UserData ??)
The below is my UserData class
#XmlRootElement(name = "Root")
#XmlAccessorType(XmlAccessType.FIELD)
public class UserData {
#XmlAttribute
private String Id;
#XmlAttribute
private String att;
// getters and setters
You can try adding the field at runtime with javassist. But... It looks like you would also require to add the Annotation #XmlAttribute and I don't know if javassist allows you to add annotations... Anyways give it a try.
See: Javassist Add
You could use XSLT to apply an attribute into your XML document. All of the classes below are available in the JDK/JRE since Java SE 6.
JAXBContext jc = JAXBContext.newInstance(UserData.class);
JAXBSource source = new JAXBSource(jc, myUserData);
StreamResult result = new StreamResult(System.out);
TransformerFactory tf = TransformerFactory.newInstance();
StreamSource xslt = new StreamSource("addMyAttribute.xslt");
Transformer t = tf.newTransformer(xslt);
t.transform(source, result);
If you are implementing your RESTful service using JAX-RS you could plug-in this logic via a MessageBodyWriter:
Related
I have to use a lib that only gives me a JAXBContext to marshall and unmarshall XML data to Java objects. Also I don't ever see XML: Only the JAXB objects are passed to me. What I now need is a conversion of those objects not to XML, but to JSON.
Is there a way to create a marshaller from the given JAXBContext that can be used to generate JSON output?
The situation is that I'm not only transforming data. I also have logic that acts on the Java objects between XML and JSON (and manipulates the data). Also it's a two-way transformation. The JAXBContext is the information I have about the transformation between XML and Java objects - My intention was to reuse this context information for not having to implement a second transformation with a second technology different to JAXB. The JAXBContext (and its Java objects) already have the information about the XML structure; The automated recognition of that structure by JAXB is the time-saving reason for using it.
If your JAXB classes just use the basic annotations, you can take a look at JacksonJAXBAnnotations, allows Jackson mapper to recognize JAXN annotations. Four lines of code (in the simplest marshalling case) would be all you would need.
ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module);
mapper.writeValue(System.out, yourJaxbObject);
You can see the link above for all the supported annotations. The maven artifact you'll need is
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.4.0</version>
</dependency>
See the github for jackson-module-jaxb-annotations - Note this artifact has dependencies on jackson-core and jackson-databind. So if you're not using maven, then you will need to make sure to download these artifacts also
Simple Exmaple:
JAXB Class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"hello",
"world"
})
#XmlRootElement(name = "root")
public class Root {
#XmlElement(required = true)
protected String hello;
#XmlElement(required = true)
protected String world;
// Getters and Setters
}
XML
<?xml version="1.0" encoding="UTF-8"?>
<root>
<hello>JAXB</hello>
<world>Jackson</world>
</root>
Test
public class TestJaxbJackson {
public static void main(String[] args) throws Exception {
JAXBContext context = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
InputStream is = TestJaxbJackson.class.getResourceAsStream("test.xml");
Root root = (Root)unmarshaller.unmarshal(is);
System.out.println(root.getHello() + " " + root.getWorld());
ObjectMapper mapper = new ObjectMapper();
JaxbAnnotationModule module = new JaxbAnnotationModule();
mapper.registerModule(module);
mapper.writeValue(System.out, root);
}
}
Result
{"hello":"JAXB","world":"Jackson"}
Update
Also see this post. It looks like MOXy also offers this support.
I need help to find the approach of how to create xml multiple times while I will be changing only two fields everytime and rest of the fields would be same as now. Please tell me the way to do it in java?
This is the sample xml below:
I would be changing the value of <Id> and <Originator>
<TransactionBlk>
<Id>NIK</Id>
<CorrelationId />
<Originator>NIK</Originator>
<Service>GetIns</Service>
<VersionNbr>1</VersionNbr>
<VersionNbrMin>0</VersionNbrMin>
<MsgNm>Req</MsgNm>
<MsgFormatCd>XML</MsgFormatCd>
</TransactionBlk>
You can crate one class contain all this parameter as class variable, create getter and setter method. Create object of class set value by using setter method.
You can use JAXB API's class to convert your java object into XML format.
The JAXBContext class provides the client's entry point to the JAXB API.
It provides an abstraction for managing the XML/Java binding information
necessary to implement the JAXB binding framework operations: unmarshal,
marshal and validate.
Here is Doc reference for convert your Java object into XML.
Here are tutorial for same Tutorial Link
Sample Code :
#XmlRootElement(name="TransactionBlk_REQ",namespace="http://TransactionBlk.com")
#XmlAccessorType(XmlAccessType.FIELD)
public class TransactionBlk
{
#XmlElement(name = "Id")
private String id;
#XmlElement(name = "Originator")
private String Originator;
//Your getter and setter method.
}
TransactionBlk bean = new TransactionBlk();
//Set your parameter value here
StringWriter responseWriter = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(TransactionBlk.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.marshal(bean, responseWriter);
String xmlStr = responseWriter!=null?responseWriter.toString():null;
You can use XSLT to transform XML.
If all you're doing is printing a "boilerplate" document with changes in those two values, a, you could use the DPH (Desperate Perl Hacker) approach: simply assemble it as text, pausing to print the values at the appropriate places. To be safe, you should pre-scan the values to make sure they don't contain the <, >, or & characters and escape those if you find them.
For something more complex, or if you want to start learning how to do it "properly", look at the standard XML APIs for Java: DOM (the Document Object Model, an in-memory tree model of a document), SAX (an event-stream view of a document), and JAXP (tools to take an XML document and parse it into DOM or SAX so you can read it, and to take DOM or SAX and write those out as XML syntax). JAXP also provides standard APIs for invoking XPath to search a document and XSLT to apply a stylesheet to a document, so taken together these cover a huge percentage of the basic operations on XML.
You might want to look at some tutorials on using Java to manipulate XML. I'm certainly biased, not least because they published one of my articles, but in my experience IBM's DeveloperWorks website (https://www.ibm.com/developerworks/xml/) has had better-than-average material for learning about XML and other standards.
I unmarshall an XML that comes in a specific format e.g.
<root>
<a/>
<b/>
<c>
<x/>
</c>
<d/>
</root>
After playing around with the Java object, I want to send it to another service that uses a different schema, e.g.
<anotherRoot>
<a/>
<x/>
<something>
<d/>
</something>
</anotherRoot>
Can this be done "easily" w/ JAXB?
Using any JAXB (JSR-222) implementation you could use XSLT on a JAXBSource and the javax.xml.transform APIs to produce a secondary XML structure:
JAXBContext jc = JAXBContext.newInstance(Foo.class);
// Output XML conforming to first XML Schema
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(foo, System.out);
// Create Transformer on Style Sheet that converts XML to
// conform the second XML Schema
TransformerFactory tf = TransformerFactory.newInstance();
StreamSource xslt = new StreamSource(
"src/example/stylesheet.xsl");
Transformer transformer = tf.newTransformer(xslt);
// Source
JAXBSource source = new JAXBSource(jc, foo);
// Result
StreamResult result = new StreamResult(System.out);
// Transform
transformer.transform(source, result);
Full Example
http://blog.bdoughan.com/2012/11/using-jaxb-with-xslt-to-produce-html.html
You can create create a proxy for the other service and regard its beans as simple data transfer objects.
So when you wish to call the service, you manually fill the beans based on the values of your proper model objects (the one you play around with, the ones that contain business logic) and call the service using the beans.
If changes happen to the service's interface, you can recreate the proxy and the compiler will help you fix the transformation.
Let's suppose I store an XML string into a variable
String resp = new String("<?xml version=\"1.0\" encodin...");
and the schema definition related to this XML in another one:
String xsd = new String("<xs:schema xmlns="http://schema-...");
do you think there is a way to validate and unmarshall 'resp'
into objects (using JAXB for example) ?? Has anybody already
tried or successfully implemented such stuff ??
In advance, thanks a lot for any suggestion...
Seb
You can use unmarshal(Source source) and setSchema(Schema schema) of the Unmarshaller class. This should work:
unmarshaller.setSchema(SchemaFactory.newSchema(new StreamSource(new StringReader(xsd));
unmarshaller.unmarshal(new StreamSource(new StringReader(resp));
Greetings! I have a server returning XML content to my client that looks like this:
<string xmlns="...">foobar</string>
I'm new to JAXB and have gotten a lot of stuff working, except this. I thought it would be pretty easy to marshal and unmarshal this to and from a String. It took a while, but I finally figured out how to marshal this as
public static String ToXML(String s) throws Exception
{
JAXBContext context = JAXBContext.newInstance(String.class);
Marshaller marshaller = context.createMarshaller();
StringWriter sw = new StringWriter();
marshaller.marshal(new JAXBElement(new QName("", "String"), String.class, s), sw);
return sw.toString();
}
So my question is, how to I unmarshal this? It cannot be annotated as a root element. I cannot use java.lang as the package to create a new instance of a JAXBContext (I get an ObjectFactory missing exception).
Any wisdom to impart? This can't be that hard, right?
You need to write an object model that conforms to your XML structure, and tell JAXB to unmarshal on to that. Your example may look simple, but it's not what JAXB is for.
Try something like this:
#XmlRootElement(name="string", namespace="blah")
public class MyString {
#XmlValue
String value;
}
JAXBContext context = JAXBContext.newInstance(MyString.class);
MyString myString = (MyString) context.createUnmarshaller().unmarshal(...);
This will unmarshal the XML <string xmlns="blah">foobar</string>. Change the namespace accordingly. If you have many namespaces, then JAXB isn't really the tool for you.
I was surprised by this, but the following seems to work:
final String xmlString = "<string>value</string>";
final StringReader xmlReader = new StringReader(xmlString);
final StreamSource xmlSource = new StreamSource(xmlReader);
final JAXBContext jaxbContext = JAXBContext.newInstance(String.class);
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final String stringValue = unmarshaller.unmarshal(xmlSource, String.class).getValue();
Is that what you were looking for?
When you're using JAXB, you need to build the code around an XML schema. That is, if you have a file, say foo.xsd, you need to run it through the xjc compiler (in JDK 6 by default, otherwise you can download JAXB 2 and use that). That will read through the schema and generate the Java bean and associated ObjectFactory classes with the elements in the schema. The Java bean classes will look like regular POJOs with annotations. The ObjectFactory classes are needed by the JAXB implementation to convert the XML into the corresponding Java bean. This explains your ObjectFactory missing exception.
So it's not hard, but there is some leg work involved. We use it for one of our production applications and it's great. I see myself using it more now that it's part of the JDK.