Showing posts with label xml. Show all posts
Showing posts with label xml. Show all posts

Saturday, 14 January 2017

Sending xml(JAXB) and json(Jackson) response with Spring MVC @ResponseBody annotation

Background

In some of our earlier posts we saw examples of how Spring controllers work. 

In those examples we returned a view name from controller method and subsequently corresponding JSP was returned and rendered. In this post we will see how we can send a xml or a json response instead of a JSP.


 Sending xml(JAXB) and json(Jackson) response with Spring MVC @ResponseBody annoatation

Your controller would look like below -

package com.osfg.controllers;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.osfg.model.Employee;

/**
 * 
 * @author athakur
 * Controller to handle employee information
 */
@Controller
public class EmployeeController {

    Logger logger = LoggerFactory.getLogger(EmployeeController.class);

    
    @RequestMapping(value = "/getEmployeeInfoData", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
    @ResponseBody
    public Employee getEmployeeInfo(HttpServletRequest request) {
        logger.debug("Receive GET request for employee data information");
        Employee empForm = new Employee();
        empForm.setName("Aniket Thakur");
        empForm.setAge(25);
        return empForm;
    }

}
 
 Most of annotations and code you would already know from previous examples. New thing here is the produces field which is set to 
  • MediaType.APPLICATION_JSON_VALUE,
  • MediaType.APPLICATION_XML_VALUE
which mean your controller method can give response in json or xml. 
NOTE : Spring framework matches this produces field with  accepts header of incoming request.

and your Employee model object would look like -

package com.osfg.model;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * 
 * @author athakur
 * Model class for Employee
 */
@XmlRootElement(name = "employee")
public class Employee implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    private String name;
    private int age;
     
    @XmlElement
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    @XmlElement
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
     
}


Notice the annotations used. Those are required for XML transformation by JAXB library.

NOTE : Don't forget to add <mvc:annotation-driven/>  tag in your spring configuration file.

Once above code and configurations are in place all you have to do is put JAXB and jackson jars on classpath. I am using ivy so add following dependency on youe ivy xml -

<dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.8.5"/>

NOTE : I am using Java 8. JAXB is inbuilt in java since java 7. So no need to explicitly add it.






You can find the working snippet of above code in my github repo -
https://github.com/aniket91/WebDynamo/blob/master/src/com/osfg/controllers/EmployeeController.java
file of
https://github.com/aniket91/WebDynamo

 Related Links

Friday, 7 October 2016

Formatting or preety printing XML and JSON in Java

Background

XML as we know is a platform independent format that can be used to communicate between different apps. We have seen couple of things on XML like parsing, handling special characters, java library etc (See links in Related Links section below). In this post we will see how we can format or preety print xml in Java.


To the code... preety printing XML

Following code will do the trick -

    private static String beautifyXml(String unformattedXML) {
        Transformer transformer;
        String formattedXmlString = null;
        try {
            transformer = TransformerFactory.newInstance().newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
            //initialize StreamResult with File object to save to file
            StreamResult result = new StreamResult(new StringWriter());
            transformer.transform(new StreamSource(new StringReader(unformattedXML)), result);
            formattedXmlString = result.getWriter().toString();
        } catch (TransformerFactoryConfigurationError | TransformerException e) {
            e.printStackTrace();
        }
        return formattedXmlString;
    }

you can test it by simple calling above method with your unformatted xml as input argument. I have created a small web app and have added the functionality of pretty printing xml there. You can see the relevant code (beautifyXml method)-
You can clone the webapp itself and see how it works for yourself. It all on github -

preety printing JSON

You can do similar stuff for Json too -

    public static String beautifyJson(String unformattedStringForm) {
        JsonParser parser = new JsonParser();
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        
        try {
            String jsonString = unformattedStringForm;
            JsonElement el = parser.parse(jsonString);
            return gson.toJson(el);
        }
        catch(JsonSyntaxException e) {
            e.printStackTrace();
        }
        return null;
    }


Again relevant code can be found in (beautifyJson method) -


Related Links

Tuesday, 10 March 2015

