Tag: MySQL

JDK8 Based Nashorn JavaScript & Java to interact with MySQL Database. (part-2)

Hi,

As part of out previous article “Why Nashorn Java Scripting in Java8, Is it Poisonous for Java? (part-1)”, We discussed some very basics of JDK8, Nashorn Java Script and about the “$JAVA_HOME/bin/jjs” command line tool. We also learned that how we can invoke a JavaScript snippet or script file from inside a java code and Also how to use the Java APIs inside a simple Java Script code.

So now lets move a step ahead and see how to interact with the Database using Nashorn Java Script. In this demo we will extensively focus on how to use various java APIs and java packages inside the Nashorn Script.

What this demo is about?

As part of this demo we will learn about the following things:

1. How to create a Database and some sample tables in MySQL database.

2. How to write a simple Nashorn Java Script to interact with MySQL.

3. How to execute the Nashorn Script using jjs.

4. How to Invoke the Nashorn Java Script from inside a java code.

Other Parts of this articles are:

Why Nashorn Java Scripting in Java8, Is it Poisonous for Java? (part-1)

Server Side Java Script Nashorn, WildFly10, Undertow with MySQL (part-3)

Setting up MySQL Database

Start the MySQL database and then do the following steps which will basically do the following things:
A. Creating a simple Database with name “TestJavaScriptDB”
B. Creating a table with name “CUSTOMER”.
C. Insert some dummy records inside the “CUSTOMER” table.

mysql -u root -p 
password:


mysql> create database TestJavaScriptDB;
Query OK, 1 row affected (0.00 sec)


mysql> use TestJavaScriptDB;
Database changed


mysql> CREATE TABLE CUSTOMER (custId INT(10) NOT NULL, custName CHAR(20) NOT NULL);
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO CUSTOMER VALUES (1000, "MiddlewareMagic");
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO CUSTOMER VALUES (2000, "Customer-2");
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO CUSTOMER VALUES (3000, "Customer-3");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM CUSTOMER;
+--------+-----------------+
| custId | custName        |
+--------+-----------------+
|   1000 | MiddlewareMagic |
|   2000 | Customer-2      |
|   3000 | Customer-3      |
+--------+-----------------+
3 rows in set (0.01 sec)

Writing Nashorn JavaScript

Now lets start writing the Java Script to interact with the Database. So lets create a file “testDB.js” somewhere in the filesystem as following:

//  ## JDBC Based JavaScript  ##

// Declaring the getConnection function
var getConnection = function() {
    var Properties = Java.type("java.util.Properties");
    var Driver = Java.type("com.mysql.jdbc.Driver");
    var driver = new Driver();
    var properties = new Properties();
    var conn = null;
    try {
        properties.setProperty("user", "root");
        properties.setProperty("password", "testpwd");
        conn = driver.connect("jdbc:mysql://localhost:3306/TestJavaScriptDB", properties);
        return conn;
    } finally {
    
    }
}

print("****** conn : " + getConnection());

// Declaring the runQuery function
function runQuery(conA, query) {
   try {
       var stmt = conA.prepareStatement(query);
       var resultSet = stmt.executeQuery();
       print("      --------------------------- ");
       while (resultSet.next()) {
          print("\t" + resultSet.getString("custId") + " - "+ resultSet.getString("custName"))
       }
       print("      --------------------------- ");
       
    } finally {
      if (resultSet)
         try {
            resultSet.close();
            print("\nResultSet Closed.");
         }
         catch(e) {}
      if (stmt)
         try {
            stmt.close();
            print("Statement Closed.");            
         } catch (e) { print( e );  }
      if (conA)        
         try { 
            conA.close();
            print( "Connection Closed." );
         } catch (e) { print( e );  }          
      }  
 } 


// Invoking the getConnection and runQuery() functions.
var con1 = getConnection();
runQuery(con1, "select * from CUSTOMER");

Running testDB.js script using jjs

As we know that JDK8 provides the “jjs” utility as part of “$JAVA_HOME/bin” directory which is a command line utility to execute the Nashorn Java Script. Here we will be using that utility to run the testDB.js script. Open a terminal and then run the following commands in order to set the JDK8 in the path.

Unix Based OS

export JAVA_HOME=/PATH/TO/jdk1.8.0_60
export PATH=$JAVA_HOME/bin/jjs:$PATH

Windows Based OS

set JAVA_HOME=C:\jdk1.8.0_60
set PATH=%JAVA_HOME%\bin;%PATH%

After setting the path lets run the Java Script.

$ jjs -cp /PATH/TO/mysql-connector-java-5.1.37-bin.jar:.: testDB.js 

****** conn : com.mysql.jdbc.JDBC4Connection@384ad17b
      --------------------------- 
	1000 - MiddlewareMagic
	2000 - Customer-2
	3000 - Customer-3
      --------------------------- 

