Showing posts with label jpa. Show all posts
Showing posts with label jpa. Show all posts

Developing JPA application for use in WebSphere

In the Developing JPA application for use in Java SE entry i blogged about how to develop a simple JPA application using RAD and execute it outside the application server. But the more common use case for JPA would be how to use it inside Application Server.

I wanted to learn how to develop an JPA application that runs inside WebSphere Application Server so i build this simple HelloJPA1Portlet application which is essentially same as that of the HelloJPA1 application that i built in the In the Developing JPA application for use in Java SE , with difference that this one runs inside in application container.

Follow these steps to add support for JPA inside a portlet

  1. First create a HelloJPA1Portlet in RAD and deploy it in the WPS 7.0. Once the basic thing is working you can right click on the project and click on Properties. Select Project Facets like this

    Select JPA and version 1.0

  2. Next configure a JDBC Datasource connecting to the same database that we used in the last project and use jdbc/hellojpa as the JNDI name for the data source make sure the database actually works


  3. Follow the same steps that i mentioned in Developing JPA application for use in Java SE for generating entities accessing Customer table or you might want to simply copy the code from there.

  4. One step that is different is change persistence.xml to use the data source configured at jdbc/hellojpa JNDI location instead of directly connecting to database. You can do that by right clicking on project and then selecting JPA Tools -< Configure project for JDBC Deployment


    As you can see i am using the JNDI name of the data source instead of database properties

  5. When you click on the Finish button, your persistence.xml file will get updated to look like this

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.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_1_0.xsd">
    <persistence-unit name="HelloJPA1" >
    <jta-data-source>jdbc/hellojpa</jta-data-source>
    <class>com.webspherenotes.jpa.Customer</class>
    <properties>
    <property name="openjpa.jdbc.Schema" value="ADMIN"/>
    </properties>
    </persistence-unit>
    </persistence>


  6. Your portlet code would be same as that of the standalone client like this

    package com.webspherenotes.jpa;

    import java.io.*;
    import java.util.List;

    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.portlet.*;

    import com.webspherenotes.jpa.controller.CustomerManager;

    /**
    * A sample portlet
    */
    public class HelloJPA1Portlet extends javax.portlet.GenericPortlet {
    /**
    * @see javax.portlet.Portlet#init()
    */
    public void init() throws PortletException{
    super.init();
    }

    /**
    * Serve up the view mode.
    *
    * @see javax.portlet.GenericPortlet#doView(javax.portlet.RenderRequest,
    javax.portlet.RenderResponse)
    */
    public void doView(RenderRequest request, RenderResponse response)
    throws PortletException, IOException {
    // Set the MIME type for the render response
    response.setContentType(request.getResponseContentType());

    EntityManagerFactory entityManagerFactory = Persistence
    .createEntityManagerFactory("HelloJPA1");
    CustomerManager manager = new CustomerManager(entityManagerFactory);

    List customerList = manager.getCustomers();
    for(Customer c : customerList){
    System.out.println(c);
    }

    super.getPortletContext().getRequestDispatcher("/index.jsp").include(request, response);

    }
    }




Now when you try to access the portlet you should be able to see list of customers being printed in the SystemOut.log file

Developing JPA application for use in Java SE

These are the steps that i followed to create a JPA project using Rational Application Developer 8.0 and executing it. I am executing this project outside application server. In the next entry i will blog about how to use JPA in J2EE application running inside the WebSphere Application Server.

I am assuming that you already have a CUSTOMER table in your database and now you want to use JPA to work with that table. If you dont have Customer table you can use this DDL to create it

CREATE TABLE CUSTOMER (
CUST_ID INTEGER NOT NULL ,
FIRST_NAME VARCHAR(50) NOT NULL,
LAST_NAME VARCHAR(50),
STREET VARCHAR(50),
APPT VARCHAR(20),
CITY VARCHAR(25),
ZIP_CODE VARCHAR(10) NOT NULL,
CUST_TYPE VARCHAR(10) NOT NULL ,
WEBSITE VARCHAR(100),
LAST_UPDATED_TIME TIMESTAMP
);


ALTER TABLE CUSTOMER ADD CONSTRAINT CUSTOMER_PK Primary Key (CUST_ID);

