Monday 14 January 2013

TopLink Without JPA

What is TopLink?

TopLink is an ORM(object relational management) framework for Java. Like the other popular framework Hibernate, using TopLink we can map Java objects to database entities or tables and can do various persistent operations. Also we can convert Java objects into XML objects. It is a product from Oracle Corporation. In 2007, Oracle donated the source code to Eclipse Foundation and the project EclipseLink was born. EclipseLink is the reference implementation for the Java Persistence API (JPA).


Persistent Operation using TopLink

Here I will show you how to use TopLink / EclipseLink in non-JPA environment. The application we are going to develop has a JSP page where user will enter roll no of a student and can retrieve student's name and percentage secured by clicking on 'Retrieve' button. There is an 'Update' button using which user can edit these details and save to the database.



Softwares / Tools

1. Struts 2.3.7
2. EclipseLink 2.4.1
3. MySQL 5.5
4. JDK 7
5. Eclipse Indigo Service Release 2
6. Apache Tomcat v7.0

Steps 

  • First, we will create a dynamic web project in Eclipse. Name of the project is TopApp. It contains 'student.jsp' page whose code is given below.
<%@taglib uri="/struts-tags" prefix="s" %>
<html>
<head>
<title>Welcome</title>
</head>
<body>
    <s:form action="studentAction" >
        <s:textfield name="rollNo" label="Enter Roll No"/>
        <s:submit name="method:retrieve" value="Retrieve" />
        <s:textfield name="name" label="Your Name"/>
        <s:textfield name="percentage" label="Percentage Scored"/>
        <s:submit name="method:update" value="Update" />
    </s:form>
</body>
</html>


  • Next we will create Student entity with 3 attributes 'rollNo', 'name' and 'percentage'.
package com.programnplay.entity;

public class Student {
    private int rollNo;
    private String name;
    private int percentage;
  
    public int getRollNo() {
        return rollNo;
    }
    public void setRollNo(int rollNo) {
        this.rollNo = rollNo;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getPercentage() {
        return percentage;
    }
    public void setPercentage(int percentage) {
        this.percentage = percentage;
    }
}

  • Third, we will create Struts Action class containing 2 methods for 'Retrieve' and 'Update' operations.
package com.programnplay.action;

import com.opensymphony.xwork2.ActionSupport;
import com.programnplay.dao.StudentDAO;
import com.programnplay.entity.Student;

public class StudentAction extends ActionSupport{
    private int rollNo;
    private String name;
    private int percentage;
    private static StudentDAO dao;
  
    public String execute() {
        dao = new StudentDAO();
        return SUCCESS;
    }
  
    public String retrieve() {
        Student stu = dao.getStudent(rollNo);
        rollNo = stu.getRollNo();
        name = stu.getName();
        percentage = stu.getPercentage();
        return SUCCESS;
    }
  
    public String update() {
        Student stu = new Student();
        stu.setRollNo(rollNo);
        stu.setName(name);
        stu.setPercentage(percentage);
        dao.updateStudent(stu);
        return SUCCESS;
    }

    public int getRollNo() {
        return rollNo;
    }

    public void setRollNo(int rollNo) {
        this.rollNo = rollNo;
    }

    public String getName() {
        return name;
    }

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

    public int getPercentage() {
        return percentage;
    }

    public void setPercentage(int percentage) {
        this.percentage = percentage;
    }
}
  • Below is given web.xml configuration. 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>TopApp</display-name>
  <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>


  • Struts.xml configuration is as follows.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
    <package name="default" extends="struts-default">
        <action name="studentAction" class="com.
programnplay.action.StudentAction">
            <result name="success">/jsp/student.jsp</result>
        </action>
    </package>
</struts>


With this our presentation layer is ready. So we will move now to service or data access layer. Already I have created 'Student' entity. The table this entity corresponds to has the following structure.

 Field              Type               Null    Key     
----------          -----------         ------  ------    

Roll                  int(3)              NO      PRI    
FirstName        varchar(15)    YES            
Percentage        int(2)             YES            

To access database through TopLink or EclipseLink, we need to create a configuration file named as 'sessions.xml'. This is the most important file which must be placed in application classpath i.e., under /WEB-INF/classes. It is through this file, SessionManager of TopLink creates Session to interact with the database. So 'sessions.xml' contains information about the data source, mapping between entities and tables etc.
  • The contents of 'sessions.xml' file is given below.
<?xml version="1.0" encoding="UTF-8" ?>
<sessions version="2.1"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<session xsi:type="database-session">
    <name>default</name>
    <event-listener-classes />
    <primary-project xsi:type="xml">mapping.xml</primary-project>
</session>
</sessions>