ResultSet Closed.
Statement Closed.
Connection Closed.

NOTICE: while running the “testDB.js” script make sure to set the Classpath using the “-cp” option provided by “jjs” utility.
Windows users need to use “;” semi colon rather than using the “:” Colon while defining the classpath. as following:
-cp C:\PATH\TO\mysql-connector-java-5.1.37-bin.jar;.;

If users will not set the classpath properly then it will throw the following kind of error because it won’t be able to find the MySQL JDBC Driver.

$ jjs testDB.js 

Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:397)
	at jdk.nashorn.tools.Shell.apply(Shell.java:397)
	at jdk.nashorn.tools.Shell.runScripts(Shell.java:326)
	at jdk.nashorn.tools.Shell.run(Shell.java:172)
	at jdk.nashorn.tools.Shell.main(Shell.java:136)
	at jdk.nashorn.tools.Shell.main(Shell.java:112)
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at jdk.nashorn.internal.runtime.Context.findClass(Context.java:1051)
	at jdk.nashorn.internal.objects.NativeJava.simpleType(NativeJava.java:493)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:322)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:314)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:310)
	at jdk.nashorn.internal.scripts.Script$Recompilation$1$65$testDB.getConnection(testDB.js:5)
	at jdk.nashorn.internal.scripts.Script$testDB.:program(testDB.js:19)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	... 5 more

Invoking testDB.js script from Java code

Just now we have seen that how we can use the “$JAVA_HOME/bin/jjs” command line utility in order to execute the Nashorn JavaScript. Now we will write a simple java code using the “javax.script.ScriptEngineManager” and “javax.script.ScriptEngine” APIs.
Hence lets write a java program “ExampleNashornJdbc.java” somewhere in the filesystem as following:

import javax.script.*;
import java.io.*;

public class ExampleNashornJdbc {
	public static void main(String ar[]) throws Exception {
		ScriptEngineManager enginManager = new ScriptEngineManager();
		ScriptEngine engine = enginManager.getEngineByName("Nashorn");
		try {
			// Executing a simple java script file
			FileReader javaScriptFileReader = new FileReader(new File("testDB.js"));
            engine.eval(javaScriptFileReader);
            
		 } catch(final ScriptException se) {
			se.printStackTrace();
		 }
	}
}

Running Java ScriptEngine to execute testDB.js

Lets run the above code which will internally evaluate the “testDB.js” script.

$ java -cp /PATH/TO/mysql-connector-java-5.1.37-bin.jar:.: ExampleNashornJdbc
****** conn : com.mysql.jdbc.JDBC4Connection@7c729a55
      --------------------------- 
	1000 - MiddlewareMagic
	2000 - Customer-2
	3000 - Customer-3
      --------------------------- 

ResultSet Closed.
Statement Closed.
Connection Closed.

Do not forget to append the “.” in the classpath “-cp” else java virtual machine will search for the ExampleNashornJdbc class also inside the same “mysql-connector-java-5.1.37-bin.jar” and it wont find that class there ;).

If the Classpath is not set properly with the JDBC driver jar included in it then you may see the following kind of exception:

$ java ExampleNashornJdbc


Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:397)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:446)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:403)
	at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:399)
	at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:150)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:249)
	at ExampleNashornJdbc.main(ExampleNashornJdbc.java:11)
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:348)
	at jdk.nashorn.internal.runtime.Context.findClass(Context.java:1051)
	at jdk.nashorn.internal.objects.NativeJava.simpleType(NativeJava.java:493)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:322)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:314)
	at jdk.nashorn.internal.objects.NativeJava.type(NativeJava.java:310)
	at jdk.nashorn.internal.scripts.Script$Recompilation$1$65$\^eval\_.getConnection(<eval>:5)
	at jdk.nashorn.internal.scripts.Script$\^eval\_.:program(<eval>:19)
	at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:640)
	at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:228)
	at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
	... 6 more

Source code for this demo is present in :
https://github.com/jaysensharma/MiddlewareMagicDemos/tree/master/WildFly/Java_8/ServerSideJavaScript/Part-2-Jdbc

.
.
Regards
Jay SenSharma


Management User Authentication using Encrypted Passwords with Database LoginModule AS7

Hi,

We have seen that using “$JBOSS_HOME/bin/add-user.sh” script we can create Management & Application Users. Using “add-user.sh” script when we create users then the credentials of Management user is stored inside the “$JBOSS_HOME/standalone/configuration/mgmt-users.properties” and inside the “$JBOSS_HOME/standalone/configuration/mgmt-users.properties” file. Even though the passwords are encrypted in these properties file still many administrators like to store their management credentials inside the Database rather than storing them inside the Database.

In our previous Demo we saw how to Authenticate Management Users based on the “DatabaseServerLoginModule” http://middlewaremagic.com/jboss/?p=2187 But the problem with that approach is we can see the Cleartext passwords present inside the Database as following:

