Saturday 29 October 2011

Create stateless session bean accessing database with JPA in Websphere 7

Create a Java project, named ‘ejb3-jpa’

Add runtime Websphere application server 7 to the build path


Under src, create a folder META-INF, under META-INF create persistence.xml


The contents of persistence.xml

<persistence 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_1_0.xsd"
             version="1.0">
    <persistence-unit name="unit">
        <jta-data-source>jdbc/derby</jta-data-source>
        <properties>
            <property name="openjpa.Log" value="SQL=TRACE"/>
            <property name="openjpa.jdbc.SynchronizeMappings"     
                  value="buildSchema"/>
            <property name="openjpa.jdbc.MappingDefaults" 
                  value="ForeignKeyDeleteAction=restrict, 
                     JoinForeignKeyDeleteAction=restrict"/>
        </properties>
    </persistence-unit>
</persistence>

jdbc/derby is the JNDI name for the datasource. It should be configured in Websphere application server already.

Openjpa.Log prints out the SQL. (Not working properly in WAS 7)

Openjpa.jdbc.synchronizeMappings creates the tables in the database if they don’t already exist.

openjpa.jdbc.MappingDefaults creates the foreign key constraints.

Create an entity bean: Person.java



package entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;


@Entity
@Table(name="T_PERSON")
public class Person{
    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "NAME")
    private String name;
    
    public Person() {
        super();
    }
    
    public Person(String name) {
        super();
        this.name = name;
    }
    
    public Person(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

Create a stateless session bean and its local interface: PersonManager.java and PersonManagerBean.java


package session;

import entity.Person;

public interface PersonManager {
    public void save(Person person);
}

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import entity.Person;

@Stateless
@Local(PersonManager.class)
public class PersonManagerBean 
    implements PersonManager {

    @PersistenceContext(unitName="unit")
    private EntityManager em;
    
    @Override
    public void save(Person person) {
        em.persist(person);
    }
}

Create a dynamic web project, named ‘ejb3-jpa-web’

Select ‘Websphere Application Server 7’ as the Target Runtime.


Include ‘ejb3-jpa’ project into the build path


Create a servlet: PersonServlet.java


package web;

import java.io.IOException;

import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import session.PersonManager;
import entity.Person;

public class PersonServlet extends HttpServlet {
    
    @EJB
    private PersonManager personManager;

    @Override
    protected void doGet(HttpServletRequest req, 
            HttpServletResponse resp)
            throws ServletException, IOException {
        personManager.save(new Person("Sun"));
    }
}

Define the servlet in web.xml

<servlet>
    <servlet-name>person</servlet-name>
    <servlet-class>web.PersonServlet</servlet-class>
</servlet>
    
<servlet-mapping>
    <servlet-name>person</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping>

Create an enterprise project, named ‘ejb3-ear’

Add ‘ejb3-jpa’ and ‘ejb3-jpa-web’ project into ‘ejb3-ear’

Add the ‘ejb3-ear’ project into the server, start the server


Right click on ‘WebSphere Application Server V7.0’, and click on ‘Properties’


Find out the port number

Go to http://localhost:PORT_NUMBER/ejb3-jpa-web/a.do

Replace PORT_NUMBER with the actual port number (i.e. 9084)

Check the database

Friday 28 October 2011

Three Ways to use an EJB

Define a stateless session bean

@Stateless(name="personBean")
@Local(PersonManager.class)
public class PersonManagerBean 
    implements PersonManager {

    @PersistenceContext(unitName="unit")
    private EntityManager em;
    
    @Override
    public void save(Person person) {
        em.persist(person);
    }
}

Way 1: Dependency Injection

@Stateless(name="dependencyInjectionService")
@Local(Ejb3Service.class)
public class Ejb3ServiceDependencyInjectionBean 
   implements Ejb3Service {

    @EJB(beanName="personBean")
    private PersonManager personManager;
    
    @Override
    public void savePerson(Person person) {
        personManager.save(person);
    }
}

beanName attribute (personBean) of @EJB annotation matches the name attribute of @Stateless annotation.

Way 2: Initial Context Look Up

@Stateless(name="initalContextService")
@Local(Ejb3Service.class)
@EJB(name="ejb/personManager", 
         beanInterface=PersonManager.class,
         beanName="personBean") 
public class Ejb3ServiceInitialContextBean 
    implements Ejb3Service {

    @Override
    public void savePerson(Person person) {
        PersonManager personManager = null;
        try {
            Context ctx = new InitialContext();
            personManager = (PersonManager)
                     ctx.lookup("java:comp/env/ejb/personManager");
        } catch (javax.naming.NamingException ne) {
            throw new EJBException(ne);
        }
        personManager.save(person);
    }
}

@EJB annotation at class level registers the EJB with the beanName (i.e. personBean) in the JNDI ENC. The name attribute specifies the logical name (i.e. ejb/personManager) of the EJB in the JNDI ENC. This logical name can be looked up by InitialContext. (prefixed with “java:comp/env”)

Way 3: EJB Context Look up

@Stateless(name="ejbContextService")
@Local(Ejb3Service.class)
@EJB(name="ejb/personManager", 
         beanInterface=PersonManager.class,
         beanName="personBean") 
public class Ejb3ServiceEjbContextBean 
    implements Ejb3Service {

    @Resource
    private EJBContext ejbContext;
    @Override
    public void savePerson(Person person) {
        PersonManager personManager = (PersonManager)
            ejbContext.lookup("ejb/personManager");
        personManager.save(person);
    }
}

With Ejb context lookup, the lookup string doesn’t need to be prefixed with “java:comp/env”

Now write a servlet to test

public class PersonServlet extends HttpServlet {
    
    @EJB(beanName="ejbContextService")
    private Ejb3Service service1;
    
    @EJB(beanName="initalContextService")
    private Ejb3Service service2;
    
    @EJB(beanName="dependencyInjectionService")
    private Ejb3Service service3;
    
    @Override
    protected void doGet(HttpServletRequest req, 
            HttpServletResponse resp)
            throws ServletException, IOException {
        service1.savePerson(new Person("Sun8"));
        service2.savePerson(new Person("Sun9"));
        service3.savePerson(new Person("Sun10"));
    }
}


Saturday 22 October 2011

Difference between Stateless and Stateful session bean

Define a stateless session bean and a stateful session bean. The only difference is the @stateless and @stateful annotation.

@Stateless(name="stateless")
@Local(Session.class)
public class StatelessSessionBean 
    implements Session {

    private int result;
    
    @Override
    public void add() {
        result++;
    }

    @Override
    public int get() {
        return result;
    }
}

@Stateful(name="stateful")
@Local(Session.class)
public class StatefulSessionBean 
    implements Session {

    private int result;
    
    @Override
    public void add() {
        result++;
    }

    @Override
    public int get() {
        return result;
    }
}

Write a servlet to test.

public class StatelessStatefulServlet 
    extends HttpServlet {

    @EJB(beanName="stateless")
    private Session stateless1;
    
    @EJB(beanName="stateless")
    private Session stateless2;
    
    @EJB(beanName="stateful")
    private Session stateful1;
    
    @EJB(beanName="stateful")
    private Session stateful2;
    
    @Override
    protected void doGet(HttpServletRequest req, 
        HttpServletResponse resp)
            throws ServletException, IOException {
        stateless1.add();
        System.out.println("Stateless1 result="+stateless1.get());
        stateless2.add();
        System.out.println("Stateless2 result="+stateless2.get());
        stateful1.add();
        System.out.println("Stateful1 result="+stateful1.get());
        stateful2.add();
        System.out.println("Stateful2 result="+stateful2.get());
    }
}

Output:

[18/08/11 11:49:22:828 EST] 0000001b SystemOut O Stateless1 result=1
[18/08/11 11:49:22:828 EST] 0000001b SystemOut O Stateless2 result=2
[18/08/11 11:49:22:828 EST] 0000001b SystemOut O Stateful1 result=1
[18/08/11 11:49:22:828 EST] 0000001b SystemOut O Stateful2 result=1

In this case, the same stateless session bean instance is used for both stateless1 and stateless2. The result is not predicable. Next time the output could be:

[18/08/11 11:49:22:828 EST] 0000001b SystemOut O Stateless1 result=1
[18/08/11 11:49:22:828 EST] 0000001b SystemOut O Stateless2 result=1

In this case, two different stateless session bean instances are picked up from the instance pool.

But the output for stateful session bean is always stable. Two different stateful session bean instances are always created.

Friday 21 October 2011

Develop and test a stateless session bean in MyEclipse 8.5

Create an EJB project in MyEclipse

There are two ways to do it.

1.

package session.bean;

public interface StatelessRemote {
    public String helloWorld();
}

package session.bean;

import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless(name="abc", mappedName="def")
@Remote(StatelessRemote.class)
public class StatelessBean 
    implements StatelessRemote {

    public String helloWorld() {
        return "Hello World";
    }

}

2.

package session.bean;

import javax.ejb.Remote;

@Remote
public interface StatelessRemote {
    public String helloWorld();
}

package session.bean;

import javax.ejb.Stateless;

@Stateless(name="abc", mappedName="def")
public class StatelessBean 
    implements StatelessRemote {

    public String helloWorld() {
        return "Hello World";
    }
}

Deploy the project into Glassfish 3.1 server

Ensure Glassfish is running, right click on GlassFish, and select 'Add Deployment'

Select the new created ejb project, click on 'Finish' button

The process is deployment is package the ejb project into a jar file, and copy that jar file to D:\glassfish3\glassfish\domains\domain1\autodeploy, (Assume the installation folder of Glassfish is D:\glassfish3\)

Check the JNDI name in the console.

The above 4 JNDI names can be used to find the statelessBean we just defined.

Create a Java project to test it.

public class Main {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception{
        Context ctx = new InitialContext();
        StatelessRemote bean = (StatelessRemote)
            ctx.lookup
            ("java:global/ejb/abc!session.bean.StatelessRemote");
        System.out.println(bean.helloWorld());
        bean = (StatelessRemote)ctx.lookup("java:global/ejb/abc");
        System.out.println(bean.helloWorld());
        bean = (StatelessRemote)
            ctx.lookup
            ("def#session.bean.StatelessRemote");
        System.out.println(bean.helloWorld());
        bean = (StatelessRemote)ctx.lookup("def");
        System.out.println(bean.helloWorld());
    }
}

The difference between name attribute and mappedName attribute is: The value of mappedName is unique in a server and it's not portable. (When you change to a different server, it may not work)

Friday 14 October 2011

Dependency Injection or Context Lookup a stateful session bean

First create a stateful session bean

@Stateful(name="stateful")
@Local(Session.class)
public class StatefulSessionBean 
    implements Session {

    private int result;
    
    @Override
    public void add() {
        result++;
    }

    @Override
    public int get() {
        return result;
    }
}

Then create a servlet to Dependency Inject the stateful session bean

public class StatefulDependencyInjectionServlet 
    extends HttpServlet {
   
    @EJB(beanName="stateful")
    private Session stateful;
    
    @Override
    protected void doGet(HttpServletRequest req, 
        HttpServletResponse resp)
            throws ServletException, IOException {
        HttpSession session = req.getSession(true);
        Session bean = (Session)session.getAttribute("stateful");
        if (bean == null){
            bean = this.stateful;
        }
        bean.add();
        System.out.println("Stateful: " + bean.get());
        session.setAttribute("stateful", bean);
        
    }
} 

Test the servlet several times and check the result

[24/08/11 14:30:00:234 EST] 00000016 SystemOut O Stateful: 1
[24/08/11 14:30:03:234 EST] 00000016 SystemOut O Stateful: 2
[24/08/11 14:30:06:203 EST] 00000016 SystemOut O Stateful: 3

It seems working fine. But if we close the browser, open it again and test the servlet several times, we will see:

[24/08/11 14:33:15:812 EST] 00000016 SystemOut O Stateful: 4
[24/08/11 14:33:16:718 EST] 00000016 SystemOut O Stateful: 5
[24/08/11 14:33:17:328 EST] 00000016 SystemOut O Stateful: 6

This behaviour is incorrect as when the browser is closed and reopened, it represents a new client, who should get a new instance of stateful session bean.

Now create another servlet to access the stateful session bean through Context Lookup.

@EJB(name="ejb/stateful", 
     beanInterface=Session.class, 
     beanName="stateful")
public class StatefulContextLookupServlet 
extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, 
        HttpServletResponse resp)
            throws ServletException, IOException {
        HttpSession session = req.getSession(true);
        Session stateful = (Session)session.getAttribute("stateful");
        if (stateful == null){
            try{
                Context ctx = new InitialContext();
                stateful = (Session)ctx.lookup
                    ("java:comp/env/ejb/stateful");
            }catch (Exception e) {
                throw new EJBException(e);
            }    
        }
        stateful.add();
        System.out.println("Stateful: "+stateful.get());
        session.setAttribute("stateful", stateful);
        
    }
}

