converting xml to java objects with xstream in java - java

I have an xml ans i want to make it objects , i am using xsteam for this and I have added xstream jars in my classpath..
below is my xml...
<Eurexflows xmlns:eur="http://www.eurexchange.com/EurexIRSFullInventoryReport" xmlns:fpml="http://www.fpml.org/FpML-5/confirmation">
<EurexMessageObject>
<CCPTradeId>109599</CCPTradeId>
<novDateTime>2012-02-15 10:59:00.0</novDateTime>
</EurexMessageObject>
<EurexMessageObject>
<CCPTradeId>122270</CCPTradeId>
<novDateTime>2012-06-29 18:59:00.0</novDateTime>
</EurexMessageObject>
</Eurexflows>
below is my pojo...
public class EurexMessageObject {
private Long CCPTradeId;
private String migratedDate;
public Long getCCPTradeId() {
return CCPTradeId;
}
public void setCCPTradeId(Long cCPTradeId) {
CCPTradeId = cCPTradeId;
}
public String getMigratedDate() {
return migratedDate;
}
public void setMigratedDate(String migratedDate) {
this.migratedDate = migratedDate;
}
}
and in my main class I have coded this way..
String xmlInputtra="C:\\Rahul\\InputXml\\Xmloutput.xml";
try
{
// get XStream instance and set required aliases
XStream xstream = new XStream();
xstream.alias("EurexMessageObject", com.rbos.gdspc.eurex.EurexMessageObject.class);
// prepare cash flow message from xslt output
EurexMessageObject eurexflowMsg = (EurexMessageObject) xstream.fromXML(xmlInputtra);
System.out.println(eurexflowMsg.toString());
}catch(Exception e)
{
e.printStackTrace();
}
now upon debuging I am getting the following exception..please advise how can I overcome from this
com.thoughtworks.xstream.io.StreamException: : only whitespace content allowed before start tag and not C (position: START_DOCUMENT seen C... #1:1)

Well,the thing that is overlooked here is how you are reading in the XML file.you are using the method fromXML which is expecting the actual XML input and not the file name. So when it parses your xml (which is "Xmloutput.xml" not the actual xml)
I suggest you to use a FileReader/BufferedReader in order to get the contents of the XML back. Something like this should work:
XStream instream = new XStream();
BufferedReader br = new BufferedReader(new FileReader("Xmloutput.xml"));
StringBuffer buff = new StringBuffer();
String line;
while((line = br.readLine()) != null){
buff.append(line);
}
EurexMessageObject eurexflowMsg = (EurexMessageObject)instream.fromXML(buff.toString());
I hope it will help you, best regards.

Here path for XML file:
String xmlInputtra="C:\\Rahul\\InputXml\\Xmloutput.xml";
is treated as XML contents,
so you need to pass as String for that you can read file and pass to constructor.

Related

Jackson CsvMapper fails to correctly deserialize to POJO despite schema configuration

For some reason despite configuring a FasterXML Jackson CSV mapper to create a POJO-based schema, it insists that no suitable configuration has been provided. I get the following exception:
com.fasterxml.jackson.databind.JsonMappingException: No value type configured for ObjectReader
com.fasterxml.jackson.databind.ObjectReader._findRootDeserializer(ObjectReader.java:1371)
com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1265)
com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:897)
aol.model.core.services.admin.CSVParserService.parseCSVFileStreamAsClass(CSVParserService.java:42)
aol.rest.controller.AdminController.importCsvData(AdminController.java:30)
aol.rest.controller.AdminController$$FastClassBySpringCGLIB$$b9304c43.invoke(<generated>)
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
...
My POJO is very simple
#JsonPropertyOrder({"firstName", "lastName", "age"})
public class Person {
String firstName;
String lastName;
Integer age;
public Person() {} //no other use than to avoid no-suitable-construction found issue
//getters and setters omitted for brevity
}
My parsing code is
public MappingIterator<Person> parseCSVFileStreamAsClass(MultipartFile file) throws IOException {
StringBuilder lines = new StringBuilder();
String lineSeparator = System.getProperty("line.separator");
try(BufferedReader reader = new BufferedReader(new InputStreamReader(file.getInputStream()))) {
for (String r = reader.readLine(); r != null; r = reader.readLine()) {
lines.append(r).append(lineSeparator);
}
}
CsvMapper mapper = new CsvMapper();
CsvSchema schema = mapper
.schemaFor(Person.class)
.withHeader()
.withLineSeparator(lineSeparator);
MappingIterator<Person> out = mapper.reader(schema).readValue(lines.toString());
return out;
}
The reason I handled the MultipartFile this way isntead of reading the stream directly is eliminate issues of mismatching line separator between file and mapper (I work on Windows [don't down-vote me :(], and the mapper's default line separator is only \n.
The data file is this
firstName,lastName,age
"Paul","Smith","22"
"Jane","Crass","98"
I tried adding and removing the quotation marks (default String separators). I tried without the age number quotes, then added them out of desperation. No joy!
I looked at the documentation other SO questions as well as blog posts. No luck.
Okay, so my colleague figured it out.
MappingIterator<Person> out = mapper.reader(schema).readValue(lines.toString());
needs to be changed to
MappingIterator<Person> out = mapper.reader(Person.class).with(schema).readValue(lines.toString());
The rest is fine
One correction to the above answer. It should be calling readValues() instead of readValue() method
MappingIterator<Person> out = mapper.reader(Person.class).with(schema).readValues(lines.toString());

JaxB marshaler overwriting file contents

I am trying to use JaxB to marshall objects I create to an XML. What I want is to create a list then print it to the file, then create a new list and print it to the same file but everytime I do it over writes the first. I want the final XML file to look like I only had 1 big list of objects. I would do this but there are so many that I quickly max my heap size.
So, my main creates a bunch of threads each of which iterate through a list of objects it receives and calls create_Log on each object. Once it is finished it calls printToFile which is where it marshalls the list to the file.
public class LogThread implements Runnable {
//private Thread myThread;
private Log_Message message = null;
private LinkedList<Log_Message> lmList = null;
LogServer Log = null;
private String Username = null;
public LogThread(LinkedList<Log_Message> lmList){
this.lmList = lmList;
}
public void run(){
//System.out.println("thread running");
LogServer Log = new LogServer();
//create iterator for list
final ListIterator<Log_Message> listIterator = lmList.listIterator();
while(listIterator.hasNext()){
message = listIterator.next();
CountTrans.addTransNumber(message.TransactionNumber);
Username = message.input[2];
Log.create_Log(message.input, message.TransactionNumber, message.Message, message.CMD);
}
Log.printToFile();
init_LogServer.threadCount--;
init_LogServer.doneList();
init_LogServer.doneUser();
System.out.println("Thread "+ Thread.currentThread().getId() +" Completed user: "+ Username+"... Number of Users Complete: " + init_LogServer.getUsersComplete());
//Thread.interrupt();
}
}
The above calls the below function create_Log to build a new object I generated from the XSD I was given (SystemEventType,QuoteServerType...etc). These objects are all added to an ArrayList using the function below and attached to the Root object. Once the LogThread loop is finished it calls the printToFile which takes the list from the Root object and marshalls it to the file... overwriting what was already there. How can I add it to the same file without over writing and without creating one master list in the heap?
public class LogServer {
public log Root = null;
public static String fileName = "LogFile.xml";
public static File XMLfile = new File(fileName);
public LogServer(){
this.Root = new log();
}
//output LogFile.xml
public synchronized void printToFile(){
System.out.println("Printing XML");
//write to xml file
try {
init_LogServer.marshaller.marshal(Root,XMLfile);
} catch (JAXBException e) {
e.printStackTrace();
}
System.out.println("Done Printing XML");
}
private BigDecimal ConvertStringtoBD(String input){
DecimalFormatSymbols symbols = new DecimalFormatSymbols();
symbols.setGroupingSeparator(',');
symbols.setDecimalSeparator('.');
String pattern = "#,##0.0#";
DecimalFormat decimalFormat = new DecimalFormat(pattern, symbols);
decimalFormat.setParseBigDecimal(true);
// parse the string
BigDecimal bigDecimal = new BigDecimal("0");
try {
bigDecimal = (BigDecimal) decimalFormat.parse(input);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bigDecimal;
}
public QuoteServerType Log_Quote(String[] input, int TransactionNumber){
BigDecimal quote = ConvertStringtoBD(input[4]);
BigInteger TransNumber = BigInteger.valueOf(TransactionNumber);
BigInteger ServerTimeStamp = new BigInteger(input[6]);
Date date = new Date();
long timestamp = date.getTime();
ObjectFactory factory = new ObjectFactory();
QuoteServerType quoteCall = factory.createQuoteServerType();
quoteCall.setTimestamp(timestamp);
quoteCall.setServer(input[8]);
quoteCall.setTransactionNum(TransNumber);
quoteCall.setPrice(quote);
quoteCall.setStockSymbol(input[3]);
quoteCall.setUsername(input[2]);
quoteCall.setQuoteServerTime(ServerTimeStamp);
quoteCall.setCryptokey(input[7]);
return quoteCall;
}
public SystemEventType Log_SystemEvent(String[] input, int TransactionNumber, CommandType CMD){
BigInteger TransNumber = BigInteger.valueOf(TransactionNumber);
Date date = new Date();
long timestamp = date.getTime();
ObjectFactory factory = new ObjectFactory();
SystemEventType SysEvent = factory.createSystemEventType();
SysEvent.setTimestamp(timestamp);
SysEvent.setServer(input[8]);
SysEvent.setTransactionNum(TransNumber);
SysEvent.setCommand(CMD);
SysEvent.setFilename(fileName);
return SysEvent;
}
public void create_Log(String[] input, int TransactionNumber, String Message, CommandType Command){
switch(Command.toString()){
case "QUOTE": //Quote_Log
QuoteServerType quote_QuoteType = Log_Quote(input,TransactionNumber);
Root.getUserCommandOrQuoteServerOrAccountTransaction().add(quote_QuoteType);
break;
case "QUOTE_CACHED":
SystemEventType Quote_Cached_SysType = Log_SystemEvent(input, TransactionNumber, CommandType.QUOTE);
Root.getUserCommandOrQuoteServerOrAccountTransaction().add(Quote_Cached_SysType);
break;
}
}
EDIT: The below is code how the objects are added to the ArrayList
public List<Object> getUserCommandOrQuoteServerOrAccountTransaction() {
if (userCommandOrQuoteServerOrAccountTransaction == null) {
userCommandOrQuoteServerOrAccountTransaction = new ArrayList<Object>();
}
return this.userCommandOrQuoteServerOrAccountTransaction;
}
Jaxb is about mapping java object tree to xml document or vice versa. So in principle, you need complete object model before you can save it to xml.
Of course it would not be possible, for very large data, for example DB dump, so jaxb allows marshalling object tree in fragments, letting the user control moment of the object creation and marshaling. Typical use case would be fetching records from DB one by one and marshaling them one by one to a file, so there would not be problem with the heap.
However, you are asking about appending one object tree to another (one fresh in memory, second one already represented in a xml file). Which is not normally possible as it is not really appending but crating new object tree that contains content of the both (there is only one document root element, not two).
So what you could do,
is to create new xml representation with manually initiated root
element,
copy the existing xml content to the new xml either using XMLStreamWriter/XMLStreamReader read/write operations or unmarshaling
the log objects and marshaling them one by one.
marshal your log objects into the same xml stram
complete the xml with the root closing element. -
Vaguely, something like that:
XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(new FileOutputStream(...), StandardCharsets.UTF_8.name());
//"mannually" output the beginign of the xml document == its declaration and the root element
writer.writeStartDocument();
writer.writeStartElement("YOUR_ROOT_ELM");
Marshaller mar = ...
mar.setProperty(Marshaller.JAXB_FRAGMENT, true); //instructs jaxb to output only objects not the whole xml document
PartialUnmarshaler existing = ...; //allows reading one by one xml content from existin file,
while (existing.hasNext()) {
YourObject obj = existing.next();
mar.marshal(obj, writer);
writer.flush();
}
List<YourObject> toAppend = ...
for (YourObject toAppend) {
mar.marshal(obj,writer);
writer.flush();
}
//finishing the document, closing the root element
writer.writeEndElement();
writer.writeEndDocument();
Reading the objects one by one from large xml file, and complete implementation of PartialUnmarshaler is described in this answer:
https://stackoverflow.com/a/9260039/4483840
That is the 'elegant' solution.
Less elegant is to have your threads write their logs list to individual files and the append them yourself. You only need to read and copy the header of the first file, then copy all its content apart from the last closing tag, copy the content of the other files ignoring the document openkng and closing tag, output the closing tag.
If your marshaller is set to marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
each opening/closing tag will be in different line, so the ugly hack is to
copy all the lines from 3rd to one before last, then output the closing tag.
It is ugly hack, cause it is sensitive to your output format (if you for examle change your container root element). But faster to implement than full Jaxb solution.

Reading XML with JDOMXpath

I have the follwing XML file -
<?xml version="1.0" encoding="UTF-8"?>
<BatchOrders xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<BatchHeader>
<ServiceProvider>123456789</ServiceProvider>
</BatchHeader>
<OrderDetails>
<MessageType>HelloWorld</MessageType>
<IssueDateTime>22/01/2012 00:00:00</IssueDateTime>
<receivedDateTime>22/01/2012 00:00:00</receivedDateTime>
<Status>TestStatus</Status>
</OrderDetails>
</BatchOrders>
I want to read in the contents and set them to fields I have created. So I have the following code below (not some is omitted - I have just included what I think I need to show. The below is in a test class which I have created - I also have a writer as part of this class that writes an XML File fine to disk as I expect. The problem I am facing is reading the file above and displaying the contents read to the Console just for now.
File myFileRead = null;
FileReader myFileReader = null;
try {
myFileRead = new File("C:/Path/myfile.xml");
myRecord = new myRecord();
myFileReader = new FileReader(myFileRead);
myXPathReader reader = new myXPathReader(myFileReader);
while (reader.hasNext())
{
record = reader.next();
//prints out then to cosole
}
So from above I have the myRecord class where I have the getters/setters for e.g ServiceProvider, etc. I also then have a class for myXpathReader which does the following:
private Document document;
private List batchorders;
private Iterator iterator;
public myXPathReader (Reader myFileReader)
throws Exception
{
SAXBuilder builder = new SAXBuilder();
document = builder.build(myFileReader);
batchorders = new JDOMXPath("//BatchOrders").selectNodes(document);
iterator = batchorders.iterator();
}
public int getSize() { return batchorders.size(); }
public boolean hasNext() { return iterator.hasNext(); }
public myRecord next()
throws Exception {
Element element = (Element) iterator.next();
myRecord record = new myRecord();
record.setServiceProvider((new JDOMXPath("./ServiceProvider").stringValueOf(element)));
//Some more sets ans close class etc...
Now if I debug the code and after the element on iterator.next I can see the file contents have being read in correctly. But on my console the ServiceProvider value and in fact all the values are getting set to empty string "". Am I doing something incorrect on the JDOMXPath in order to pull the value from the XML?
In your example XML ServiceProvider is not a child of BatchOrders, there's another level (BatchHeader) in between. So your second XPath expression should probably be
BatchHeader/ServiceProvider
instead of ./ServiceProvider

json to xml java

I want convert json to xml
here is code
public class ConvertJSONtoXML {
public static void main(String[] args) throws Exception {
InputStream is = ConvertJSONtoXML.class.getResourceAsStream("demo1.txt");
String jsonData = IOUtils.toString(is);
XMLSerializer serializer = new XMLSerializer();
JSON json = JSONSerializer.toJSON(jsonData);
String xml = serializer.write((JSON) json);
System.out.println(xml);
Here is demo1.txt
{"name":"naveed" }
It reads demo1.txt file and convert into xml but i m trying to pass json as string.
String jsonString="{\"name\":\"naveed\" }";
InputStream is = ConvertJSONtoXML.class.getResourceAsStream(jsonString);
but it wont work for string..
i thing getResourceAsStream(jsonString) doesnt work for string....
please suggest any reference
The method getResourceAsStream() actually looks on the file system for resource identified by the input string and open an input stream for it.
You should rather use something like
InputStream is = new ByteArrayInputStream( jsonString.getBytes() );
Also, you should take care of using compatible charsets.

confirmation email - create templae and combine it with an object

I need to implement email confirmation in my java web application. I am stuck with the email I have to send to the user.
I need to combine a template (of an confirmation email) with the User object and this will be the html content of the confirmation email.
I thought about using xslt as the template engine but I don't have xml form of the User object and don't really know how to create a xml from User instance.
I thought about jsp, but how do I render jsp page with an object and get the html as a result?
Any idea what packages I can use in order to create templae and combine it with an object?
I have used the following before. I seem to recall it wasn't complicated
http://velocity.apache.org/
How complex is the user object? If it's just five string-valued fields (say) you could simply supply these as string parameters to the transformation, avoiding the need to build XML from your Java data.
Alternatively, Java XSLT processors typically provide some way to invoke methods on Java objects from within the XSLT code. So you could supply the Java object as a parameter to the stylesheet and invoke its methods using extension functions. The details are processor-specific.
Instead of learning a new code, debug other's complicate code I decided to write my own small and suitable util:
public class StringTemplate {
private String filePath;
private String charsetName;
private Collection<AbstractMap.SimpleEntry<String, String>> args;
public StringTemplate(String filePath, String charsetName,
Collection<AbstractMap.SimpleEntry<String, String>> args) {
this.filePath = filePath;
this.charsetName=charsetName;
this.args = args;
}
public String generate() throws FileNotFoundException, IOException {
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(
getClass().getResourceAsStream(filePath),charsetName));
try {
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append(System.getProperty("line.separator"));
}
} finally {
reader.close();
}
for (AbstractMap.SimpleEntry<String, String> arg : this.args) {
int index = builder.indexOf(arg.getKey());
while (index != -1) {
builder.replace(index, index + arg.getKey().length(), arg.getValue());
index += arg.getValue().length();
index = builder.indexOf(arg.getKey(), index);
}
}
return builder.toString();
}
}

Categories

Resources