mysql> select * from PRINCIPLES;
+--------------+----------+
| principal_id | password |
+--------------+----------+
| adminUser    | admin123 |
+--------------+----------+
1 row in set (0.00 sec)

But in this Current Demo we will see how we can store the Encrypted (MD5 + hex) password in the Database so that it will be safe. This can be simply achieved by adding the following two module options in the “security-domain”


    <module-option name="hashAlgorithm" value="MD5"/>
    <module-option name="hashEncoding" value="hex"/>

We will see it in more details so first we will proceed with creating the Hashed Password. Here we will write a simple program in order to Encrypt the Management User’s password.

Program to Encrypt Management User’s Password

Step1). Write the following program “EncryptPassword.java” inside your file system somewhere.

import java.security.MessageDigest;
import java.math.BigInteger;
import org.jboss.crypto.CryptoUtil;

public class EncryptPassword
  {
    public static void main(String ar[]) throws Exception
     {
       /*
       You will need the following JAFRs in your classpath in order to compile & run this program 
       export CLASSPATH=$JBOSS_HOME/modules/org/picketbox/main/picketbox-4.0.7.Final.jar:$JBOSS_HOME/bin/client/jboss-client.jar:$CLASSPATH:.:
       */

       //String clearTextPassword=ar[0]+":ManagementRealm:"+ar[1];     //---> This is how JBoss Encrypts password

       String clearTextPassword=ar[0];
       String hashedPassword=CryptoUtil.createPasswordHash("MD5", "hex", null, null, clearTextPassword);
       System.out.println("clearTextPassword: "+clearTextPassword);
       System.out.println("hashedPassword: "+hashedPassword);
     }
  }

Step2). Now Open a terminal/Command prompt then set the PATH to include the JDK “bin” directory in it. Also we will set the CLASSPATH by including the “picketbox-4.0.7.Final.jar” and “jboss-client.jar” jar, which are required in order to compile and run the program. As soon as we will run the following program we will see the HashedPassword which we need to insert in the database “PRINCIPLES” table.


export JBOSS_HOME=/home/userone/jboss-as-7.1.1.Final

export CLASSPATH=$JBOSS_HOME/modules/org/picketbox/main/picketbox-4.0.7.Final.jar:$JBOSS_HOME/bin/client/jboss-client.jar:$CLASSPATH:.:

javac EncryptPassword.java 

java EncryptPassword admin123

_________

OUTPUT
_________

clearTextPassword: admin123
hashedPassword: 0192023a7bbd73250516f069df18b500

MySQL Database & Datasource configuration

First of all we will see what all configurations are needed at the Database end and the Datasource configuration.
Step3). Start the MySQL database and then create the following Tables with the required Data as mentioned:

CREATE TABLE PRINCIPLES ( principal_id VARCHAR(64) primary key,password VARCHAR(64));
CREATE TABLE ROLES ( principal_id VARCHAR(64),user_role VARCHAR(64),role_group VARCHAR(64));

Insert into PRINCIPLES values('adminUser','0192023a7bbd73250516f069df18b500');
Insert into ROLES values('adminUser','admin','admin');

You can insert more records in your database based on your requirement. I created only one Admin User.

mysql> select * from PRINCIPLES;
+--------------+----------------------------------+
| principal_id | password                         |
+--------------+----------------------------------+
| adminUser    | ec28e69f42b23f2e524572c4f263263d |
+--------------+----------------------------------+
1 row in set (0.00 sec)

***NOTE*** As you can see that actually the password for user “adminUser” is “admin123” but we entered the Encrypted password (0192023a7bbd73250516f069df18b500) for this user inside the Database not the Clear Text Password.

JBossAS7 side configuration

Step4). Place the MySQL database driver “mysql-connector-java-5.1.13-bin.jar” inside the “$JBOSS_HOME/standalone/deployments” directory.

Step5). Now start your JBossAS7 standalone profile as following:

[userone@localhost bin]$ ./standalone.sh -c standalone-full.xml -bmanagement 10.10.10.10 -b 20.20.20.20

NOTE: You can start your Server in localhost address as well. Here i started the JBoss Management interface at 10.10.10.10 Address where as the public interface on “20.20.20.20”.

Step6). It’s time to create a DataSource. So lets start the JBossAS7.1.1.Final and then open the JBoss CLI utility “$JBOSS_HOME/bin/jboss-cli.sh” then run the following command in order to create MySQL DataSource as following:

 [userone@localhost bin]$ ./jboss-cli.sh --connect --controller=10.10.10.10:9999

 [standalone@10.10.10.10:9999 /] /subsystem=datasources/data-source="java:jboss/MySqlDS":add(jndi-name="java:jboss/MySqlDS",pool-name="MySqlPool",driver-name="mysql-connector-java-5.1.13-bin.jar",connection-url="jdbc:mysql://localhost:3306/testDB",user-name="root",password="redhat")