Test the servlet several times and check the result

[24/08/11 14:38:42:250 EST] 00000016 SystemOut O Stateful: 1
[24/08/11 14:38:45:453 EST] 00000016 SystemOut O Stateful: 2
[24/08/11 14:38:46:000 EST] 00000016 SystemOut O Stateful: 3

Close the browser, open it again and test the servlet several times

[24/08/11 14:39:38:734 EST] 00000016 SystemOut O Stateful: 1
[24/08/11 14:39:39:796 EST] 00000016 SystemOut O Stateful: 2
[24/08/11 14:39:40:546 EST] 00000016 SystemOut O Stateful: 3

Now the behaviour is correct.

Configure Derby JDBC resource in WebSphere 7

Assume the URL for Derby connection is
jdbc:derby://localhost:1527/C:\Data\derbydb\mydb

Go to Websphere Application Server 7 Admin Console

Resources->JDBC->JDBC Providers



Click on 'New' button


Click on 'Next' button


Click on 'Finish' button



Click on 'Save'



Click on ‘Data sources’


Click on ‘New’


Click on ‘Next’


Click on ‘Next’


Click on ‘Next’


Click on ‘Next’


Click on ‘Finish’


Click on ‘Save’


Click on ‘Test connection’

This message means the configuration is successful.