Escaping special characters of XML in Java

Background

In previous post I had shown how to parse XML from String - 
 So lets parse a simple String that contains Google Play App name. Eg - 
  • <AppName>Temple Run</AppName>
Code is as follows -

    public static void main(String args[]) throws SAXException, IOException, ParserConfigurationException {
            String xmlString = "<AppName>Temple Run</AppName>";
            DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = db.parse(new InputSource(new StringReader(xmlString)));
            System.out.println(doc.getFirstChild().getTextContent());
    }

and output is as expected - Temple Run

Now lets change out input xml string/ app name as follows -
  • <AppName>Angels & Demons</AppName>
 Run the code again with above xml String input. You will get following Exception -

[Fatal Error] :1:18: The entity name must immediately follow the '&' in the entity reference.
Exception in thread "main" org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 18; The entity name must immediately follow the '&' in the entity reference.
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at StringXMLParser.main(StringXMLParser.java:20)


Reason being '&' is a special character and you need to escape it in a String before parsing the String as XML. Same goes for HTML as well. Special characters like '&' should be escaped. '&'
 in it's escaped form looks like '&amp;'. So the input should be something like -
  • <AppName>Angels '&amp; Demons</AppName>

Special Characters in XML

Special characters in XML are  - 
  1. & - &amp;
  2. < - &lt;
  3. > - &gt;
  4. " - &quot;
  5. ' - &apos;
So when you are creating an XML from some input that has these special characters then you need to take care of it. Obviously you wont expect your clients to enter the app name as ''Angels &amp; Demons".



Reason for escaping these so called special characters is that these have special meaning in XML and when used in data will led to parsing errors as the one show in the code snippet above. For example & character is used to import other XML entities.

Escaping Input for XML in Java

You can very well write your own piece of code to parse these special characters from the input and replace them with their escaped version. For this tutorial I am going to use Apache commons lang’s StringEscapeUtils class which provide escaping for several  languages like XML, SQL and HTML.

As usual I am using Ivy as my dependency manager and Eclipse as my IDE. To install and configure Apache Ivy refer to the link provided in "Related Links" section at the bottom.

My ivy file looks like following - 

<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
    <info
        organisation="OpenSourceForGeeks"
        module="XMLEscaper"
        status="integration">
    </info>
    
    <dependencies>
        <dependency org="org.apache.commons" name="commons-lang3" rev="3.3.2"/>        
    </dependencies>
    
</ivy-module>

now lets get to the code -

import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.lang3.StringEscapeUtils;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


public class StringXMLParser {
    
    public static void main(String args[]) throws SAXException, IOException, ParserConfigurationException {
           
            String appNameInput = "Angels & Demons";
            System.out.println("App Name Before Escaping : " + appNameInput);
            String escapedInput = StringEscapeUtils.escapeXml(appNameInput);
            System.out.println("App Name After Escaping : " + escapedInput);
            String xmlString = "<AppName>" + escapedInput + "</AppName>";
            DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = db.parse(new InputSource(new StringReader(xmlString)));
            System.out.println(doc.getFirstChild().getTextContent());
    }
}
 

Compile and run above code. You should get the following output - 

App Name Before Escaping : Angels & Demons
App Name After Escaping : Angels &amp; Demons
Angels & Demons

No Exception. I have just shown this demo for '&' special character but you can do the same for all special characters mentioned in  "Special Characters in XML" section above.



Note: Only the characters "<" and "&" are strictly illegal in XML. The greater than character is legal, but it is a good habit to replace it.


Related Links

Monday, 26 January 2015

Resolving "The markup in the document following the root element must be well-formed" Exception

Background

In last post we say how we can efficiently parse an XML file using DocumentBuilder -


But as we had concluded that post saying we cannot parse an XML file with multiple root elements. Hence in this post we will see how we can achieve that.

To The Code....

Let say now our data.xml file looks like the following - 

<data key="name" value="John"></data>
<data key="age" value="23"></data>
<data key="sex" value="male"></data>

That is no root element (or rather 3 root elements). If we run the previous code here we will get following Exception -