Once the above command executes successfully executes you will see the following kind of entry inside your “$JBOSS_HOME/standalone/configuration/standalone-full.xml” file (Inside the “[subsystem xmlns=”urn:jboss:domain:datasources:1.0″]” subsystem):

   <datasource jndi-name="java:jboss/MySqlDS" pool-name="java:jboss/MySqlDS">
       <connection-url>jdbc:mysql://localhost:3306/testDB</connection-url>
       <driver>mysql-connector-java-5.1.13-bin.jar</driver>
       <security>
          <user-name>root</user-name>
          <password>redhat</password>
       </security>
   </datasource>

Step7). Now we will create a Security-Domain inside the “[subsystem xmlns=”urn:jboss:domain:security:1.1″]” subsystem of your “$JBOSS_HOME/standalone/configuration/standalone-full.xml” file as following:

  <security-domain name="DBAuthTest">
      <authentication>
         <login-module code="Database" flag="required">
            <module-option name="dsJndiName" value="java:jboss/MySqlDS"/>
            <module-option name="principalsQuery" value="select password from  PRINCIPLES where principal_id=?"/>
            <module-option name="rolesQuery" value="select user_role, 'Roles' from  ROLES where  principal_id=?"/>
            <module-option name="password-stacking" value="useFirstPass"/>

            <!-- Encryption Related module-options -->
            <module-option name="hashAlgorithm" value="MD5"/>
            <module-option name="hashEncoding" value="hex"/>

         </login-module>
         <login-module code="org.jboss.security.auth.spi.RoleMappingLoginModule" flag="optional">
            <module-option name="rolesProperties" value="${jboss.server.config.dir}/test-roles.properties"/>
            <module-option name="replaceRole" value="false"/>
         </login-module>
     </authentication>
   </security-domain>

Step8). As you can see above that in the “RoleMappingLoginModule” configuration we passed a file “test-roles.properties” for mapping the database user to the authorization role. So we will need to now create a file with name “test-roles.properties” inside the following location
“$JBOSS_HOME/standalone/configuration/test-roles.properties”
and
“$JBOSS_HOME/domain/configuration/test-roles.properties”

#username=RoleName
adminUser=admin

Step9). The Most important part now. We will edit the “$JBOSS_HOME/standalone/configuration/standalone-full.xml” file as well as “$JBOSS_HOME/domain/configuration/domain.xml” file <management> <security-realms> section as following sothat our custom security “DBAuthTest” can be associated with this ManagementRealm:

    <security-realm name="ManagementRealm">
        <authentication>
             <jaas name="DBAuthTest"/>
        </authentication>
    </security-realm>

Step10). Restart your JBossAS7 profile and then try to access the JBoss Console “http://10.10.10.10:9990/console” with the database table credential like
username: adminUser
password: admin123

.
.
Thanks 🙂
MiddlewareMagic Team


Resteasy and JPA with Hibernate as Provider in JBoss AS7

Hi,

The Java Persistence Architecture API (JPA) is a Java specification for accessing, persisting, and managing data between Java objects / classes and a relational database. JPA was defined as part of the EJB 3.0 specification as a replacement for the EJB 2 CMP Entity Beans specification. JPA is now considered the standard industry approach for Object to Relational Mapping (ORM) in the Java Industry.

JBoss also provides feature to deploy JAX-RS based applications including package “org.jboss.resteasy.*”. Here in this example we will see how to integrate the Resteasy wtih JPA. In this process we will see how to use various annotations like @XmlRootElement, @ApplicationPath @Entity @PersistenceContext etc.. A Quick tour on JAX-RS Reference Guide will be better.

The JBoss Application Server JPA subsystem implements the JPA 2.0 container-managed requirements. JPA Applications use the Hibernate (core) 4.0 persistence provider, that is included with JBoss AS. Hibernate 4 is packaged with the AS and is the default persistence provider. The JPA 2.0 Specifications can be found in the following link: http://jcp.org/aboutJava/communityprocess/pfd/jsr317/index.html

A Best reference for JPA features inside JBoss AS7 can be foun in the following link: JPA Reference Guide

However in this current emo we will just create a Simple JPA persistence unit and then we will try to insert some employee detils insie the DataBase using the JAX-RS as frontend. So basically this is just as a startup.

In this example we will mainly focus on following points

Point-1). For Web Applications we should put the “persistence.xml” file inside “${WEB_APPLICATION}/WEB-INF/classes/META-INF/persistence.xml”
For EJB Applications we should put the “persistence.xml” file inside “${EJB_JAR}/META-INF”

Point-2). To inject the EntityManager inside our Web Components we can use the annotation @javax.persistence.PersistenceContext(unitName=”name”)

