Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Thursday, December 22, 2016

Parsing JSON using Jackson Library

Apart from being able to parse a json using the json libraries as shown here, another interesting way to parse a json is using the jackson library. To begin using this method, we add the following entry to our pom -

pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.6.3</version>
</dependency>

And we use the following json file that we read from our resource folder -

sherlock.json

{
 "firstname": "Sherlock",
 "lastname": "Holmes",
 "address": {
  "street": "221B, Baker Street",
  "city": "London"
 },
 "books": ["A Study in Scarlet", "The Sign of the Four", "The Hound of the Baskervilles"]
}

The Jackson library essentially maps json elements to class variables. So, to map the values, a model consisting of one or more classes, having the same structure as the json is needed. For our current json, we need two classes - one for the original json and one for the address.

The two models are as follows -

Address.java


public class Address {
        String street;
        String city;

        //Getters and Setters
}

JsonEntry.java

import java.util.List;
import com.fasterxml.jackson.annotation.JsonProperty;

public class JsonEntry {
        @JsonProperty("firstname")
        String firstName;

        @JsonProperty("lastname")
        String lastName;

        Address address;
        List<String> books;

        //Getters and Setters
}

The JsonProperty annotation is used when the name of the json field varies from the variable name. It is not needed in the case when the name of the field is the same as the name of the variable.

The complete java file which parses and prints the json is given below -

JsonParser.java

package json.parser;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonParser {
 public static void main(String[] args) {
  String json;
  try {
   ClassLoader classLoader = JsonParser.class.getClassLoader();
   InputStream in = classLoader.getResourceAsStream("json/sherlock.json");
   json = convertToString(in);
   ObjectMapper mapper = new ObjectMapper();

   JsonEntry jsonParsed = parseJson(json, mapper);

   System.out.println("-----Printing Json--------------");
   printJson(jsonParsed);

   System.out.println("\n-----Pretty Printing Json--------------");
   prettyPrintJson(jsonParsed, mapper);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 private static String convertToString(InputStream in) throws IOException {
  StringBuilder sb = new StringBuilder();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));

  String line;

  while ((line = br.readLine()) != null) {
   sb.append(line).append("\n");
  }

  return sb.toString();

 }

 private static JsonEntry parseJson(String jsonString, ObjectMapper mapper) {
  JsonEntry jsonEntry = null;

  try {
   // Convert JSON string to Object
   jsonEntry = mapper.readValue(jsonString, JsonEntry.class);
  } catch (JsonGenerationException e) {
   e.printStackTrace();
  } catch (JsonMappingException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }

  return jsonEntry;

 }

 private static void printJson(JsonEntry json) {
  System.out.println("First Name: " + json.getFirstName());
  System.out.println("Last Name: " + json.getLastName());

  System.out.println("Street: " + json.getAddress().getStreet());
  System.out.println("City: " + json.getAddress().getCity());

  for (int i = 0; i < json.getBooks().size(); i++) {
   System.out.println("Book " + (i + 1) + ": " + json.getBooks().get(i));
  }
 }

 private static void prettyPrintJson(JsonEntry json, ObjectMapper mapper) throws JsonProcessingException {
  String prettyPrint = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(json);
  System.out.println(prettyPrint);
 }
}

The method parseJson() maps the json string to the object model definition. printJson() and prettyPrintJson()are simply outputting the values of the mapped json.


See also -
Parsing Json using Json Libraries

Parsing Json using Json Libraries

In this example we try to parse a json file using the json libraries. I have used the json library found here. So, I added the following dependency to my POM.

pom.xml

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20160810</version>
</dependency>

In my workspace, the follwing json file is used and read from the resource directory. The json can also be provided directly as a string or simply read from a file.

sherlock.json

{
 "firstname": "Sherlock",
 "lastname": "Holmes",
 "address": {
  "street": "221B, Baker Street",
  "city": "London"
 },
 "books": ["A Study in Scarlet", "The Sign of the Four", "The Hound of the Baskervilles"]
}


The code uses the class JSONObject and JSONArray to parse through the json and print accordingly. The code for the parser is as follows -