[Fatal Error] data.xml:2:2: The markup in the document following the root element must be well-formed.
Exception in thread "main" org.xml.sax.SAXParseException; systemId: file:/C:/Users/athakur/newJavaWorkspace/XMLParserDemo/data.xml; lineNumber: 2; columnNumber: 2; The markup in the document following the root element must be well-formed.
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at XMLParser.main(XMLParser.java:24)


Now lets see how can we tackle this. In this case we will take help of java.io.SequenceInputStream.


import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * @author athakur
 *
 */
public class XMLParser {
    
    public static void main(String args[]) throws IOException, ParserConfigurationException, SAXException
    {
        File file = new File("data.xml");
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Enumeration<InputStream> streams = Collections.enumeration(
                Arrays.asList(new InputStream[] {
                    new ByteArrayInputStream("<ROOT>".getBytes()),
                    new FileInputStream(file),
                    new ByteArrayInputStream("</ROOT>".getBytes()),
                }));

        SequenceInputStream sequenceStream = new SequenceInputStream(streams);
        Document doc = db.parse(sequenceStream);
        NodeList nodes = doc.getElementsByTagName("data");
        for ( int i = 0; i < nodes.getLength(); i++) 
        {
            Element element = (Element) nodes.item(i);
            String key = element.getAttribute("key");
            String value = element.getAttribute("value");    
            System.out.println("Key : " + key + " || Value : " + value);
        }
    }
}
 

and life is good again! Output is -

Key : name || Value : John
Key : age || Value : 23
Key : sex || Value : male 



Related Links

Parsing XML files in Java using javax.xml.parsers.DocumentBuilder

Background

If you want to read xml files and process tag and attributes then there is a smarter way to do it than just reading the file line by line. That is exactly what we are going to see in this post.

To the Code.....

Assume we have the following data.xml file in the root directory of the project with following contents - 

<ROOT>
    <data key="name" value="John"></data>
    <data key="age" value="23"></data>
    <data key="sex" value="male"></data>
</ROOT>


Our goal is to parse this file and print key and value in an efficient manner. We do it the following way - 

import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * 
 * @author athakur
 *
 */
public class XMLParser {
    
    public static void main(String args[]) throws IOException, ParserConfigurationException, SAXException
    {
        File file = new File("data.xml");
        DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = db.parse(file);
        NodeList nodes = doc.getElementsByTagName("data");
        for ( int i = 0; i < nodes.getLength(); i++) 
        {
            Element element = (Element) nodes.item(i);
            String key = element.getAttribute("key");
            String value = element.getAttribute("value");    
            System.out.println("Key : " + key + " || Value : " + value);
        }
    }
}

and the output is as expected - 

Key : name || Value : John
Key : age || Value : 23
Key : sex || Value : male

Easy... wasn't it? Using DocumentBuilder makes parsing xml files easy.

NOTE : The XML file should have only one root element and can have multiple child elements. If this is not satisfied you will get following Exception

org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.

In case of such cases (multiple root elements) how can we parse the XML? I have explained the same in separate post (See Related Links section below)

Parsing XML String

For parsing Simple XML strings you can do - 

import java.io.IOException;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


public class StringXMLParser {
    
    public static void main(String args[]) throws SAXException, IOException, ParserConfigurationException {
        
            String xmlString = "<records><employee><name>Aniket</name><title>Software Developer</title></employee></records>";
            
            DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document doc = db.parse(new InputSource(new StringReader(xmlString)));
            
            NodeList nodes = doc.getElementsByTagName("employee");

            for (int i = 0; i < nodes.getLength(); i++) {
              Element element = (Element) nodes.item(i);

              NodeList name = element.getElementsByTagName("name");
              Element line = (Element) name.item(0);
              System.out.println("Name: " + line.getFirstChild().getNodeValue());

              NodeList title = element.getElementsByTagName("title");
              line = (Element) title.item(0);
              System.out.println("Title: " + line.getFirstChild().getNodeValue());
            }
    }
}

Related Links



t> UA-39527780-1 back to top