Point-3). How to use the JAX-RS resteasy implementations and various annotations associated with it.

<<< I S S U E >>>: I tried to use the @javax.ejb.EJB annotation to inject an Enterprise Java Bean inside Rest Easy component but it did not work Like @EJB(lookup=”jndiName”) , which need to be checked (May be it’s work as designed). But it worked fine inside a Servlet in another case.

Server Side Configuration

Point-1). Here we are using JBoss AS7 latest build “jboss-as-7.1.0.CR1” which can be downloaded from the following link: http://www.jboss.org/jbossas/downloads

Point-2). In order to get more details on how to create MySQL DataSource in JBoss AS7 you can refer to the following article: http://middlewaremagic.com/jboss/?p=872
Create a DataSource inside “${JBOSS_HOME}/standalone/configuration/standalone-full.xml” file as following:

        <subsystem xmlns="urn:jboss:domain:datasources:1.0">
            <datasources>
                <datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="H2DS" enabled="true">
                    <connection-url>
                        jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
                    </connection-url>
                    <driver>
                        h2
                    </driver>
                    <security>
                        <security-domain>
                            encrypted-ds
                        </security-domain>
                    </security>
                </datasource>


                <!-- Below is the DataSource Configuration which we added for our JPA TestCase-->
                <datasource jndi-name="java:/MySqlDS" pool-name="MySqlDS_Pool" enabled="true" jta="false" use-ccm="false">
                    <connection-url>
                        jdbc:mysql://localhost:3306/testDB
                    </connection-url>
                    <driver-class>
                        com.mysql.jdbc.Driver
                    </driver-class>
                    <driver>
                        mysql-connector-java-5.1.13-bin.jar
                    </driver>
                    <security>
                        <user-name>someDBUserName</user-name>
                        <password>someDBPassword</password>
                    </security>
                </datasource>
                <!-- Above is the DataSource we created on MySQL Database -->


                <drivers>
                    <driver name="h2" module="com.h2database.h2">
                        <xa-datasource-class>
                            org.h2.jdbcx.JdbcDataSource
                        </xa-datasource-class>
                    </driver>
                </drivers>
            </datasources>
        </subsystem>

Point-3). Restart your JBoss AS7 from inside “/home/userone/jboss-as-7.1.0.CR1/bin” directory as following:

.
 ./standalone.sh -c standalone-full.xml
.

Developing JPA Part Of the Test Case

Step1). Create a directory somewhere in your filesystem like “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7” where we will place our application build related stuff. Then create another directory “src” inside “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7” where we will be placing our source codes and JSPs.

Step2). Now first of all we will create an Entity “Employee.java” as following inside the “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” directory. NOTICE: we used the annotation “@XmlRootElement”

package jpa;
import java.io.Serializable;
import javax.persistence.*;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@Entity
@Table(name="Employee")
public class Employee implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	private Integer empno;
	private String ename;

        public Employee() {
    	 System.out.println("[Employee] Employee Object Created. "+this);
        }

	public Integer getEmpno() {
                System.out.println("[Employee] getEmpno() called on "+this);
		return this.empno;
	}

	public void setEmpno(Integer empno) {
                System.out.println("[Employee] setEmpno("+empno+") called on "+this);
		this.empno = empno;
	}

	public String getEname() {
                System.out.println("[Employee] getEname() called on "+this);
		return this.ename;
	}

	public void setEname(String ename) {
                System.out.println("[Employee] setEname("+ename+") called on "+this);
		this.ename = ename;
	}

}

Step3). Now we will create a Simple Stateless SessionBean remote Interface “EmployeeServiceRemote.java” inside “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” directory as following:

package jpa;
import java.util.Collection;
import javax.ejb.Remote;
@Remote

public interface EmployeeServiceRemote{
  public void doAction();
  public Employee createEmployee(Integer id, String name);
  public void removeEmployee(Integer id);
  public Employee findEmployee(Integer id);
  public Collection<Employee> findAllEmployees() ;

}

Step4). Now we will Stateless Session Bean class “EmployeeService.java” by implementing the interface “EmployeeServiceRemote.java”. Place this file as well inside the “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” directory as following:

package jpa;
import java.util.Collection;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

@Stateless
public class EmployeeService implements EmployeeServiceRemote {
  @PersistenceContext(unitName="EmployeeService")
  EntityManager em;

  public EmployeeService() {
	  System.out.println("n[EmployeeService] EmployeeService Created. this: "+this);
  }

  public Employee createEmployee(Integer id, String name) {
    Employee emp = new Employee();
    emp.setEmpno(id);
    emp.setEname(name);
    em.persist(emp);
    emp = findEmployee(id);
    System.out.println("n[EmployeeService] Inside createEmployee() findEmployee result: "+emp+"t this: "+this);
    em.flush();
    return emp;
  }