package json.reader;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class JsonReader {
 public static void main(String[] args) {
  String json;
  try {
   ClassLoader classLoader = JsonReader.class.getClassLoader();
   InputStream in = classLoader.getResourceAsStream("json/sherlock.json");
   json = convertToString(in);

   parseJson(json);

  } catch (Exception e) {
   e.printStackTrace();
  }
 }

 private static String convertToString(InputStream in) throws IOException {
  StringBuilder sb = new StringBuilder();
  BufferedReader br = new BufferedReader(new InputStreamReader(in));

  String line;

  while ((line = br.readLine()) != null) {
   sb.append(line).append("\n");
  }

  return sb.toString();

 }

 private static void parseJson(String jsonString) throws JSONException {
  JSONObject obj = new JSONObject(jsonString);

  System.out.println("First Name: " + obj.getString("firstname"));
  System.out.println("Last Name: " + obj.getString("lastname"));

  JSONObject address = obj.getJSONObject("address");
  System.out.println("Street: " + address.getString("street"));
  System.out.println("City: " + address.getString("city"));

  JSONArray books = obj.getJSONArray("books");
  for (int i = 0; i < books.length(); i++) {
   System.out.println("Book " + (i + 1) + ": " + books.get(i));
  }
 }
}

The responsibility of the method convertToString()is to take an InputStream as input and return the json as a string. The json string is then passed to the method parseJson() which reads throught the json one value at a time. The books is an array of string and hence is handled accordingly.

The output of the above program looks as below -

Output

First Name: Sherlock
Last Name: Holmes
Street: 221B, Baker Street
City: London
Book 1: A Study in Scarlet
Book 2: The Sign of the Four
Book 3: The Hound of the Baskervilles


See also -
Parsing JSON using Jackson Library

Monday, June 27, 2016

Parsing XMLs with DOM Parser

DOM parsers are the simpler of the two parsers, the other being SAX parser. Its is programmetically less complicated but is also less efficient compared to sax. The DOM parser loads the whole document into the main memory and then parses the whole document all at once as opposed to parsing on encountering in SAX parser. The obvious drawback to loading the full file in memoory is that the efficiency of parsing reduces with the increase in size of the document. Not to mention, documents that don't fit in the memory cannot be parsed.

To understand DOM parser, we take an example xml file and parse it using DOM. Lets consider the following xml -

testXML.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<first>
    <second atName="one">
        <number id="one">1</number>
        <number id="two">2</number>
    </second>
    
    <second atName="two"> 
        <number id="one">1</number>
        <number id="two">2</number>
    </second>
</first>

Our goal is to parse this whole document and output the same using DOM parser. Before beginning with the example lets look into some helper classes and basic methods -

DocumentBuilder - It defines the API to generate the DOM document tree from an XML. Its usually created by using the DocumentBuilderFactory.newInstance().

Node - It is an interface which represents a node in the DOM tree.

Attr - This is the interface which represents the attributes of a node.

NamedNodeMap - This represents the list of attributes that a node holds.

In our example, the main() method first generates the DOM tree and the processNode() method traverses this tree printing the nodes as it encounters them.

DomParser.java


public class DomParser {

