I'm having some issue while converting String object to JAXBElement string object where I need to set this one
This is the target method where I need to set the value
public void setData(JAXBElement<String> value) {
this.data = ((JAXBElement<String> ) value);
}
For this one, I have written code something like this
ObjectFactory factory = new ObjectFactory();
JAXBElement<ApplicationIngestionRequest> jaxbElement = new JAXBElement(
new QName(ApplicationIngestionRequest.class.getSimpleName()), ApplicationIngestionRequest.class, request);
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(ApplicationIngestionRequest.class);
context.createMarshaller().marshal(jaxbElement, writer);
LOG.info("JAXBElement object :\n"+ writer.toString());
Unmarshaller u = context.createUnmarshaller();
JAXBElement<ApplicationIngestionRequest> o = (JAXBElement<ApplicationIngestionRequest>) u.unmarshal(new StringReader(writer));
Log gives me following output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ApplicationIngestionRequest><BranchCode></BranchCode><SourceCode>0000005511</SourceCode></ApplicationIngestionRequest>
Now when I try to set into the method as
losRequest.setData(o.toString());
It doesn't allow me to set as its expecting as JAXBElement format. Any ideas would be greatly appreciated.
As per the code snippet [setData(JAXBElement value)] , setData , accept instance of '(JAXBElement'). But here , you are trying to set a string value [losRequest.setData(o.toString())] . Here you have to set an instance of 'JAXBElement' .This could be the issue.
Related
I have created several REST Web Services that will return list of records, from my database.
I'm returning all query results in XML format and in my Web service methods I convert it to Java to send it to my client app in JSON (I know, not the best case).
I'm trying to reduce the code in my methods an part of the code that I started with was the XML to Java conversion.
Right now I'm using the following
String xml = xml.replaceFirst("ROWSET xmlns:xsi = " + "\"http://www.w3.org/2001/XMLSchema-instance\"", "invTrxXmlList");
String string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
xml = string.concat(xml);
xml = xml.replaceAll("ROWSET", "invTrxXmlList");
xml = xml.replaceAll("ROW", "invTrxXmlList");
xml = xml.replaceAll(" xsi:nil = \"true\"", "");
InputStream instr = new ByteArrayInputStream(xml.getBytes());
JAXBContext jaxbContext = JAXBContext.newInstance(InvTrxXmlList.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
InvTrxXmlList invTrxXml = (InvTrxXmlList) jaxbUnmarshaller.unmarshal(instr);
inventoryTrx = new InventoryTrx(invTrxXml);
What I want is to create a separate method that could be called by all methods to this job, if possible to work with several distinct Custom Objects, like InvTrxXmlList.
I have, in another task worked a little with Reflection and i was thinking of using it to solve this issue.
Can you help me?
Is there another approach?
Thanks
Thanks silfrede,
I was able to put it to work with the following code
public Object xmlToJava(Object pCurrentObject, String pXml, String pRowset, String pRow) {
InputStream instr = null;
JAXBContext jaxbContext = null;
Unmarshaller jaxbUnmarshaller = null;
String xmlHeader = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
String xmlReturn = null;
Class objectClass = pCurrentObject.getClass();
try {
xmlReturn =
pXml.replaceFirst("ROWSET xmlns:xsi = " +
"\"http://www.w3.org/2001/XMLSchema-instance\"",
pRowset); //"invTrxLines");
xmlReturn = xmlHeader.concat(xmlReturn);
xmlReturn = xmlReturn.replaceAll("ROWSET", pRowset); //"invTrxLines");
if (null != pRow && !pRow.isEmpty()) {
xmlReturn = xmlReturn.replaceAll("ROW", pRow); //invTrxLine);
} else { //Remove Row tags in case of single object
xmlReturn = xmlReturn.replaceAll("<ROW>", "");
xmlReturn = xmlReturn.replaceAll("</ROW>", "");
}
xmlReturn = xmlReturn.replaceAll(" xsi:nil = \"true\"", "");
instr = new ByteArrayInputStream(xmlReturn.getBytes());
jaxbContext = JAXBContext.newInstance(objectClass); //InvTrxHead.class);
jaxbUnmarshaller = jaxbContext.createUnmarshaller();
pCurrentObject = jaxbUnmarshaller.unmarshal(instr);
} catch (Exception e) {
// TODO: Add catch code
e.printStackTrace();
}
return pCurrentObject;
}
with the following call
invTrxHead = (InvTrxHead) WSUtils.xmlToJava(invTrxHead, invTrxHeadXml, "invTrxHead", null);
Now I can sen my XML from my DB and an instance of my object and don't have to duplicate any of the code.
Below is an xml File that i have to parse..
<dataroot>
<PARM>
<P1>123</P1>
<P2>abc</P2>
</PARM>
<PARM>
<P1>456</P1>
<P2>def</P2>
</PARM>
<PARM>
<P1>789</P1>
<P2>ghi</P2>
</PARM>
.......(15times)
</dataroot>
my goal is to get the child nodes (ie p1,p2 not the values inside) and compare those names with a template.
say if p2 is not present i have to append that particular tag to that particular position in the xml file. The problem is when i use getElementsByTagNames() and store that in an array and then compare it with the template it includes dataroot and PARM as well which i don't want.
so how can i get just p1 and p2 (for upto 15times) only.
For me, the simplest approach would be to use JAXB to unmarshal and marshal, thus adding the missing elements of PARM. You need to add a few annotations in the classes for dataroot and PARM if the XML element names require different case, but then it's a matter of a few lines of code for unmarshalling and marshalling.
#XmlRootElement(name="dataroot")
#XmlType(propOrder = {"parm"})
public class Data {
#XmlElement(name="PARM")
private List<Parm> parm = new ArrayList<>();
public List<Parm> getParm(){ return parm; }
}
#XmlRootElement(name="PARM")
public class Parm {
private String p1="";
#XmlElement(name="P1")
public String getP1(){ return p1; }
public void setP1( String v ){ p1 = v; }
}
In the same package, add a file jaxb.index containing a single line:
Data
The main program:
JAXBContext jc = JAXBContext.newInstance( PACKAGE ); // dir path
Unmarshaller u = jc.createUnmarshaller();
Data data = (Data)u.unmarshal( new File( XMLIN ) ); // file path
Marshaller m = jc.createMarshaller();
Writer sw = ...; // whatever you need
m.marshal( data, sw );
Note the initialisation for field p1. This ensures that the element will show up with an empty string. A null results in omitting the element.
I have the following code,
JAXBContext jc = JAXBContext.newInstance(TestResults.class);
Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
OutputStream os = new FileOutputStream( "nosferatu.xml" );
TestResults tr = new TestResults();
tr.setUuid(new JAXBElement<String>(new QName("uuid"),String.class, "uuidcontent"));
//ObjectFactory objectFactory = new ObjectFactory();
m.marshal(new JAXBElement<TestResults>(new QName("uri","local"),TestResults.class,new TestResults()), System.out);
in which I am trying to wrap the Java String Class as a jaxb element, since if I do not I get
the
unable to marshal type “java.lang.String” error.
However when I try wrap the java.lang.string in a jaxb element, I get the following error
The method setUuid(String) in the type TestResults is not applicable for the arguments (JAXBElement<String>)
The setUuid method looks as follows
public void setUuid(java.lang.String value) {
this.uuid = value;
}
How can I then wrap my String as a jaxb element where this error will not be thrown?
When marshalled as the root object an instance of String needs to be wrapped in a JAXBElement to provide the root element information (same as for any class without an #XmlRootElement annotation.
When marshalled as a field or property value the containing element is normally derived from the containing field/property so a JAXBElement by default is not required.
I am getting an 832edi file with namespaces as xml string, i need to extract elements from this xml string. So i have generated jaxb classes based on 832edi file. When i am trying to store the contents of the xml string i am getting the following exception
javax.xml.bind.JAXBElement cannot be cast to org.bam.jaxb.Transaction834
I am using the following code to parse the xml string
JAXBContext jaxbContext = JAXBContext.newInstance("org.bam.jaxb");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(im.getPayload());
Transaction834 edi = (Transaction834) unmarshaller.unmarshal(reader);
List<Loop2000> loop2000=edi.getLoop2000();
System.out.println(loop2000.get(10));
where im.getPayload() will return an xml string . Here is the fragment of the xml.
<?xml version = '1.0' encoding = 'UTF-8'?><Transaction-834 xmlns:zcha="http://www.edifecs.com/xdata/200" XDataVersion="2.0" Standard="X12" Version="V5010" GUID="{C7846049-8C91-4E59-B0BA-4B24CEE69FBB}" CreatedBy="XEngine_4016" CreatedDate="2013-09-05T12:36:12" xmlns="http://www.edifecs.com/xdata/200"><zcha:Segment-ISA><zcha:Element-I01 Offset="4" Size="2">00</zcha:Element-I01><zcha:Element-I02 Offset="7" Size="10">Authorizat</zcha:Element-I02><zcha:Element-I03 Offset="18" Size="2">00</zcha:Element-I03><zcha:Element-I04 Offset="21" Size="10">Security I</zcha:Element-I04><zcha:Element-I05 Offset="32" Size="2">01</zcha:Element-I05><zcha:Element-I06 Offset="35" Size="15">Interchange Sen</zcha:Element-I06><zcha:Element-I05_1 Offset="51" Size="2">01</zcha:Element-I05_1><zcha:Element-I07 Offset="54" Size="15">Interchange Rec</zcha:Element-I07><zcha:Element-I08 Offset="70" Size="6">130905</zcha:Element-I08><zcha:Element-I09 Offset="77" Size="4">1236</zcha:Element-I09><zcha:Element-I65 Offset="82" Size="1">*</zcha:Element-I65><zcha:Element-I11 Offset="84" Size="5">00501</zcha:Element-I11><zcha:Element-I12 Offset="90" Size="9">000000001</zcha:Element-I12><zcha:Element-I13 Offset="100" Size="1">0</zcha:Element-I13><zcha:Element-I14 Offset="102" Size="1">I</zcha:Element-I14><zcha:Element-I15 Offset="104" Size="1">\</zcha:Element-I15></zcha:Segment-ISA><zcha:Segment-GS><zcha:Element-479 Offset="110" Size="2">BE</zcha:Element-479><zcha:Element-142 Offset="113" Size="15">Application Sen</zcha:Element-142><zcha:Element-124 Offset="129" Size="15">Application Rec</zcha:Element-124><zcha:Element-373 Offset="145" Size="8">20130905</zcha:Element-373><zcha:Element-337 Offset="154" Size="6">123602</zcha:Element-337><zcha:Element-28 Offset="161" Size="1">1</zcha:Element-28><zcha:Element-455 Offset="163" Size="1">T</zcha:Element-455><zcha:Element-480 Offset="165" Size="6">005010</zcha:Element-480></zcha:Segment-GS><zcha:Segment-ST><zcha:Element-143 Offset="176" Size="3">834</zcha:Element-143><zcha:Element-329 Offset="180" Size="4">0001</zcha:Element-329></zcha:Segment-ST><zcha:Segment-BGN><zcha:Element-353 Offset="190" Size="2">00</zcha:Element-353><zcha:Element-127 Offset="193" Size="24">Reference Identification</zcha:Element-127><zcha:Element-373 Offset="218" Size="8">20130905</zcha:Element-373></zcha:Segment-BGN><zcha:Loop-1000><zcha:Segment-N1><zcha:Element-98 Offset="231" Size="2">00</zcha:Element-98><zcha:Element-93 Offset="234" Size="4">Name</zcha:Element-93></zcha:Segment-N1><zcha:Segment-N4/></zcha:Loop-1000><zcha:Segment-SE><zcha:Element-96 Offset="243" Size="1">4</zcha:Element-96><zcha:Element-329 Offset="245" Size="4">0001</zcha:Element-329></zcha:Segment-SE><zcha:Segment-GE><zcha:Element-97 Offset="254" Size="1">1</zcha:Element-97><zcha:Element-28 Offset="256" Size="1">1</zcha:Element-28></zcha:Segment-GE><zcha:Segment-IEA><zcha:Element-I16 Offset="263" Size="1">1</zcha:Element-I16><zcha:Element-I12 Offset="265" Size="9">000000001</zcha:Element-I12></zcha:Segment-IEA></Transaction-834>
Here Transaction834 is the root element of the xsd.Please could you suggest me where am i doing the mistake ?
thanks for your patience.
Most likely the class Transaction834 doesn't specify the XmlRootElement annotation (probably because it's a top-level type rather than an anonymous type).
In this case you have to use something like:
JAXBElement<Transaction834> ediElement = unmarshaller.unmarshal(new StreamSource(reader), Transaction834.class);
Transaction834 edi = ediElement.getValue();
When you aren't sure whether the result returned from JAXB will be you can use JAXBInstropector to do any unwrapping of the JAXBElement if necessary.
JAXBContext jaxbContext = JAXBContext.newInstance("org.bam.jaxb");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(im.getPayload());
Transaction834 edi = (Transaction834) JAXBIntrospector.getValue(unmarshaller.unmarshal(reader));
For More Information
http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
I have a method like this.
public void myMethod(String xml){
...
File file=convertStringToFile(xml) // I need to convert xml string to File
object.fileDemandingMethod(file);
}
fileDemandingMethod(file) is expecting File but my input is string.
How can I get my xml string in the form of File object?
I need this for this JAXB Validation
Schema schema = schemaFactory.newSchema(new File("C:\\schema.xsd"));
unmarshaller.setSchema(schema );
Since you can also work with a StreamSource, you can construct a javax.xml.transform.Source from the String with:
new StreamSource(new StringReader(xml))
You don't need a file, you surely don't want the overhead of writing to a file.
setSchema() can take any object implementing javax.xml.transform.Source
StreamSource is one such class, and that can be constructed from an InputStream or Reader.
Reader reader = new StringReader(myString);
Source source = new StreamSource(reader);
unmarshaller.setSchema(spource);
The best way to do that is to create/generate a class in e.g. Employee
from your Schema (C:\Schema.xsd)
After that the rest is easy
JAXBContext context = JAXBContext.newInstance(Employee.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Employee object = new Employee();
object.setCode("CA");
object.setName("Cath");
object.setSalary(300);
m.marshal(object, new FileOutputStream("result.xml"));
}