  public void removeEmployee(Integer id) {
    System.out.println("n[EmployeeService] Inside removeEmployee("+id+") this: "+this);
    Employee emp = findEmployee(id);
    if (emp != null) {
      em.remove(emp);
    }
  }

  public Employee findEmployee(Integer id) {
    System.out.println("n[EmployeeService] Inside findEmployee("+id+") this: "+this);
    return em.find(Employee.class, id);
  }

  @SuppressWarnings("unchecked")
  public Collection<Employee> findAllEmployees() {
    System.out.println("n[EmployeeService] Inside findAllEmployees() this: "+this);
    Query query = em.createQuery("SELECT e FROM Employee e");
    return (Collection<Employee>) query.getResultList();
  }

  public void doAction(){
  }
}

Step5). Now we will write the “persistence.xml” file inside the “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” directory as following:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
	xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
	<persistence-unit name="EmployeeService"> <!-- transaction-type="JTA" -->
		<jta-data-source>java:/MySqlDS</jta-data-source>
		<class>jpa.Employee</class>
		<properties>
			<property name="hibernate.hbm2ddl.auto" value="create-drop" />
                        <property name="hibernate.show_sql" value="true" />
			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
		</properties>
	</persistence-unit>
</persistence>

NOTE: We need to make sure that this “persistence.xml” file goes inside the “${war.name}/WEB-INF/classes/META-INF” directory of our WAR file.
Due to the property “hibernate.hbm2ddl.auto” the Employee table will be automatically created in the database as soon as we deploy the application on JBoss and will be automatically droped as soon as we undeploy our application. Valid values for this property are “validate | update | create | create-drop”

Developing JAX-RS Part Of the Test Case

Step6). Now we will write a simple “index.jsp” page to just provide a some input forms so that a user can enter the employee name and id details , Place this file as well inside the “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” directory as following:

<html>
<head>
<title>JPA With Rest Demo In JBoss AS7</title>
</head>
<body>

<h1>Add An Employee</h1>
   <table border="10%">
      <form action="services/create" method="post">
         <TR><TD>Enter Employee ID </TD><TD> <input name="empno" type="text" value="" /> </TD></TR>
         <TR><TD>Enter Employee Name </TD><TD> <input name="empname" type="text" value="" /> </TD></TR>
         <TR><TD><input type="submit" value="Add Employee" /></TD><TD> <input type="reset" value="Clear" /></TD></TR>
      </form>
    </table>

<h1>Remove An Employee</h1>
   <table border="10%">
     <form action="services/removeemployee" method="post">
         <TR><TD>Enter Employee ID </TD><TD> <input name="empno" type="text" value=""/> </TD></TR>
         <TR><TD></TD><TD><input type="submit" value="Remove Employee" /></TD></TR>
   </form>
    </table>

<h1>Find An Employee</h1>
   <table border="10%">
      <form action="services/findemployee" method="post">
         <TR><TD>Enter Employee ID </TD><TD> <input name="empno" type="text" value=""/> </TD></TR>
         <TR><TD></TD><TD><input type="submit" value="Find Employee" /></TD></TR>
      </form>
    </table>

<h1>Find All Employees</h1>
   <a href="services/findall">Find All Employees</a>  

</body>
</html>

Step7). We will write the “MyRestService.java” inside the “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” as following in order to insert the details entered by the user in previous index.jsp page.

package rest;
import java.util.Collection;

//Rest related imports
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.FormParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

// EJB Related imports
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.ejb.EJB;
import jpa.Employee;
import jpa.EmployeeServiceRemote;

@ApplicationPath("/services")
@Path("/")
public class MyRestService extends Application
{
   /* ::::NOTE::::
        The Following Injection is not Working which need to be checked. So Here i am doing the old style lookup for the EJB.

        @EJB(lookup="java:global/JPA_BASIC_Demo/EmployeeService!jpa.EmployeeServiceRemote")
        jpa.EmployeeServiceRemote remote;
   */

  jpa.EmployeeServiceRemote remote;
  public MyRestService()
     {
       try{
            InitialContext ctx=new InitialContext();
            remote = (EmployeeServiceRemote) ctx.lookup("java:global/JPA_BASIC_Demo/EmployeeService!jpa.EmployeeServiceRemote");
          }
       catch(NamingException ne) 
          {
            System.out.println("n[MyRestService]NamingException: "+ne);
            ne.printStackTrace();
          }
     }


  @POST
  @Path("/create")
  @Produces(MediaType.APPLICATION_XML)  
  @Consumes("application/x-www-form-urlencoded")
  public Employee createEmployee(@FormParam("empno") Integer id, @FormParam("empname") String name) 
    {
        System.out.println("n[MyRestService]jpa.EmployeeServiceRemote remote = "+remote);
        Employee emp=null;
        if(remote!=null)
           emp=remote.createEmployee(id,name);
        else
          {
           emp=new Employee();
           emp.setEname(name);
           emp.setEmpno(id);
          }
        return emp;
    }        