    public static void main(String[] args) {
        try {
            File file = new File("src/testXML.xml");
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(file);
            doc.getDocumentElement().normalize();

            String tab = "";

            System.out.println("Staring Parsing...");

            //Process root Node
            Node root = doc.getDocumentElement();
            System.out.println(root.getNodeName());
            processNode(root, "\t" + tab);

            System.out.println("Parsing Complete...");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void processNode(Node node, String tab) {
        try {
            NodeList children = node.getChildNodes();

            for (int i = 0; i < children.getLength(); i++) {
                Node ele = children.item(i);

                //Printing the node name or the text value in case of a Text node
                if (ele.getNodeName().equals("#text")) {
                    System.out.print(" " + ele.getNodeValue());
                } else {
                    System.out.print(tab + ele.getNodeName());
                }

                //Printing attributes of the current node.
                if (ele.hasAttributes()) {
                    NamedNodeMap attrs = ele.getAttributes();
                    for (int j = 0; j < attrs.getLength(); j++) {
                        Attr attribute = (Attr) attrs.item(j);
                        System.out.print(" " + attribute.getName() + "=" + attribute.getValue());
                    }
                }

                //Process children 
                processNode(ele, "\t" + tab);
            }

        } catch (DOMException e) {
            e.printStackTrace();
        }

    }

}

The text nodes appear with a "#text" in them. This nodes accordingly dealt with. The method processNode()is recursively called as it traverses through the whole tree. The output for the above program is as follows -

Output


Staring Parsing...
first
 
     second atName=one 
          number id=one 1 
          number id=two 2 
     
    
     second atName=two  
          number id=one 1 
          number id=two 2 
     
Parsing Complete...


The DOM parser is not a very efficient parser, but for small documents, it can be very useful.

Sunday, June 12, 2016

Design Patterns - Singleton Pattern

Java Singleton patterns are the simplest type of design patterns. They are part of the Creational Patterns. This type of design pattern is used to ensure that only a single instance of an object is running at all times. The easiest way to do this is simply by making the constructor private and allowing the object to be instantiated only through a public static method.

An example of a simple singleton class is as follows -


public class SingletonClass {

    private static SingletonClass singleton;

    private SingletonClass() {
 //private is used to restrict class instantiantion
    }

    public static SingletonClass getInstance() {
        if (singleton == null) {
            singleton = new SingletonClass();
        }

        return singleton;
    }

    public static void releaseInstance() {
        singleton = null;
    }

}

This class is pretty self explanatory. The access modifier of the constructor could also be changed to protected in order to allow the children classes to instantiate the singleton class. A method releaseInstance() is used only to forget the current instance of the class.

Ensuring Singletonness


There are some ways in which this implementation of the singleton pattern may break. We look into the problems and ways to ensure the singletonness.

Thread Safety


Sometimes multithreading can break the functionality of singleton classes. In the following test example the singletonness of the class is not maintained.


@Test
    public void UniqueTest_multithreading() throws InterruptedException {
        SingletonClass s1;
        SingletonClass s2;

        Runnable run = new Runnable() {
            @Override
            public void run() {
                try {
                    SingletonClass s = SingletonClass.getInstance();
                    System.out.println(s.toString()); //Prints different object instances
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        Thread t1 = new Thread(run, "First");
        t1.start();
        Thread t2 = new Thread(run, "Second");
        t2.start();

        t1.join();
        t2.join();
    }


 public static SingletonClass getInstance() {
        if (singleton == null) {
            additionalFunctionality();
            singleton = new SingletonClass();
        }

        return singleton;
 }

 private static void additionalFunctionality() {
        if (Thread.currentThread().getName().equals("First")) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
        }
  }



The test essentially creates two threads which individualy call the getInstance() method. Lets say that some additional work is performed for the first thread. In this case, the first thread becomes busy after performing the null check, during which the second thread already intializes the singleton class. After the additional work by the first thread is done, it re-intializes the singleton class. This results in both the threads having two seperate instances of the singleton class.

Solution

A solution for this problem is making the instantiation part of the singleton class synchronized. So, just adding a synchronised block to the getInstance() method will solve this problem.


    public static SingletonClass getInstance() {
        synchronized (SingletonClass.class) {
            if (singleton == null) {
                additionalFunctionality();
                singleton = new SingletonClass();
            }
        }

        return singleton;
    }

Serializing and Deserializing


Another scenario that breaks the singletonness of the class is when the a singleton object is serialized and then deserialized twice. So, the following test would fail.


@Test
    public void UniqueTest_serializable() {
        SingletonClass singleton = SingletonClass.getInstance();

        writeSingletonObjectToDisk(singleton);
        SingletonClass s1 = readSingletonObjectFromDisk();
        SingletonClass s2 = readSingletonObjectFromDisk();
        assertEquals(s1, s2); //Fails
    }

Solution

There is however a very easy solution for this. The addition of the readResolve() method to the singleton class solves this problem.


 private Object readResolve() {
        return SingletonClass.getInstance();
 }

What happens here is that the readResolve() method is executed first before beginning the deserialization procedure. When a valid object is found, the deserialization essentially never takes place.

One thing to keep in mind is that for the singleton class to be able to serialize it should implement the interface java.io.Serializable.


Saturday, June 11, 2016

Deleting files in a folder using Java

To delete the files in a folder using java, the following piece of code can be used.

String path = "Path\\to\\target\\folder\\";

File folder = new File(path);
File[] listOfFiles = folder.listFiles();

//Iterate through the files
for (File f : listOfFiles) {
    f.delete();
}

The folder itself can also be deleted by adding the following line after the for loop.

folder.delete();

Tuesday, September 30, 2014

Bi-Directional live Scrolling with Lazy Loading for PrimeFaces Datatable using Javascript

Primefaces Datatables are very versatile, but when it comes to certain features, the PF Team is very stubborn as not to release a feature unless it is needed by many. One such problem that I had was when I worked on the bidirectional scroll  feature for LiveScroll or the On-Demand Data. They already had the forward scroll implemented, but did not release a version for the backward scroll. So, I ended up making my own implementation. Here goes.

For simplicity, I built my table with only two columns. My model is as follows -

Car.java

public class Car {

    private String name;
    private String other;

    public Car(String name, String other) {
        this.name = name;
        this.other = other;
    }

    //Getters and Setters
}

It contains only two fields, name and other,  which are also the columns of my table. My lazy datamodel is as follows.

DataModel.java

public class DataModel extends LazyDataModel<Car> {

    List<Car> listVals;
    private List<Car> datasource;
    private int count = 200;
    private int backCount = 200;
    private String rowString = "";
    private static final long serialVersionUID = 1L;

    public DataModel() {
        datasource = new ArrayList<>();
        this.setRowCount(1000);
    }

    //Getter and Setter for rowString and listVals

    @Override
    public Car getRowData(String rowKey) {
        try {
            for (Car listVal : listVals) {
                if (listVal.getName().equals(rowKey)) {
                    return listVal;
                }
            }

        } catch (ArrayIndexOutOfBoundsException ex) {
            ex.printStackTrace();
        }

        return null;
    }

    @Override
    public Object getRowKey(Car car) {
        return car.getName();
    }

    @Override
    public List<Car> load(int first, 
                          int pageSize, 
                          String sortField, 
                          SortOrder sortOrder, 
                          Map<String, Object> filters) {
        listVals = new ArrayList<>();
        System.out.println("loading");

        int end = (count + 50);
        for (int i = count; i < end && count <= 5000; i++, count++) {
            listVals.add(new Car("lamborghini" + count, "other" + count));
        }

        datasource.addAll(listVals);

        return listVals;
    }

    public void loadPreCar() {
        listVals = new ArrayList<>();
        System.out.println("loading pre");

        int end = backCount;
         rowString="";
         
        for (int i = backCount - 50; i < end && backCount >= 0; i++, backCount--) {
            listVals.add(new Car("lamborghini" + i, "other" + i));
        }

        datasource.addAll(0, listVals);
       
        for (int i = 0; i < listVals.size(); i++) {
            Car car = listVals.get(i);
            rowString = rowString + "<tr class=\"ui-widget-content ui-datatable-even\" role=\"row\" data-ri=\"" + i + "\">"
                    + "<td role=\"gridcell\">" + car.getName() + "</td>"
                    + "<td role=\"gridcell\">" + car.getOther() + "</td>"
                    + "</tr>";
            
            i++;
            car = listVals.get(i);
            rowString = rowString + "<tr class=\"ui-widget-content ui-datatable-odd\" role=\"row\" data-ri=\"" + i + "\">"
                    + "<td role=\"gridcell\">" + car.getName() + "</td>"
                    + "<td role=\"gridcell\">" + car.getOther() + "</td>"
                    + "</tr>";
        }

    }
}


To perform lazy loading, it is important that the model class must extend the LazyDataModel<T> class. The load() method of the class is overridden so that we can compose the list on every callback and return it to the view. Here, it returns the next list when the bottom of the viewport/frame is reached. The loadPreCar()  method is where the customization is occurring. In this method, we generate the previous set of list occurring before the first record. This list is to be displayed when the backward live scrolling is performed.

The following is my bean.

DataBean.java


import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import org.primefaces.model.LazyDataModel;

@Named
@SessionScoped
public class DataBean implements Serializable {

    private static final long serialVersionUID = 1L;
    private String value;

    LazyDataModel<Car>  data = null;

    public DataBean() {
    }

    public LazyDataModel<Car>  getData() {
        return data;
    }

    public void setData(LazyDataModel<Car>  data) {
        this.data = data;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @PostConstruct
    public void init() {
        data = new DataModel();
    }
    
}
This class merely holds the datamodel and provides the getter and the setter for it.

Next comes my form.

testDatatable.xhtml


<h:form id="mainForm">
                <pf:growl id="growl"/>  

                <pf:panel>
                    <pf:dataTable 
                        var="car"
                        scrollable="true"
                        liveScroll="true"
                        scrollHeight="300"
                        scrollRows="50"
                        value="#{dataBean.data}" 
                        id="carTable" 
                        lazy="true" >
                        <pf:column headerText="Name">
                            <h:outputText value="#{car.name}" />
                        </pf:column>

                        <pf:column headerText="Other">
                            <h:outputText value="#{car.other}" />
                        </pf:column>
                    </pf:dataTable>
                </pf:panel>

                <h:inputHidden value="#{dataBean.data.rowString}"  
                               id="rowString"/>

                <pf:remoteCommand name="myRemote" 
                                  actionListener="#{dataBean.data.loadPreCar()}" 
                                  oncomplete="addRows()" update="rowString" />


</h:form>
If you notice, it contains three components - a datatable, a hidden variable and a remote command. The Javascript portion of the code is as follows -


<script type="text/javascript">
/* <![CDATA[ */

var lastScrollTop = 0;
var delay = (function() { //Adding delay
    var timer = 0;
    return function(callback, ms) {
        clearTimeout(timer);
        timer = setTimeout(callback, ms);
    };
})();

$(document).ready(function() {

    $('#mainForm\\:carTable .ui-datatable-scrollable-body').on('scroll', null, function() {
        var scrollLocation = $('#mainForm\\:carTable .ui-datatable-scrollable-body').prop('scrollTop');
        if (scrollLocation < 10) {
            var scrollB = $('#mainForm\\:carTable .ui-datatable-scrollable-body')

            if (scrollB.scrollTop() < lastScrollTop) {
                delay(function() {
                    myRemote();
                }, 300);
            }
            lastScrollTop = scrollB.scrollTop();

        }
    });
});



function addRows() {

    var rows = $('#mainForm\\:carTable .ui-datatable-scrollable-body table tr');

    for (i = 0; i < rows.length; i++) {
        var attrVal = parseInt(rows[i].getAttribute('data-ri')) + 50;
        rows[i].setAttribute('data-ri', attrVal);
    }



    var firstRow = $('#mainForm\\:carTable .ui-datatable-scrollable-body table tr:first');
    var rowHeight = firstRow.height();
    firstRow.before(document.getElementById('mainForm:rowString').value);

    var scrollB = $('#mainForm\\:carTable .ui-datatable-scrollable-body')
    scrollB.scrollTop('' + rowHeight * 50);
    lastScrollTop = rowHeight * 50;
}

/* ]]> */
</script>

It isn't as complex as it seems. Here, the scroll event simply fires the remote command method when the scroll bar is towards the top (for scroll position less than 10). The delay prevents the event from firing for every point in the scrollbar. The lastScrollTop variable keeps track of the direction of the scroll. The event fires only when the scrolling is happening in the upward direction.

The addRows() method adds the returned string from the backend to the beginning of the table. It also increments the data-ri, which is the row index attribute each row, by the number of newly added rows.


The flow -

When the page loads for the first time, the PostConstruct  in the DataBean.java creates an instance of the DataModel.java. As the table is loaded, it fires the load() method of the DataModel and creates the table with the first set of rows. Scrolling down functionality will behave in the expected way as for Primefaces. The Scrolling up functionality is where the magic occurs.

When the upper region of the datatable viewport/frame is reached, the js scroll event is fired which in turn triggers the remoteCommand to fire the method loadPreCar() in the class DataModel.java. This fetches the records and formats them into <tr> tags, thus forming a big string of records. This string is stored in the hidden variable rowString in the dataModel. The onComplete attribute in the remoteCommand tag fires the JS method addRows() after the execution completion of the backing bean. In this method, the generated string is retrieved from the hidden variable and is simply appended to the beginning of the table. A small adjustment to the row indices is done to all the existing rows.

This functionality works very similarly to the live downward scroll feature of primefaces. The add row method is of linear complexity to the size of the table. So, with a very large tables, performance may be affected due to the adjustment in the attributes of the existing  rows. Anyway, Hope this helps!