Follow these steps to create JPA project and execute it.

  1. Open RAD and click on Create new Project -< JPA -< JPA Project. On the next screen enter HelloJPA as project name and click on next next. Make sure to select value of Configuration to Minimal JPA 1.0 Configuration


  2. Next on the JPA Facet dialog box, you can select the existing database connection that you have in RAD. In my case i dont have the connection to the Apache Derby Sample database configured so i need to click on Add Connection


  3. Use the steps provided in Accessing Database using Eclipse/ Rational Application Developer for configuring connection to the database

  4. Once your database connection is configured it will bring you back to the Create JPA Project screen like this, In my case name of the connection that i just configured is "New Connection"


  5. With this your JPA project will be ready, the project generated by RAD does not have anything but the persistence.xml.

  6. In my case i already have a database table that i want to interact with. Now i want to generate JPA code for working with project. So right click on the project and click on JPA Tools -< Generate Entities from table. It will open a dialog box like this. As you can see the New Connection is selected in the Connection select box and you can see the tables in that database. I am only interested in CUSTOMER table so select it.


  7. On the next screen it will ask you few more options for generating entity. Change value of Key Generation to auto and change package name to com.webspherenotes.jpa and click next


  8. In the last screen it will ask you for some information related to customer table things like what should be name of the entity class,.. Keep default values like this


  9. If you look at the HelloJPA project you will notice that RAD has generated a Customer.java class which is entity class (Java object representing Customer table) like this

    'package com.webspherenotes.jpa;

    import java.io.Serializable;
    import javax.persistence.*;
    import java.sql.Timestamp;

    /**
    * The persistent class for the CUSTOMER database table.
    *
    */
    @Entity
    public class Customer implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "CUST_ID")
    private int custId;

    private String appt;

    private String city;

    @Column(name = "CUST_TYPE")
    private String custType;

    @Column(name = "FIRST_NAME")
    private String firstName;

    @Column(name = "LAST_NAME")
    private String lastName;

    @Column(name = "LAST_UPDATED_TIME")
    private Timestamp lastUpdatedTime;

    private String street;

    private String website;

    @Column(name = "ZIP_CODE")
    private String zipCode;

    public Customer() {
    }

    public int getCustId() {
    return this.custId;
    }

    public void setCustId(int custId) {
    this.custId = custId;
    }

    public String getAppt() {
    return this.appt;
    }

    public void setAppt(String appt) {
    this.appt = appt;
    }

    public String getCity() {
    return this.city;
    }

    public void setCity(String city) {
    this.city = city;
    }

    public String getCustType() {
    return this.custType;
    }

    public void setCustType(String custType) {
    this.custType = custType;
    }

    public String getFirstName() {
    return this.firstName;
    }

    public void setFirstName(String firstName) {
    this.firstName = firstName;
    }

    public String getLastName() {
    return this.lastName;
    }

    public void setLastName(String lastName) {
    this.lastName = lastName;
    }

    public Timestamp getLastUpdatedTime() {
    return this.lastUpdatedTime;
    }

    public void setLastUpdatedTime(Timestamp lastUpdatedTime) {
    this.lastUpdatedTime = lastUpdatedTime;
    }

    public String getStreet() {
    return this.street;
    }

    public void setStreet(String street) {
    this.street = street;
    }

    public String getWebsite() {
    return this.website;
    }

    public void setWebsite(String website) {
    this.website = website;
    }

    public String getZipCode() {
    return this.zipCode;
    }

    public void setZipCode(String zipCode) {
    this.zipCode = zipCode;
    }

    public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append("custId : " + custId);
    sb.append(" First Name : " + firstName);
    sb.append(" Last Name : " + lastName);
    sb.append(" customer type : " + custType);

    return sb.toString();
    }
    }

    I copied the toString() method. You can also get RAD to generate the toString() method for you

  10. Now next step will be to configure database connection properties. For that right click on the HelloJPA project say JPA tools -< Configure Project for JDBC Deployment and select "Set Connection Directly Via properties" radio box. This will copy the connection properties that you used for connecting to DB inside your persistence.xml file like this

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="1.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_1_0.xsd">
    <persistence-unit name="HelloJPA1">
    <class>com.webspherenotes.jpa.Customer</class>
    <properties>
    <property name="openjpa.ConnectionDriverName"
    value="org.apache.derby.jdbc.ClientDriver"/>
    <property name="openjpa.ConnectionURL"
    value="jdbc:derby://localhost:1527/C:/work/webspherenotes/db;create=true"/>
    <property name="openjpa.ConnectionUserName" value="admin"/>
    <property name="openjpa.ConnectionPassword" value="admin"/>
    </properties>
    </persistence-unit>
    </persistence>


  11. Now your JPA code is ready you can use it directly. But you can also ask RAD to create Managed Bean which will generate basic JPA methods for performing CRUD operation on the table. FOr that right click on the HelloJPA project -< JPA Tools -< Add JPA Managed Beans it will open a screen like this

    This list the entities in your project. In my case i have only Customer table so select that and click on next.

  12. Here it will allow you to create few more methods like this


  13. Once you click on finish the RAD will generate CustomerManager.java class like this

    package com.webspherenotes.jpa.controller;

    import java.util.List;

    import com.ibm.jpa.web.JPAManager;
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Query;

    import com.ibm.jpa.web.Action;
    import com.webspherenotes.jpa.Customer;

    @SuppressWarnings("unchecked")
    @JPAManager(targetEntity = com.webspherenotes.jpa.Customer.class)
    public class CustomerManager {

    private EntityManagerFactory emf;

    public CustomerManager() {

    }

    public CustomerManager(EntityManagerFactory emf) {
    this.emf = emf;
    }

    public void setEntityManagerFactory(EntityManagerFactory emf) {
    this.emf = emf;
    }

    private EntityManager getEntityManager() {
    if (emf == null) {
    throw new RuntimeException(
    "The EntityManagerFactory is null.
    This must be passed in to the constructor or
    set using the setEntityManagerFactory() method.");
    }
    return emf.createEntityManager();
    }

    @Action(Action.ACTION_TYPE.CREATE)
    public String createCustomer(Customer customer) throws Exception {
    EntityManager em = getEntityManager();
    try {
    em.getTransaction().begin();
    em.persist(customer);
    em.getTransaction().commit();
    } catch (Exception ex) {
    try {
    if (em.getTransaction().isActive()) {
    em.getTransaction().rollback();
    }
    } catch (Exception e) {
    ex.printStackTrace();
    throw e;
    }
    throw ex;
    } finally {
    em.close();
    }
    return "";
    }

    @Action(Action.ACTION_TYPE.DELETE)
    public String deleteCustomer(Customer customer) throws Exception {
    EntityManager em = getEntityManager();
    try {
    em.getTransaction().begin();
    customer = em.merge(customer);
    em.remove(customer);
    em.getTransaction().commit();
    } catch (Exception ex) {
    try {
    if (em.getTransaction().isActive()) {
    em.getTransaction().rollback();
    }
    } catch (Exception e) {
    ex.printStackTrace();
    throw e;
    }
    throw ex;
    } finally {
    em.close();
    }
    return "";
    }

    @Action(Action.ACTION_TYPE.UPDATE)
    public String updateCustomer(Customer customer) throws Exception {
    EntityManager em = getEntityManager();
    try {
    em.getTransaction().begin();
    customer = em.merge(customer);
    em.getTransaction().commit();
    } catch (Exception ex) {
    try {
    if (em.getTransaction().isActive()) {
    em.getTransaction().rollback();
    }
    } catch (Exception e) {
    ex.printStackTrace();
    throw e;
    }
    throw ex;
    } finally {
    em.close();
    }
    return "";
    }

    @Action(Action.ACTION_TYPE.FIND)
    public Customer findCustomerByCustId(int custId) {
    Customer customer = null;
    EntityManager em = getEntityManager();
    try {
    customer = (Customer) em.find(Customer.class, custId);
    } finally {
    em.close();
    }
    return customer;
    }

    public List getAllCustomers(){
    List customerList = null;
    EntityManager em = getEntityManager();
    try {
    Query q= em.createQuery("SELECT x from Customer x");
    customerList =(List)q.getResultList();
    System.out.println(customerList.size());
    } finally {
    em.close();
    }
    return customerList;
    }

    @Action(Action.ACTION_TYPE.NEW)
    public Customer getNewCustomer() {

    Customer customer = new Customer();

    return customer;
    }

    }


  14. Now you want to create your own class to test your JPA configuration so create a CustomerTest.java class like this

    package com.webspherenotes.jpa;

    import java.util.List;

    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;

    import com.webspherenotes.jpa.controller.CustomerManager;

    public class CustomerTest {

    /**
    * @param args
    */
    public static void main(String[] args) {
    try {
    EntityManagerFactory entityManagerFactory = Persistence
    .createEntityManagerFactory("HelloJPA1");

    CustomerManager manager = new CustomerManager(entityManagerFactory);
    Customer customer = new Customer();
    customer.setFirstName("James");
    customer.setLastName("Bond");
    customer.setStreet("845 JB Ave");
    customer.setAppt("153");
    customer.setCity("JBCity");
    customer.setZipCode("007");
    customer.setCustType("test");
    customer.setWebsite("http://www.webspherenotes.com");
    manager.createCustomer(customer);

    System.out.println("Customer with id 1 " + manager.findCustomerByCustId(0));

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

    }

    }

    In this class i am using JPA code to get the EntityManagerFactory but after that i am delegating control to CustomerManager for creating new record in CUSTOMER table

  15. Since we want to execute this code outside application server we will have to make one change, At the runtime you will have to make one configuration change which is to set the value of javaagent to the JPA implementation provided by WebSphere Application server like this
    -javaagent:C:/IBM/WebSphere/AppServer/runtimes/com.ibm.ws.jpa.thinclient_7.0.0.jar


Java Persisence API in WebSphere

Starting from J2EE 5, the Java Persistence API is part of the J2EE specification. The basic idea is you develop data access application by creating POJO classes like Hibernate and then the container specific implementation takes care of interacting with the database.

The WebSphere Application Server V7.0 has support for JPA (I believe JPA 1.0) and i remember reading that WebSphere Application Server V8.0 supports JPA 2.0 and also provides second level caching. Since IBM will provide as well as support JPA i think WebSphere customer's might move towards it so i started spending some time learning about it and i am planning to blog about my experiences with JPA

The Rational Application Developer has support for developing JPA applications. You can execute JPA applications both inside and outside the container.