Sunday 9 October 2011

A simple JSF 2.0 Web Application in MyEclipse 8.5

The project structure will look like:



Create a new Web Project in My Eclipse.


Add pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"      
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0     
    http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>jsf2</groupId>
    <artifactId>jsf2</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name />
    <description />
    <dependencies>
        <dependency>
            <groupId>org.apache.openejb</groupId>
            <artifactId>javaee-api</artifactId>
            <version>5.0-1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-api</artifactId>
            <version>2.1.0-b03</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.faces</groupId>
            <artifactId>jsf-impl</artifactId>
            <version>2.1.0-b03</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Run maven, mvn eclipse:eclipse clean install


Refresh the project.

Create a java class: HelloBean.java

package bean;

import java.io.Serializable;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="hello")
@SessionScoped
public class HelloBean implements Serializable {

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

    public String getName() {
        return name;
    }

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

Create hello.xhtml and welcome.xhtml under src/main/webapp

hello.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head>
        <title>JSF 2.0 Hello World</title>
    </h:head>
    <h:body>
        <h3>JSF 2.0 Hello World Example - hello.xhtml</h3>
        <h:form>
            <h:inputText value="#{hello.name}"></h:inputText>
            <h:commandButton value="Welcome Me" action="welcome" />
        </h:form>
    </h:body>
</html>

welcome.xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"      
      xmlns:h="http://java.sun.com/jsf/html">
    
    <h:head>
        <title>JSF 2.0 Hello World</title>
    </h:head>
    <h:body bgcolor="white">
        <h3>JSF 2.0 Hello World Example - welcome.xhtml</h3>
        <h4>Welcome #{hello.name}</h4>
    </h:body>
</html>

Deploy the application into Glassfish 3.1

Test http://localhost:8080/jsf2/hello.faces


Result

Monday 3 October 2011

Derby installation

Download the latest derby release from http://db.apache.org/derby/

Unzip the downloaded zip file to c:\Java

In the command line, go to the lib folder under extracted derby folder. e.g.

cd C:\Java\db-derby-10.9.1.0-bin\lib

Start the derby server by

java -jar derbynet.jar start










Open another command line window, go to the folder in which you will create the derby database

e.g. cd C:\derbydb

Connect the derby server with the ij derby tool

java -jar C:\Java\db-derby-10.9.1.0-bin\lib\derbyrun.jar ij




Create the database named ‘mydb’

CONNECT 'jdbc:derby://localhost:1527/c:\derbydb\mydb;create=true';




create table STUDENT (stuid int, name varchar(10));
insert into STUDENT values (1, 'Wang');






exit;





Test the connection in Squirrel




Note: User Name and Password can be anything but empty.