  @POST
  @Path("/removeemployee")
  @Consumes("application/x-www-form-urlencoded")
  @Produces(MediaType.TEXT_HTML)  
  public String removeEmployee(@FormParam("empno") Integer id) 
    {
        System.out.println("n[MyRestService]Inside removeEmployee("+id+") this: "+this);
        remote.removeEmployee(id);
        return "Emplloyee Removed with Id: "+id;
    }


  @POST
  @Path("/findemployee")
  @Produces(MediaType.APPLICATION_XML)  
  @Consumes("application/x-www-form-urlencoded")
  public Employee findEmployee(@FormParam("empno") Integer id) 
    {
        System.out.println("n[MyRestService]Inside findEmployee("+id+") this: "+this);
        Employee emp=remote.findEmployee(id);
        return  emp;
    }


  @GET
  @Produces(MediaType.APPLICATION_XML)  
  @Path("/findall")
  public Collection<Employee> findAllEmployees() 
   {
       System.out.println("n[MyRestService]Inside findAllEmployees() this: "+this);
       Collection<Employee> collection=remote.findAllEmployees();
       return collection;
   }
}

Step8). As this is going to be a WebApplication so we will provide a simple default “web.xml” file inside “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/src” directory as following:

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

</web-app>

Building and deploying the Application

Step9). Now the most important part, here we are going to develop “build.xml” ANT file, which will build, deploy our web application on the JBoss AS7.1 CR1 Server, so write the following “build.xml” file inside “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7” directory.

<project name="JPA_BASIC_Demo" default="deploy">
<property name="jboss.home" value="/home/userone/jboss-as-7.1.0.CR1" />
<property name="jboss.module.dir" value="${jboss.home}/modules" />
<property name="basedir" value="." />
<property name="tmp.dir" value="tmp" />
<property name="output.dir" value="build" />
<property name="src.dir" value="src" />
<property name="war.name" value="JPA_With_JAXRS_BASIC_Demo.war" />
 
   <path id="jboss.classpath">
     <fileset dir="${jboss.module.dir}">
        <include name="**/*.jar"/>
     </fileset>
   </path>
 
        <target name="init">
           <delete dir="${output.dir}" />
           <mkdir dir="${output.dir}" />
           <delete dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}" />
           <mkdir dir="${tmp.dir}/WEB-INF/classes/META-INF"/>
        </target>
 
        <target name="build" depends="init">
           <javac srcdir="${src.dir}" destdir="${tmp.dir}/WEB-INF/classes"  includes="*.java" classpathref="jboss.classpath" />
           <copy todir="${tmp.dir}/WEB-INF/classes">
                <fileset dir="${src.dir}" includes="**/*.java"/>
           </copy>
           <copy file="${src.dir}/index.jsp" tofile="${tmp.dir}/index.jsp"/>
           <copy file="${src.dir}/web.xml" tofile="${tmp.dir}/web.xml"/>

           <!-- Make Sure that the persistence.xml file is placed inside "${war.name}/WEB-INF/classes/META-INF" directory -->
           <copy file="${src.dir}/persistence.xml" tofile="${tmp.dir}/WEB-INF/classes/META-INF/persistence.xml"/>

           <jar jarfile="${tmp.dir}/${war.name}" basedir="${tmp.dir}" compress="true" />
           <copy file="${tmp.dir}/${war.name}" tofile="${output.dir}/${war.name}"/>

           <delete includeEmptyDirs="true">
              <fileset dir="${tmp.dir}"/>
           </delete>
        </target>
 
        <target name="deploy" depends="build">
            <echo message="*******************  Deploying the WAR file ${war.name} *********************" />
            <echo message="********** ${output.dir}/${war.name} to ${jboss.home}/standalone/deployments **********" />
            <copy todir="${jboss.home}/standalone/deployments/">
                <fileset dir="${output.dir}/">
                  <include name="${war.name}"/>
                </fileset>
            </copy>
            <echo message="*******************  Deployed Successfully   *********************" />
        </target>
</project>

NOTE: The only change in the above file you need to do is to change the “jboss.home” directory path in the second line of the above script to point to your own JBoss AS7 directory.

Step10). Now before running your ANT script to build and deploy the above webapplication you should have the ANT as well as JAVA set in the $PATH variable of the Shell / command prompt as following:

For Unix Based OS:
export PATH=/home/userone/jdk1.6.0_21/bin:/home/userone/org.apache.ant_1.6.5/bin:$PATH

For Windows Based OS:
set PATH=C:/jdk1.6.0_21/bin;C:/org.apache.ant_1.6.5/bin;%PATH%

Step11). Now once the PATH is set In the command/Shell prompt you can move inside the directory “/home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7” and then run the ant to build the webservice. by running the command “ant”

