Tuesday, May 17, 2016

JAVA and XML - The Ultimate Magic

I've a lot of issues but I've decided to play with XML file i.e. create XML, parse XML etc.

JAVA provides several options for handling XML structures and files. One of the most common and used ones is JAXB.

JAXB = JAVA Architecture for XML Binding.

It offers the possibility to convert JAVA objects into XML and the vice versa i.e. convert XML into JAVA objects!!!!

It provides annotations to map java fields to a XML structure i.e. node, attribute, node order, root, hierarchy, nesting etc.

Few of mostly used annotations:

  • @XmlRootElement as root element.
  • @XmlElement in combination with setter methods i.e. the node name.
  • @XmlAttribute to pass attributes to the XML nodes. These attributes can have properties like to be required or not.
  • @XmlType to indicate special options like to order of appearance in the XML.
Now I'm going to technical hands on.

1. Covert a Java Object into a XML file called Marshaling.

2. Convert / Load XML file into a JAVA object Un-Marshal.

3. Handling complex data type which is not directly available in JAXB. 



1. Marshaling


At 1st i'll create a class Country having a JAXB annotation indicating the root,  few variables/fields and getter setter methods. No any complex things just a normal class which you can create in your 1st day of java learning.


import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name="country")
public class Country {
    
    private String name,capital;
    
    private int population;

   
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCapital() {
        return capital;
    }

    public void setCapital(String capital) {
        this.capital = capital;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }
     
}



Now  i'll create a sample XML file for our Country class. For this purpose, i'll create a test main program using JAXBContext and its marshaling functionalities which will use Country class..

The most important part is JAXBContext class. This provides framework for validate, marshal, un-marshal XML file into java object and vice versa.