  • The file 'mapping.xml' which is being referred by 'sessions.xml' is as follows.
<?xml version="1.0" encoding="UTF-8"?>
<object-persistence xmlns="http://www.eclipse.org/eclipselink/xsds/persistence"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:eclipselink="http://www.eclipse.org/eclipselink/xsds/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.eclipse.org/eclipselink/xsds/persistence
     http://www.eclipse.org/eclipselink/xsds/persistence/eclipselink_persistence_map_2.3.xsd"
    version="Eclipse Persistence Services - 2.4.1.v20121003-ad44345">
   <name>Student</name>
   <class-mapping-descriptors>
      <class-mapping-descriptor xsi:type="relational-class-mapping-descriptor">
         <class>com.
programnplay.entity.Student</class>
         <alias>Student</alias>
         <primary-key>
            <field table="Student" name="Roll" xsi:type="column"/>
         </primary-key>
         <events/>
         <querying/>
         <attribute-mappings>
            <attribute-mapping xsi:type="direct-mapping">
               <attribute-name>rollNo</attribute-name>
               <field table="Student" name="Roll" xsi:type="column"/>
            </attribute-mapping>
            <attribute-mapping xsi:type="direct-mapping">
               <attribute-name>name</attribute-name>
               <field table="Student" name="FirstName" xsi:type="column"/>
            </attribute-mapping>
            <attribute-mapping xsi:type="direct-mapping">
               <attribute-name>percentage</attribute-name>
               <field table="Student" name="Percentage" xsi:type="column"/>
            </attribute-mapping>
         </attribute-mappings>
         <descriptor-type>independent</descriptor-type>
         <caching>
            <cache-sync-type>change-set</cache-sync-type>
         </caching>
         <instantiation/>
         <copying xsi:type="instantiation-copy-policy"/>
         <tables>
            <table name="Student"/>
         </tables>
      </class-mapping-descriptor>
   </class-mapping-descriptors>
   <login xsi:type="database-login">
        <platform-class>org.eclipse.persistence.platform.database.MySQLPlatform</platform-class>
           <user-name>abc</user-name>
           <password>abc</password>
           <driver-class>com.mysql.jdbc.Driver</driver-class>
           <connection-url>jdbc:mysql://localhost:3306/mydb</connection-url>
       </login>
</object-persistence>

  • At last we will create StudentDAO, the data access object which interacts with the MySQL database using EclipseLink session.
package com.programnplay.dao;

import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.factories.SessionManager;

import com.programnplay.entity.Student;

public class StudentDAO {
    SessionManager manager;
    Session session;
   
    public StudentDAO(){
        manager = SessionManager.getManager();
        session = manager.getDefaultSession();
    }

    public Student getStudent(int rollNo){
        Student stu = (Student)session.readObject(Student.class, new ExpressionBuilder().get("rollNo").equal(rollNo));
        session.refreshObject(stu);
        return stu;
    }
   
    public void updateStudent(Student student){
        ((DatabaseSession)session).beginTransaction();
        ((DatabaseSession)session).updateObject(student);
        ((DatabaseSession)session).commitTransaction();
    }
}

StudentDAO contains 2 methods, getStudent() and updateStudent() to retrieve and update the Student entity respectively. To do so, getStudent() uses readObject() method while updateStudent() uses updateObject() method of session. TopLink creates conditional clauses using ExpressionBuilder class. By default, EclipseLink stores entities retrieved in session cache. Hence if we use the same query again, it will get the entity from cache until and unless we use refreshObject() method.

Similarly we can do insert and delete operations using insertObject() and deleteObject() respectively. I have left it as an exercise to the readers.
  • Now let us start Tomcat Server, open the browser and place the url http://localhost:8080/TopApp/studentAction in address bar. We will get a screen similar as follows: 
Running the TopLink App
Running the TopLink App

    Hurray! See you in my next techno blog.


      No comments:

      Post a Comment