[userone@localhost JPA2_JAXRS_And_Hibernate4_On_AS7]$ ant
Buildfile: /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/build.xml

init:
   [delete] Deleting directory /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/build
    [mkdir] Created dir: /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/build
    [mkdir] Created dir: /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp
    [mkdir] Created dir: /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp/WEB-INF/classes/META-INF

build:
    [javac] /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/build.xml:25: warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds
    [javac] Compiling 4 source files to /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp/WEB-INF/classes
     [copy] Copying 4 files to /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp/WEB-INF/classes
     [copy] Copying 1 file to /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp
     [copy] Copying 1 file to /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp
     [copy] Copying 1 file to /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp/WEB-INF/classes/META-INF
      [jar] Building jar: /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/tmp/JPA_With_JAXRS_BASIC_Demo.war
     [copy] Copying 1 file to /home/userone/JPA2_JAXRS_And_Hibernate4_On_AS7/build

deploy:
     [echo] *******************  Deploying the WAR file JPA_With_JAXRS_BASIC_Demo.war *********************
     [echo] ********** build/JPA_With_JAXRS_BASIC_Demo.war to //home/userone/jboss-as-7.1.0.CR1/standalone/deployments **********
     [copy] Copying 1 file to //home/userone/jboss-as-7.1.0.CR1/standalone/deployments
     [echo] *******************  Deployed Successfully   *********************

BUILD SUCCESSFUL
Total time: 2 seconds

Step12). Now you will see the following kind of output on your JBoss AS7.1 console which means the application is deployed successfully:

20:21:15,570 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-1) Starting deployment of "JPA_With_JAXRS_BASIC_Demo.war"
20:21:15,589 INFO  [org.jboss.jpa] (MSC service thread 1-2) JBAS011401: Read persistence.xml for EmployeeService
20:21:15,598 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-3) JNDI bindings for session bean named EmployeeService in deployment unit deployment "JPA_With_JAXRS_BASIC_Demo.war" are as follows:

	java:global/JPA_With_JAXRS_BASIC_Demo/EmployeeService!jpa.EmployeeServiceRemote
	java:app/JPA_With_JAXRS_BASIC_Demo/EmployeeService!jpa.EmployeeServiceRemote
	java:module/EmployeeService!jpa.EmployeeServiceRemote
	java:global/JPA_With_JAXRS_BASIC_Demo/EmployeeService
	java:app/JPA_With_JAXRS_BASIC_Demo/EmployeeService
	java:module/EmployeeService

20:21:15,617 INFO  [org.jboss.jpa] (MSC service thread 1-6) JBAS011402: Starting Persistence Unit Service 'JPA_With_JAXRS_BASIC_Demo.war#EmployeeService'
20:21:15,619 INFO  [org.hibernate.ejb.Ejb3Configuration] (MSC service thread 1-6) HHH000204: Processing PersistenceUnitInfo [
	name: EmployeeService
	...]
20:21:15,628 INFO  [org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator] (MSC service thread 1-6) HHH000130: Instantiating explicit connection provider: org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider
20:21:15,635 INFO  [org.hibernate.dialect.Dialect] (MSC service thread 1-6) HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
20:21:15,635 INFO  [org.hibernate.engine.jdbc.internal.LobCreatorBuilder] (MSC service thread 1-6) HHH000423: Disabling contextual LOB creation as JDBC driver reported JDBC version [3] less than 4
20:21:15,636 INFO  [org.hibernate.engine.transaction.internal.TransactionFactoryInitiator] (MSC service thread 1-6) HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jta.CMTTransactionFactory
20:21:15,636 INFO  [org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory] (MSC service thread 1-6) HHH000397: Using ASTQueryTranslatorFactory
20:21:15,643 INFO  [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6) HHH000227: Running hbm2ddl schema export
20:21:15,643 INFO  [stdout] (MSC service thread 1-6) Hibernate: drop table if exists Employee
20:21:15,645 INFO  [stdout] (MSC service thread 1-6) Hibernate: create table Employee (empno integer not null, ename varchar(255), primary key (empno))
20:21:15,768 INFO  [org.hibernate.tool.hbm2ddl.SchemaExport] (MSC service thread 1-6) HHH000230: Schema export complete
20:21:15,776 INFO  [org.jboss.web] (MSC service thread 1-4) registering web context: /JPA_With_JAXRS_BASIC_Demo
20:21:15,788 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS018559: Deployed "JPA_With_JAXRS_BASIC_Demo.war"

Step13). Now access the WebApplication like following :
http://localhost:8080/JPA_With_JAXRS_BASIC_Demo/

JPA_With_JAXRS


.
.
Thanks 🙂
Middleware Magic Team


Copyright © 2010-2012 Middleware Magic. All rights reserved. |