Here are my bean classes:
package request;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
#JacksonXmlRootElement
public class Employee {
private List<String> roles= new ArrayList<String>();
private String name;
public Employee(){}
#JacksonXmlProperty
public String getName ()
{
return name;
}
public void setName (String name)
{
this.name = name;
}
#JacksonXmlElementWrapper(useWrapping=false)
#JacksonXmlProperty
public List<String> getRoles ()
{
return roleCodes;
}
public void setRoles (String role)
{
this.roles.add(role);
}
}
and,
package request;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
public class Employees
{
#JacksonXmlElementWrapper(localName="employees")
#JacksonXmlProperty(localName="employee")
private ArrayList<Employee> emps;
//Employee Employee ;
public Employees(){}
#JacksonXmlProperty(localName="employee")
public ArrayList<Employee> getEmployees ()
{
return emps;
}
public void setEmployees(Employee emp){
this.emps.add(emp);
}
#Override
public String toString()
{
if(emps.isEmpty()!=true)
for (Employee e:emps)
return "this is [employee = "+e ;
return "none there";
}
public ArrayList<Employee> addingEmployee(Employee e){
this.emps.add(e);
return emps;
}
}
And here is the code to parse the xml into POJO:
package testPkg4;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import request.Bean;
import request.Employee;
import request.Employees;
public class Test4 {
public static void main(String[] args) {
XmlMapper xmlMapper = new XmlMapper();
//Bean value = new Bean();
Employees emps=new Employees();
try {
emps = xmlMapper.readValue(new File("D:\\workspace\\test\\src\\test\\resources\\employee.xml"),
Employees.class);
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
}
System.out.println(emps.getEmployees().get(0).getFirstName());
//System.out.println(e.getFirstName());
//System.out.println(emps.getEmployees().get(0).getThirdElement());
}
}
Now here is the error I am getting :
com.fasterxml.jackson.databind.JsonMappingException: N/A at [Source:
D:\workspace\test\src\test\resources\employee.xml; line: 5, column:
12] (through reference chain: request.Employees["employee"]) at
com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:277)
at
com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:551)
at
com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:532)
at
com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:108)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276)
at
com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140)
at
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3814)
at
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2756)
at testPkg4.Test4.main(Test4.java:23) Caused by:
java.lang.NullPointerException at
request.Employees.setEmployees(Employees.java:31) at
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at
java.lang.reflect.Method.invoke(Unknown Source) at
com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:106)
... 5 more Exception in thread "main" java.lang.NullPointerException
at testPkg4.Test4.main(Test4.java:29)
while i am parsing thsi xml file:
<employees>
<employee>
<name>ASHISH</name>
<roles>MD</roles>
</employee>
<employee>
<name>BAHADUR</name>
<roles>CO</roles>
<roles>TM</roles>
</employee>
</employees>
Can anyone help me figure out what's the issue!
Found an useful tutorial to create custom untyped xml deserializer which helped me overcome it .
and in case of serialization create java classes from schema using jaxb2-maven-pluging as a build plug in .
org.codehaus.mojo
jaxb2-maven-plugin
1.5
xjc
-extension -npa -b ${project.basedir}/src/main/xsd/global.xjb
** if you are using jackson library then either replace the annotations with the jackson alternatives for jaxb annotaions . or register the jaxbannotation module into your serializer .
Here is the link for the gist that helped me .
Related
I am trying to convert messages from PubSub to a JSON object which I can use later for filtering and inserting into BigQuery. Currently, I am getting an error converting the message to a JSON object.
Input from PubSubMessage:
[
{
"name": "test-name",
"details": {
"email": "test-email",
"location": "test-location"
}
},
{
"name": "test-name2"
}
]
In the above message, the details field can be nullable.
Pipeline code:
import org.apache.beam.sdk.values.PCollection;
import org.apache.beam.sdk.Pipeline;
import org.apache.beam.sdk.coders.AvroCoder;
import org.apache.beam.sdk.coders.DefaultCoder;
import org.apache.beam.sdk.options.PipelineOptionsFactory;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.transforms.ParDo;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubIO;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubOptions;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import javax.annotation.Nullable;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.apache.beam.sdk.io.gcp.pubsub.PubsubMessage;
#DefaultCoder(AvroCoder.class)
class Raw {
public String name;
#Nullable
Details details;
}
class Details {
public String email;
public String location;
}
public class DataFlowPipeline {
public static void main(String[] args) {
PubsubOptions options = PipelineOptionsFactory.fromArgs(args)
.withValidation()
.as(PubsubOptions.class);
options.setPubsubRootUrl("http://localhost:8085");
Pipeline pipeline = Pipeline.create(options);
PCollection<List<Raw>> message = pipeline
.apply("ReadPubSubTopic", PubsubIO.readMessagesWithAttributes().fromTopic("projects/test-dataflow/topics/demo-dataflow"))
.apply("DeserializePubSubMessage", ParDo.of(new DoFn<PubsubMessage, List<Raw>>() {
#ProcessElement
public void processElement(ProcessContext c) {
System.out.println("Inside processor..");
PubsubMessage message = c.element();
String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
TypeFactory typeFactory = mapper.getTypeFactory();
try {
List<Raw> data = mapper.readValue(payload, typeFactory.constructCollectionType(List.class, Raw.class));
System.out.println("Message = " + data);
c.output(data);
} catch (IOException e) {
e.printStackTrace();
}
}}));
;
pipeline.run().waitUntilFinish();;
}
}
Executing the pipeline returns a Null Pointer Exception in Data Reflection. Based on AvroCoder documentation Nullable annotations allows the null fields.
Error:
Caused by: java.lang.NullPointerException: in com.company.dataflow.Raw in com.company.dataflow.Raw in string null of string in field name of com.company.dataflow.Details in field details of com.company.dataflow.Message
at org.apache.avro.reflect.ReflectDatumWriter.write(ReflectDatumWriter.java:161)
at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:62)
at org.apache.beam.sdk.coders.AvroCoder.encode(AvroCoder.java:312)
at org.apache.beam.sdk.coders.IterableLikeCoder.encode(IterableLikeCoder.java:114)
at org.apache.beam.sdk.coders.IterableLikeCoder.encode(IterableLikeCoder.java:60)
at org.apache.beam.sdk.coders.Coder.encode(Coder.java:136)
at org.apache.beam.sdk.util.CoderUtils.encodeToSafeStream(CoderUtils.java:82)
at org.apache.beam.sdk.util.CoderUtils.encodeToByteArray(CoderUtils.java:66)
at org.apache.beam.sdk.util.CoderUtils.encodeToByteArray(CoderUtils.java:51)
at org.apache.beam.sdk.util.CoderUtils.clone(CoderUtils.java:141)
at org.apache.beam.sdk.util.MutationDetectors$CodedValueMutationDetector.<init>(MutationDetectors.java:115)
at org.apache.beam.sdk.util.MutationDetectors.forValueWithCoder(MutationDetectors.java:46)
at org.apache.beam.runners.direct.ImmutabilityCheckingBundleFactory$ImmutabilityEnforcingBundle.add(ImmutabilityCheckingBundleFactory.java:112)
at org.apache.beam.runners.direct.ParDoEvaluator$BundleOutputManager.output(ParDoEvaluator.java:300)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner.outputWindowedValue(SimpleDoFnRunner.java:267)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner.access$900(SimpleDoFnRunner.java:79)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner$DoFnProcessContext.output(SimpleDoFnRunner.java:413)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner$DoFnProcessContext.output(SimpleDoFnRunner.java:401)
at com.company.Dataflow.DataFlowPipeline$1.processElement(Collector.java:100)
Caused by: java.lang.NullPointerException
at org.apache.avro.specific.SpecificDatumWriter.writeString(SpecificDatumWriter.java:67)
at org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:128)
at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:75)
at org.apache.avro.reflect.ReflectDatumWriter.write(ReflectDatumWriter.java:159)
at org.apache.avro.generic.GenericDatumWriter.writeField(GenericDatumWriter.java:166)
at org.apache.avro.specific.SpecificDatumWriter.writeField(SpecificDatumWriter.java:90)
at org.apache.avro.reflect.ReflectDatumWriter.writeField(ReflectDatumWriter.java:191)
at org.apache.avro.generic.GenericDatumWriter.writeRecord(GenericDatumWriter.java:156)
at org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:118)
at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:75)
at org.apache.avro.reflect.ReflectDatumWriter.write(ReflectDatumWriter.java:159)
at org.apache.avro.generic.GenericDatumWriter.writeField(GenericDatumWriter.java:166)
at org.apache.avro.specific.SpecificDatumWriter.writeField(SpecificDatumWriter.java:90)
at org.apache.avro.reflect.ReflectDatumWriter.writeField(ReflectDatumWriter.java:191)
at org.apache.avro.generic.GenericDatumWriter.writeRecord(GenericDatumWriter.java:156)
at org.apache.avro.generic.GenericDatumWriter.writeWithoutConversion(GenericDatumWriter.java:118)
at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:75)
at org.apache.avro.reflect.ReflectDatumWriter.write(ReflectDatumWriter.java:159)
at org.apache.avro.generic.GenericDatumWriter.write(GenericDatumWriter.java:62)
at org.apache.beam.sdk.coders.AvroCoder.encode(AvroCoder.java:312)
at org.apache.beam.sdk.coders.IterableLikeCoder.encode(IterableLikeCoder.java:114)
at org.apache.beam.sdk.coders.IterableLikeCoder.encode(IterableLikeCoder.java:60)
at org.apache.beam.sdk.coders.Coder.encode(Coder.java:136)
at org.apache.beam.sdk.util.CoderUtils.encodeToSafeStream(CoderUtils.java:82)
at org.apache.beam.sdk.util.CoderUtils.encodeToByteArray(CoderUtils.java:66)
at org.apache.beam.sdk.util.CoderUtils.encodeToByteArray(CoderUtils.java:51)
at org.apache.beam.sdk.util.CoderUtils.clone(CoderUtils.java:141)
at org.apache.beam.sdk.util.MutationDetectors$CodedValueMutationDetector.<init>(MutationDetectors.java:115)
at org.apache.beam.sdk.util.MutationDetectors.forValueWithCoder(MutationDetectors.java:46)
at org.apache.beam.runners.direct.ImmutabilityCheckingBundleFactory$ImmutabilityEnforcingBundle.add(ImmutabilityCheckingBundleFactory.java:112)
at org.apache.beam.runners.direct.ParDoEvaluator$BundleOutputManager.output(ParDoEvaluator.java:300)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner.outputWindowedValue(SimpleDoFnRunner.java:267)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner.access$900(SimpleDoFnRunner.java:79)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner$DoFnProcessContext.output(SimpleDoFnRunner.java:413)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner$DoFnProcessContext.output(SimpleDoFnRunner.java:401)
at com.company.dataflow.DataFlowPipeline$1.processElement(Collector.java:100)
at com.company.dataflow.DataFlowPipeline$1$DoFnInvoker.invokeProcessElement(Unknown Source)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner.invokeProcessElement(SimpleDoFnRunner.java:227)
at org.apache.beam.repackaged.direct_java.runners.core.SimpleDoFnRunner.processElement(SimpleDoFnRunner.java:186)
at org.apache.beam.repackaged.direct_java.runners.core.SimplePushbackSideInputDoFnRunner.processElementInReadyWindows(SimplePushbackSideInputDoFnRunner.java:78)
at org.apache.beam.runners.direct.ParDoEvaluator.processElement(ParDoEvaluator.java:240)
at org.apache.beam.runners.direct.DoFnLifecycleManagerRemovingTransformEvaluator.processElement(DoFnLifecycleManagerRemovingTransformEvaluator.java:54)
at org.apache.beam.runners.direct.DirectTransformExecutor.processElements(DirectTransformExecutor.java:160)
at org.apache.beam.runners.direct.DirectTransformExecutor.run(DirectTransformExecutor.java:124)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
I am a .NET Developer learning Java. Please see the code below:
The class HelloWorld
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
#Path("generic")
public class HelloWorld {
#Context
private UriInfo context;
public HelloWorld() {
}
#GET
#Produces("application/xml")
public String getHtml() {
return "<?xml version='1.0'?><PARTS><TITLE>Computer Parts</TITLE><PART><ITEM>Motherboard</ITEM></PART></PARTS>";
}
}
The class JavaApplication3
package javaapplication3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import sun.misc.IOUtils;
/**
*
* #author 3212627
*/
public class JavaApplication3 {
private static String charset;
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws MalformedURLException, IOException, JAXBException {
//Get the URI by selecting the RESTful web services folder under the web app project. Then right click on the underlying node
//and select: TestResourceURI
String content;
String uri ="http://localhost:8080/HelloRestService/webresources/generic";
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
//connection.setRequestProperty("Accept", "application/xml");
connection.setRequestProperty("Accept", "application/xml");
JAXBContext jc = JAXBContext.newInstance(String.class); //I changed Customer.class to String.class
InputStream xml = connection.getInputStream();
String str = (String) jc.createUnmarshaller().unmarshal(xml); //line causing exception
connection.disconnect();
}
}
The exception returned is:
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"PARTS"). Expected elements are (none)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:380)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:619)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3129)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:880)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:606)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:118)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:504)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:848)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:777)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:243)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:214)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204)
at javaapplication3.JavaApplication3.main(JavaApplication3.java:46)
Java Result: 1
BUILD SUCCESSFUL (total time: 5 seconds)
I have marked the line that causes the exception. What is the problem?
The main purpose of JAXB is to do the mapping between XML and a Java Bean but to be able to do it, it relies on annotations from javax.xml.bind.annotation that you need to declare on the fields or on the getters of your target Java Bean.
So for example here, your mapping could be defined as next:
The class Parts
public class Parts {
#XmlElement(name = "TITLE")
private String title;
#XmlElement(name = "PART")
private List<Part> parts;
public String getTitle() {
return this.title;
}
public void setTitle(final String title) {
this.title = title;
}
public List<Part> getParts() {
return this.parts;
}
public void setParts(final List<Part> parts) {
this.parts = parts;
}
}
The class Part
#XmlAccessorType(XmlAccessType.FIELD)
public class Part {
#XmlElement(name = "ITEM")
private String item;
public String getItem() {
return this.item;
}
public void setItem(final String item) {
this.item = item;
}
}
Once you have your mapping defined, you need to provide it to your JAXBContext to be able to unmarshal your XML content to get an instance of the class Parts:
JAXBContext jc = JAXBContext.newInstance(Parts.class);
InputStream xml = connection.getInputStream();
Parts parts = (Parts) jc.createUnmarshaller().unmarshal(xml);
Here is a good tutorial about JAXB that you should read. You should also read the one from oracle.
I know there are similar questions around such as How to marshal/unmarshal a Map<Integer, List<Integer>>? and JAXB java.util.Map binding. Also I read Blaise Doughan's blog a lot especially this post: http://blog.bdoughan.com/2013/03/jaxb-and-javautilmap.html and tried to follow what he suggested as much as I can, however I still cannot unmarshal the json payload successfully and really appreciate your help.
The json payload to unmarshal looks like this:
{
"uri":"\\foo\\dosomthing",
"action":"POST",
"queryParameters":[
"$filter=aaa",
"$orderby=bbb"
],
"requestData":{
"data1":{
"key1":"value1",
"key2":"value2"
},
"ids":[
"1234",
"0294"
]
}
}
And I am having problem to unmarshal the "data" into the java.util.Map. The "data" field does not have specific schema so it can contains an array, key-value pairs or any other valid json data. I decided to use a Map to wrap it. Based on what I researched, I think I need XmlAdapter to convert the data properly.
Here are my code:
The Java Schema Class:
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class CustomerRequest
{
public CustomerRequest() {}
public CustomerRequest(String uri, String action, List<String>
queryParameters, Map<String, Object> reqeustData)
{
this.uri = uri;
this.action = action;
this.queryParameters = queryParameters;
this.requestData = reqeustData;
}
public String getUri()
{
return uri;
}
public String getAction()
{
return action;
}
public List<String> getQueryParameters()
{
return Collections.unmodifiableList(queryParameters);
}
public Map<String, Object> getRequestData()
{
return Collections.unmodifiableMap(requestData);
}
#XmlElement
private String uri;
#XmlElement
private String action;
#XmlElementWrapper
private List<String> queryParameters = new ArrayList<String>();
#XmlPath(".")
#XmlJavaTypeAdapter(StringObjectMapAdapter.class)
private Map<String, Object> requestData = new HashMap<String, Object>();
}
The XmlAdpater:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
public class StringObjectMapAdapter extends
XmlAdapter<StringObjectMapAdapter.AdaptedMap, Map<String, Object>>
{
public static class AdaptedEntry
{
#XmlTransient
public String key;
#XmlValue
public Object value = new Object();
}
public static class AdaptedMap
{
#XmlVariableNode("key")
List<AdaptedEntry> entries = new ArrayList<AdaptedEntry>();
}
#Override
public AdaptedMap marshal(Map<String, Object> map) throws Exception
{
AdaptedMap adaptedMap = new AdaptedMap();
for (Entry<String, Object> entry : map.entrySet())
{
AdaptedEntry adaptedEntry = new AdaptedEntry();
adaptedEntry.key = entry.getKey();
adaptedEntry.value = entry.getValue();
adaptedMap.entries.add(adaptedEntry);
}
return adaptedMap;
}
#Override
public Map<String, Object> unmarshal(AdaptedMap adaptedMap) throws Exception
{
List<AdaptedEntry> adapatedEntries = adaptedMap.entries;
Map<String, Object> map = new HashMap<String, Object>(adapatedEntries.size());
for (AdaptedEntry adaptedEntry : adapatedEntries )
{
map.put(adaptedEntry.key, adaptedEntry.value);
}
return map;
}
}
and finally is my test app:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.testng.annotations.Test;
public class TestStringObjectMapAdapter {
#Test
public void testUnmarshalFromJson() throws Exception
{
JAXBContext jc = JAXBContext.newInstance(CustomerRequest.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
unmarshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
StreamSource json = new StreamSource("test-data.json");
CustomerRequest request= unmarshaller.unmarshal(json,
CustomerRequest.class).getValue();
assert(request.getUri().equals("\\foo\\dosomthing"));
assert(request.getAction().equals("POST"));
}
}
Then when test app runs, an java.lang.ClassCastException exception is generated:
FAILED: testUnmarshalFromJson
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.DocumentImpl cannot be cast to org.w3c.dom.Element
at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.endSelfNodeValue(XMLCompositeObjectMappingNodeValue.java:468)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.endDocument(UnmarshalRecordImpl.java:606)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.endElement(UnmarshalRecordImpl.java:1084)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:304)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parseRoot(JSONReader.java:179)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:125)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:140)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:857)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:707)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:655)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:301)
at com.absolute.asb.urp.services.domain.TestStringObjectMapAdapter.testUnmarshalFromJson(TestStringObjectMapAdapter.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
Maybe you should try creating the correct MoXY JAXBContext like:
private static synchronized JAXBContext createJAXBContext() throws JAXBException {
if(jc == null){
jc = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(new Class[] {CustomerReqeust.class}, null);
}
return jc;
}
Or use another way like mentioned in http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
Btw "CustomerReqeust" is a little bit wrong spelled :-)
I have a service that does the following:
receives different XML requests
turns them into JIBX-generated Java objects
maps the JIBX-generated Java objects into POJOs
sends the POJOs to another service
gets a POJO response back
maps POJO back into JIBX-generated Java objects
turns JIBX-generated Java objects back into XML
returns XML to client.
I'd like to make this process more efficient. Can anyone suggest how? Can JIBX map directly into my POJOs?
Yes Jibx can map directly to your POJOs using Jibx mapping files. I think the below link will be very helpful to understand Jibx binding.
Jibx Introduction
In this you needed library which is available in the url(4shared.com) commented in comments.
package com.xml.Sample.MainP;
import java.io.File;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import com.xml.Sample.Actions.XMLAction;
import com.xml.Sample.Model.States;
public class Retrieve {
public static String XMLModelName = "com.xml.Sample.Model.States";
private static String cities = "E:\\Webeclipseworkspace\\Samples\\src\\Srates.xml";
public static void main(String[] args) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File f = new File(cities);
Document doc = db.parse(f);
doc.getDocumentElement().normalize();
XMLAction xmla = new XMLAction();
List<States> listXML = xmla.readData(XMLModelName, doc);
// System.out.println(listXML);
String xmlData = xmla.writtingData(listXML);
System.out.println(xmlData);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
}
}
}
package com.xml.Sample.Model;
import com.xml.Sample.XMLAnn.XMLColumn;
import com.xml.Sample.XMLAnn.XMLReport;
#XMLReport(reportName = "row")
public class Directory {
private String city_id;
private String city_name;
private String state_id;
#XMLColumn(label = "city_id")
public String getCity_id() {
return city_id;
}
public void setCity_id(String city_id) {
this.city_id = city_id;
}
#XMLColumn(label = "city_name")
public String getCity_name() {
return city_name;
}
public void setCity_name(String city_name) {
this.city_name = city_name;
}
#XMLColumn(label = "state_id")
public String getState_id() {
return state_id;
}
public void setState_id(String state_id) {
this.state_id = state_id;
}
}
Here I Created Own Library For Converting Pojo classes to xml and xml to pojo classes.
Use Below Link(4Shared.com) at Comments to download Library to add for The Above Code.
String(XML in String) to List
1. FolderItem.java
<code>
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
#XmlAccessorType(XmlAccessType.FIELD)
public class FolderItem {
long itemId ;
String itemName;
String itemType;
String description;
String[] tags;
String path;
/* setters and getters
Annotations not required*/
}
</code>
2. FolderItems.java
<code>
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class FolderItems {
#XmlElement
private List<FolderItem> folderItem;
/* setter and getter */
}
</code>
3. Testing--main method
<code>
class Test{
public static void main(String[] args) throws Exception {
FolderItems f = (FolderItems)strToVo(content, FolderItems.class);
System.out.println(f);
}
static Object strToVo(String content, Class c) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(c);
Unmarshaller unmarshaller = jc.createUnmarshaller();
return unmarshaller.unmarshal(new InputSource(new StringReader(content)));
}
}
</code>
4. XML in String
<code>
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<FolderItems>
<folderItem>
<description>Lapse notice invoice for additional interests/additional insureds</description>
<itemId>480004439</itemId>
<itemName>Lapse_Invoice_AI</itemName>
<itemType>application/x-thunderhead-ddv</itemType>
<path>/Templates/Billing Center/Lapse_Invoice_AI</path>
<tags></tags>
</folderItem>
</FolderItems>
</code>
When I am trying to create an object from a data file, I am getting the following exception while assest class is present. I have tried with dum; it was able to dump the data but when I have tried to read same data I am getting the following exception:
[ConstructorException: null; Can't construct a java object for tag:yaml.org,2002:model.Asset; exception=Class not found: model.Asset]
File reader:
package utill;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileInputStream;
import java.io.*;
import java.io.InputStream;
import java.util.*;
import model.*;
import java.util.LinkedHashMap;
import org.yaml.snakeyaml.constructor.Constructor;
public class FileReaderUtill {
public static List getAssest(String fileName){
LinkedHashMap<String,Asset> assest=null;
List<Asset> data= new ArrayList<Asset>();
try{
InputStream input = new FileInputStream(new
File("conf/datafile.yaml"));
Yaml yaml = new Yaml();
data=(List<Asset>)yaml.load(input);
//System.out.println(assest.get("Asset0"));
}catch(IOException e){
e.printStackTrace();
}
return data;
}
}
Datafile.yaml
- !!model.Asset {cid: null, enable: '1', id: re, internalName: df, name: fd}
- !!model.Asset {cid: null, enable: '0', id: rexz, internalName: dxxf, name: fdxxx}
Assest.java
package model;
public class Asset {
public Asset(){
}
public Asset(String id,String cid,String name,String internalName,String enable ){
this.id=id;
this.name=name;
this.internalName=internalName;
this.enable=enable;
}
public String id;
public String cid;
public String name;
public String internalName;
public String enable;
}
Please help me solve this issue.