public class XMLMagic {

   
    public static void main(String[] args)  {

        // intialize country class

        Country bd = new Country();
        
       bd.setName("Bangladesh");

        bd.setCapital("Dhaka");

        bd.setPopulation(160000000);

        try {
            /* init jaxb marshaler */
            JAXBContext context =    JAXBContext.newInstance(Country.class);

        Marshaller marshaler = context.createMarshaller();
            
            /* set this flag to true to format the output */
            marshaler.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            
            /* marshaling of java objects in xml (output to file and standard output) */
            marshaler.marshal(bd, new File("country.xml"));       
     
             // For JAVA Version 6, include following instead of previous line

            /*marshal.marshal(bd, new FileWriter("country.xml")); */           



            /*The following is for console output. You can remove following line*/
            marshaler.marshal(bd, System.out); 

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

The output is country.xml.



If any change, required in XML I only change in country class. No change in main class.

Now i want to change the node ordering in XML file. i.e. population, name, capital.


So i just add the following line (XML) in top of the Country class.

@XmlType(propOrder={"population", "name", "capital"})


You've to specify all property in @XmlType.propOrder otherwise IllegalAnnotationsException will be raised.



Run the main program declared in previous section. The output is as follows:



Now i'll change Node name using XmlElement annotation.

@XmlElement (name="####")




After Run the main program, country.xml should be as follows:




Now I'll add an Attribute. So I do following:

- Add a class variable: importance

- getter/setter methods for that variable

- Use annotation: XmlAttribute

- No propOrder is required for Attribute.


The code is as follows:


private int population, importance;


public int getImportance() {
        return importance;
    }

@XmlAttribute(name="imp", required=true)
public void setImportance(int importance) {
        this.importance = importance;
    }


@XmlAttribute annotation specifies the attribute of parent node. required=true means  the

 attribute must be present in parent node even if the value is not set.


Run main program. The country.xml:



Now i want to iterate a node containing String. For example, I'll iterate cities in country.

Add highlighted code in Country.java



And modified main class is as follows:



The country.xml is as follows:


Now I'll use wrapper node around the city collections. So I use @XmlElementWrapper annotation to wrap city nodes. Just add the highlighted line.


After run main program, country.xml is as follows.


Now i'll show how to nesting nodes from collection of nested classes.


- Create 2 more classes : Place.java & Location.java

- In Country class there is List of Place class

- In Place class, there is a List of Location class

- I use @XmlSeeAlso annotation when we want another class included in the XML output

The Country.java is as follows:


package com.xml.node;

import java.util.ArrayList;

import java.util.List;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlList;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;

/**

 *
 * @author Dell
 */

@XmlType(propOrder={"population", "name", "capital", "cities", "places"})

@XmlRootElement(name="country")
@XmlSeeAlso({Place.class})
public class Country {
    
    private String name,capital;
    
    private int population, importance;
    
    private List<String> cities;
    
    private List<Place> places;

    public Country() {

        cities = new ArrayList<String>();
        places = new ArrayList<Place>();
    }

    public List<Place> getPlaces() {

        return places;
    }

    @XmlElement(name="place")

    public void setPlaces(List<Place> places) {
        this.places = places;
    }

    

    public List<String> getCities() {
        return cities;
    }

    @XmlElementWrapper(name="cities")

    @XmlElement(name="city")
    public void setCities(List<String> cities) {
        this.cities = cities;
    }

    public String getName() {

        return name;
    }

    @XmlElement(name="countryName")

    public void setName(String name) {
        this.name = name;
    }

    public String getCapital() {

        return capital;
    }

    @XmlElement(name="countryCapital")

    public void setCapital(String capital) {
        this.capital = capital;
    }

    public int getPopulation() {

        return population;
    }

    @XmlElement(name="countryPopulation")

    public void setPopulation(int population) {
        this.population = population;
    }

    public int getImportance() {

        return importance;
    }

    @XmlAttribute(name="imp", required=true)

    public void setImportance(int importance) {
        this.importance = importance;
    }
    
}


The Place.java is as follows:


package com.xml.node;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;



/**
 *
 * @author Dell
 */

@XmlType(propOrder={"name", "address", "lattitude", "locations"})
public class Place {
    private String name;
    private String address;
    private double lattitude;
    
    private List <Location> locations;

    

    public Place() {
        locations = new ArrayList<Location>();
    }

    public List<Location> getLocations() {
        return locations;
    }

    public void setLocations(List<Location> locations) {
        this.locations = locations;
    }

    
    
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public double getLattitude() {
        return lattitude;
    }

    @XmlElement(name="lat")
    public void setLattitude(double lattitude) {
        this.lattitude = lattitude;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
}

The Location.java is as follows:


package com.xml.node;

/**
 *
 * @author Dell
 */
public class Location {
    private String name, address;

    public Location() {
        name="LOCATION";
        address = "ADDRESS";
    }

    
    
    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }        
}


The Main Program is as follows:

public static void main(String[] args) {

        
        Country bd = new Country();
        
        bd.setCapital("Dhaka");
        bd.setName("Bangladesh");
        bd.setPopulation(160000000);
        bd.setImportance(2);
                
        bd.getCities().add("Dhaka");
        bd.getCities().add("Rajshahi");
        bd.getCities().add("Sylhet");
        bd.getCities().add("Chittagong");
        
        Place place1 = new Place();
        
        place1.setAddress("DHAKA"); place1.setLattitude(10.5); place1.setName("ZOO");
        
        place1.getLocations().add(new Location());
        place1.getLocations().add(new Location());
        place1.getLocations().add(new Location());
        
        bd.getPlaces().add(place1);
        
        Place place2 = new Place();
        place2.setAddress("RAJSHAHI"); place2.setLattitude(20.99); place2.setName("ZOO");
        
        place2.getLocations().add(new Location());
        place2.getLocations().add(new Location());
        place2.getLocations().add(new Location());
        
        bd.getPlaces().add(place2);
        
        try {
            // TODO code application logic here
            
            JAXBContext context = JAXBContext.newInstance(Country.class);
            
            Marshaller marshal = context.createMarshaller();
            
            marshal.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            
            marshal.marshal(bd, new FileWriter("country.xml"));

            marshal.marshal(bd, System.out);

        } catch (IOException ex) {
            Logger.getLogger(XMLMagic.class.getName()).log(Level.SEVERE, null, ex);
        } catch (JAXBException ex) {
            Logger.getLogger(XMLMagic.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        

    }

Output Country.xml is as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<country imp="2">
    <countryPopulation>160000000</countryPopulation>
    <countryName>Bangladesh</countryName>
    <countryCapital>Dhaka</countryCapital>
    <cities>
        <city>Dhaka</city>
        <city>Rajshahi</city>
        <city>Sylhet</city>
        <city>Chittagong</city>
    </cities>
    <place>
        <name>ZOO</name>
        <address>DHAKA</address>
        <lat>10.5</lat>
        <locations>
            <address>ADDRESS</address>
            <name>LOCATION</name>
        </locations>
        <locations>
            <address>ADDRESS</address>
            <name>LOCATION</name>
        </locations>
        <locations>
            <address>ADDRESS</address>
            <name>LOCATION</name>
        </locations>
    </place>
    <place>
        <name>ZOO</name>
        <address>RAJSHAHI</address>
        <lat>20.99</lat>
        <locations>
            <address>ADDRESS</address>
            <name>LOCATION</name>
        </locations>
        <locations>
            <address>ADDRESS</address>
            <name>LOCATION</name>
        </locations>
        <locations>
            <address>ADDRESS</address>
            <name>LOCATION</name>
        </locations>
    </place>
</country>



2. Un-Marshaling

You can un marshal (load XML file into object) country.xml by using following lines:

try {
            JAXBContext context = JAXBContext.newInstance(Country.class);
            Unmarshaller unmarshal = context.createUnmarshaller();
            
            File file = new File("country.xml");
            
            Country country = (Country) unmarshal.unmarshal(file);
            
            System.out.println(country);
            
        } catch (JAXBException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }





3. Handling Complex Data Type Using Adapter

If we want to marshaling complex data type such as java.util.Date into a specific format, then we've to write an adapter class to indicate JAXB how to manage.

The class must extends from XmlAdapter class and implements following abstract methods of this class:

- marshal &
- unmarshal

I've write the following Adapter class:


import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.xml.bind.annotation.adapters.XmlAdapter;

public class DateAdapter extends  XmlAdapter<String, Date> {

    @Override
    public String marshal(Date v) throws Exception {
        
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        return sdf.format(v);
    }

    @Override
    public Date unmarshal(String v) throws Exception {
        Date dt = new SimpleDateFormat("dd-MM-yyyy").parse(v);
        return dt;
    }
   
}

And in Country.class I've add following:




Add the following 2 lines in Main program to see the value of foundationDate node in XML:

Date dt = new Date("26-MAR-1971");
        
 bd.setFoundation(dt); 




Run the Main program to check the output:




And that's all about this topic.



Thursday, May 5, 2016

JAVA Entity Class Creation Technique For Simple Key and Composite Key Tables

This is quite advanced topic.  But this is the blog for making advanced topic into a simple topic !!! 



My Environment is as follows:

1. EJB 3.0 containing stateless remote session bean.

2. Data Source.

3. Entity Class for table in Oracle RDBMS.

4. JBOSS 6 Application Server

5. A console based application to test the bean.

Entity class is a persistent object or POJO which  represents the data-stores record of a table. It is good to be a serializable.

You can simply say that an Entity class contains a single data record of a table in a RDBMS Or data storing (persistence) class in JAVA programming language. 

Please don't be confused of term POJO (Plain Old Java Object). POJO means that a class never be subclass or implements any class methods. It has just class-level variables and corresponding getter setter methods. For example:

// A Sample POJO Class
public class ClassA
{
         private String name;
         private String address;

         public ClassA()
        {
                    //Code
         }

         public setName(String name)
        {
                    this.name = name;
         }

         public String getName()
        {
                   return name;
         }

         public setAddress(String address)
        {
                    this.address = address;
         }

         public String getAddress()
        {
                    return address;
         }
}

To create Entity Class we'll use this type of class. Just adding few @annotaions.

And 1 more thing, to use Entity Class (for DML opeartions), you have to  EntityManager persistent interface to add/delete/update/find. But this is not our topic.

Now we'll create Entity class for simple key table that means only 1 column is primary key.


CREATE TABLE   books (   id     integer PRIMARY KEY,   name   varchar(50));


Now, i'll create an entity class for books. I'll use following annotations.

@Entity: defines this POJO class is an entity.

@Table (name="books"): specify the table name.

@Column (name="name"): specify the column name.

@Id: defines the primary key property of a table.

@Basic(optional=false): if is followed by @Id. It tells that no sequence generated for primary key that means the value of primary key filed will be set manually.

Using the above r annotations, i'll create an entity class of the table: books.



           import java.io.Serializable;
           import java.math.BigDecimal;
           import javax.persistence.*;
@Entity                                           // defines this is an entity class
@Table(name="books")                 // defines the table name  
public class Book implements Serializable {  
    
    @Id                                             // defines this is a primary key field
    @Basic(optional = false)            // defines the value not auto generated
    @Column(name="id")                // defines the column name
    private BigDecimal id;
    
    @Column(name="name")          // defines the column name

    private String name;

    public Book() {
    }

    
    public BigDecimal getId() {
        return id;
    }

    public void setId(BigDecimal id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

Now i'll create a composite primary key table.


create table MyPersistentTable
          (
   id integer,
   trn_ref_no varchar2(50),
   amount number,
   primary key(id, trn_ref_no)
);
The above table has composite primary key of two columns.There is 2 techniques to create entity class for above table.

1st Technique

Just create an entity class of MyPersistentTable table just  like before example.


@Entity
@Table(name="MyPersistentTable")
public class MyTable1 implements Serializable {
    
    @Id
    @Basic(optional=false)
    @Column(name="id")
    private int id;
    
    @Id
    @Basic(optional=false)
    @Column(name="trn_ref_no")
    private String refNo;
    
    @Column(name="amount")
    private BigDecimal price;

    public MyTable1() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getRefNo() {
        return refNo;
    }

    public void setRefNo(String refNo) {
        this.refNo = refNo;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}


2nd Technique

In this approach i'll create another class for 2 field primary keys (id + trn_ref_no) in MyPersistentTable table. And i tell the entity class that the new class is id class.

The fields inside the new class will be used as id/keys.

I use the annotation @Embeddable for the new class

@Embeddable annotation specifies that the class will be id class.

And i tell the entity class using annotation @EmbeddedId about the id class.

@EmbeddedId annotation used to define id class in entity class.

In our case, id class is following:


@Embeddable
public class MyTable2PK implements Serializable{
    
    
    @Basic(optional=false)
    @Column(name="id")
    private int id;
    
    
    @Basic(optional=false)
    @Column(name="trn_ref_no")
    private String refNo;

    public MyTable2PK() {
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getRefNo() {
        return refNo;
    }

    public void setRefNo(String refNo) {
        this.refNo = refNo;
    }    
}


And Entity class is as follows:



@Entity
@Table(name="MyPersistentTable")
public class MyTable2 implements Serializable {
    
    @EmbeddedId
    protected MyTable2PK pk;
    
    
    @Column(name="amount")
    private BigDecimal price;

    public MyTable2() {
    }

    public MyTable2PK getPk() {
        return pk;
    }

    public void setPk(MyTable2PK pk) {
        this.pk = pk;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }
}




My bean class is so simple to add/select data from table using above entity class.

@Stateless
public class LibraryPersistentBean implements LibraryPersistentBeanRemote {

    public LibraryPersistentBean() {
    }

    // Add business logic below. (Right-click in editor and choose
    // "Insert Code > Add Business Method")

    @PersistenceContext(unitName="EjbComponentPU")
    private EntityManager manager;
    
    @PersistenceContext(unitName="EjbComponentPU")
    private EntityManager mgr1;
    
    @Override
    public List getBooks() {
        return manager.createQuery("Select b From Book b").getResultList();
    }

    @Override
    public void addBook(Book book) {
        
        manager.persist(book);
    }

    @Override
    public void addMyTable1(MyTable1 myTable) {
        mgr1.persist(myTable);
    }

    @Override
    public List getMyTables1() {
        return mgr1.createQuery("select t from MyTable1 t").getResultList();
    }

    @Override
    public void addMyTable2(MyTable2 MyTable) {
        manager.persist(MyTable);
    }

    @Override
    public List getMyTables2() {
        return manager.createQuery("select t from MyTable2 t").getResultList();
    }  
}


And that is all about entity class.