Wednesday, August 29, 2012

Spring Framework with Hibernate JPA - ApplicationContext


Continued from Spring Framework with Hibernate JPA

Notice the property variables in the ApplicationContext.xml.
Notice the bean specifying the location of configuration.properties file whose property definitions can be used for substitution into the ApplicationContext.xml file.

ApplicationContext.xml


configuration.properties file
zzz.rambutan.driver=oracle.jdbc.driver.OracleDriver
zzz.rambutan.url=jdbc:oracle:thin:@holymoly.kacang.putty
zzz.rambutan.user=durian
zzz.rambutan.password=langsat
zzz.rambutan.hibernate.dialect=org.hibernate.dialect.OracleDialect
zzz.rambutan.hibernate.showSql=true

To be continued ....

Spring Framework with Hibernate JPA

The few articles prior to this discussed the conjunctive use of
  • GWT as REST client
  • JAX-RS REST service
  • JPA2
  • A POJO data transfer schema shared across the three frameworks

This article furthers the conjunction by including the deployment of Spring Framework. Therefore, the technology conjunctivitis now comprises
  • GWT
  • RestyGWT
  • RestEasy
  • Hibernate 3.x in JPA 2.x mode
  • Spring Framework's inversion of control to configure Hibernate.
Reason for Spring Framework
The reason for including Spring Framework is to exploit its ability to turn away from Hibernate's persistence.xml hard-coded values towards Spring's ability to make the persistence definition agile and adaptive. I should have used the term "dynamic" definition rather than agile/adaptive. 

However, being dynamic would mean we would change those configuration in the middle of playing the game. Not so, we only want to adaptively define those values during application loading. We want to place variables in Hibernate connectivity that are resolved during application loading.

So that we do not have to manually, or write an application within an application to, modify persistence.xml hard-coded values when deploying the app across disparate systems.

The issue at hand is
how to use Spring Framework to configure Hibernate as a JPA 2.x provider.

The usual persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<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="obamacare"
      transaction-type="RESOURCE_LOCAL">
    <provider>
      org.hibernate.ejb.HibernatePersistence
    </provider>
    <exclude-unlisted-classes>
      false
    </exclude-unlisted-classes>
    <!-- Scan for annotated classes and Hibernate mapping XML files -->
    <properties>
      <property name="hibernate.archive.autodetection"
        value="class, hbm"/>
      <property name="javax.persistence.jdbc.driver"
        value="oracle.jdbc.driver.OracleDriver"/>
      <property name="javax.persistence.jdbc.url"
        value="jdbc:oracle:thin:@holymoly.kacang.putty"/>
      <property name="javax.persistence.jdbc.user"
        value="durian"/>
      <property name="javax.persistence.jdbc.password"
        value="langsat"/>
      <property name="hibernate.dialect"
        value="org.hibernate.dialect.OracleDialect"/>
     <property name="hibernate.show_sql"
        value="true"/>
    </properties>
  </persistence-unit>
</persistence>

The goal is to conceptually be able to do this:
    <properties>
      <property name="hibernate.archive.autodetection"
        value="class, hbm"/>
      <property name="javax.persistence.jdbc.driver"
        value="${zzz.rambutan.driver}"/>
      <property name="javax.persistence.jdbc.url"
        value="${zzz.rambutan.url}"/>
      <property name="javax.persistence.jdbc.user"
        value="${zzz.rambutan.user}"/>
      <property name="javax.persistence.jdbc.password"
        value="${zzz.rambutan.password}"/>
      <property name="hibernate.dialect"
        value="${zzz.rambutan.hibernate.dialect}"/>
     <property name="hibernate.show_sql"
        value="${zzz.rambutan.isDebug}"/>
    </properties>

However, neither JPA nor Hibernate is able to accept variables in the persistence.xml file. Therefore, we would have to depend on Spring's ApplicationContext.xml ability to accept variables.

Tuesday, July 17, 2012

GWT with JAX-RS (and JPA) Part 3

Come unto me all ye who are weary of heavy-laden clients and I will give you REST.

Continued from GWT with JAX-RS (aka RPC/REST) Part 2
OK, the cast of the technology mix is
  • JAX-RS (either Resteasy or Jersey on the server side)
  • JAX-RS + GWT = RestyGWT on the client-side
  • JPA on the server-side
  • JAXB over JAX-RS on both GWT client and server-side.
  • Jackson JSON processor on server-side.

I feel those acronyms are intimidating, but they are actually not difficult to implement. If you could understand the intricacies of GWT-RPC, you should have no problem understanding the soup mix above.

JPA remains to be the most difficult part of the mix to learn/master (most difficult but not difficult). Mastering GWT is actually the more difficult part than JPA. However, if you have no desire for your server to connect to a JDBC-enabled database, you do not need to concern with JPA.

This is your JAX-RS POJO:
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement (name="employee")
    public class Employee
    implements Serializable {
      @XmlAttribute
      private Long eid = null;
      @XmlAttribute
      private String name = null;
    }
This is the same POJO, if your app is obsessed with the order of appearance:
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement (name="employee")
    @XmlType(propOrder = {
      "eid",
      "name"
    }
    public class Employee implements Serializable {
      @XmlAttribute
      private Long eid = null;
      @XmlAttribute
      private String name = null;
    }
This is the POJO with public getters/setters (generated by Eclipse) so to enable RestyGWT to operate on it. Hoever, RestyGWT would not need the public getters/setters if the fields are public instead of private.
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement (name="employee")
    @XmlType(propOrder = {
      "eid",
      "name"
    }
    public class Employee
    implements Serializable {
      @XmlAttribute
      private Long eid = null;
      @XmlAttribute
      private String name = null;
    
      public Long getEid() {
        return eid;
      }
      public void setEid (Long  eid ) {
        this. eid = eid ;
      }
      public String getName () {
        return  name ;
      }
    
      public void setName (String  name ) {
        this. name = name ;
      }
    }
And finally, this is your Three-in-one POJO to accommodate JPA.
    @Entity
    @Table(name="Employee", schema="bombay")
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlRootElement (name="employee")
    @XmlType(propOrder = {
      "eid",
      "name"
    }
    public class Employee
    implements Serializable {
      @XmlAttribute
      @Id
      private Long eid = null;
      @XmlAttribute
      private String name = null;
    
      public Long getEid() {
        return eid;
      }
      public void setEid (Long  eid ) {
        this. eid = eid ;
      }
      public String getName () {
        return  name ;
      }
      public void setName (String  name ) {
        this. name = name ;
      }
    }
Let's create another POJO:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement (name="employees")
public class EmployeeList {

  @XmlElement(name="enployee")
 private List<Employee> employees;
 
 public List<Employee> getEmployees() {
  if (employees==null)
   employees = new ArrayList<Employee>();
  
  return employees;
 }

 public void setEmployees(List<Employee> employees) {
  this.employees = employees;
 }
}
But, WHERE's THE JSON? JSON output will be borrowing the JAXB XML annotation. The following is the server side service API interface.
    @Path("/employee")
    @Produces({"application/xml", "application/json"})
    public interface EmployeeServiceAPI {
       /**
       * Find all employee ids with the given name
       */
      @GET
      @Path("/eids/name")
      LongList getEmployeeIdsWithName(@QueryParam ("name")String name) ;
      
      
      /**
       * Get employee wit Id
       */
      @GET
      @Path("/employee/{id}")
      Employee getEmployeeWithId(@PathParam ("eid")Long eid) ;
      
      /**
       * Get project list for an employee
       */
      @POST
      @Path("/projects/employee")
      ProjectList getProjects(Employee employee) ;
    }
And this is the async service API on the GWT Client.
    @Path("/employee")
    @Consumes({"application/json"}) // put in a http header to tell server to return me JSON
    public interface EmployeeServiceAPI {
      
      /**
       * Find all employee ids with the given name
       */
      @GET
      @Path("/eids/name")
      LongList getEmployeeIdsWithName(@QueryParam ("name")String name, MethodCallback  <LongList  > callback) ;
      
      /**
       * Get employee wit Id
       */
      @GET
      @Path("/employee/{id}")
      Employee getEmployeeWithId(@PathParam ("eid")Long eid, MethodCallback  <Employee  > callback) ;
      
      /**
       * Get project list for an employee
       */
      @POST
      @Path("/projects/employee")
      ProjectList getProjects(Employee employee, MethodCallback  <ProjectList  > callback) ;
    }
The server-side implementation to access the database.
    public class EmployeeServiceAPIImpl
    implements EmployeeServiceAPI {
      
      @Override
      public Employee getEmployeeIdsWithName(Long eid) {
        Employee emp = new Employee();
        
        EntityManager em = null;
        try {
          em = EMF.get().createEntityManager();
          Query q = em.createQuery(
            "SELECT n FROM Employee n WHERE n.status = 'active' AND n.eid = ?1"
          ).setParameter(1, eid);
    
          Employee emp = q.getSingleResult();
          return emp;
        }
        
        finally{
          if (em!=null)
            em.close();
        }
      }
    
      ......
    }
This is how your GWT client will call the async REST service:
  public class EmployeePresenter{

    static public EmployeeAsyncServiceAPI enpServiceAPI = GWT.create(EmployeeAsyncServiceAPI.class);
    
    public void search(Long eid) {
      enpServiceAPI.getEmployeeIdsWithName(eid, new EmployeeCallBack());
    }

    public class EmployeeCallBack
    implements MethodCallback{

      @Override
      public void onFailure(Method method, Throwable exception) {
        Window.alert("Error accessing data");
      }

      @Override
      public void onSuccess(Method method, Employee response) {
        EmployeePresenter.this.view.setEmployeeRecords(
          response.getEmployee());
        if (response.getEmployee().size()==0) {
          Window.alert("No records found");
        }
      }
    }
  }
Let's say function search(Long eid) got called as
  search(12529);
RestyGWT code generated by GWT.create() will send this request over the URL
/employee/employee/12529
RestyGWT would find the phrase in the async service API
  @Consumes({"application/json"})
and proceeds to place a header in the HTTP request
  Accepts: application/json
When the RestEasy Listener intercepts the request, it would search for the class implementing EmployeeServiceAPI and finds EmployeeServiceAPIImpl. RestEasy loads that class which proceeds to service the request.

Therefore, you could use the browser to debug your web service independent of the GWT client.

You could use python or PHP to poke the server too. May be, your QA hates Java and loves PHP - so he/she could write unit tests using PHP.

Furthermore, now, you do not have to bother with SmartGWT XML or JSON datasource and you can take full control over your POJO datasource. It's really frustrating to have to take lots of time going thro nooks and corners whenever you need to tweak your datasource a lil' bit. Now you don't have to.

Here is your web.xml to tell RestEasy to do its strut.
<web-app>
  <display-name>Employee Service</display-name>

  <!-- Auto scan REST service -->
  <context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
  </context-param>

  <!-- this need same with resteasy servlet url-pattern -->
  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/CurryMuttonOilDrilling/</param-value>
  </context-param>

  <listener>
    <listener-class>
      org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
    </listener-class>
  </listener>

  <servlet>
    <servlet-name>resteasy-servlet</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>resteasy-servlet</servlet-name>
    <url-pattern>/CurryMuttonOilDrilling/*</url-pattern>
  </servlet-mapping>

</web-app>

Therefore, according to the web.xml, the actual URL path sent to the server is:


/CurryMuttonOilDrilling/employee/employee/12529

And notice the presence of Jackson json provider in the following maven dependency?
  <properties>
    <resteasy.version>2.3.4.Final</resteasy.version>
    <gwt.version>2.4.0</gwt.version>
  </properties>

  <repositories>
    <repository>
      <id>fusesource-snapshots</id>
      <name>Fusesource Snapshots</name>
      <url>http://repo.fusesource.com/nexus/content/repositories/snapshots</url>
      <snapshots><enabled>true</enabled></snapshots>
      <releases><enabled>false</enabled></releases>
    </repository>    
  </repositories>
  
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.10</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>javax.validation</groupId>
      <artifactId>validation-api</artifactId>
      <version>1.0.0.GA</version>
    </dependency>
    <dependency>
      <groupId>com.google.gwt</groupId>
      <artifactId>gwt-user</artifactId>
      <version>${gwt.version}</version>
    </dependency>
    <dependency>
        <groupId>com.sencha.gxt</groupId>
        <artifactId>gxt</artifactId>
        <version>2.2.5-gwt22</version>
        <scope>system</scope>
        <systemPath>${project.basedir}/lib/GWT/gxt-2.2.5-gwt22.jar</systemPath>
    </dependency>
    <dependency>
      <groupId>com.googlecode.mvp4g</groupId>
      <artifactId>mvp4g</artifactId>
      <version>1.4.0</version>
    </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jaxrs</artifactId>
      <version>${resteasy.version}</version>
      <type>jar</type>
    </dependency>
    <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>resteasy-jaxb-provider</artifactId>
      <version>${resteasy.version}</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson-provider</artifactId>
        <version>${resteasy.version}</version>
    </dependency>
    <dependency>
      <groupId>org.fusesource.restygwt</groupId>
      <artifactId>restygwt</artifactId>
      <version>1.3-SNAPSHOT</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.6.10.Final</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>4.3.0.Final</version>
    </dependency>
    
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava-gwt</artifactId>
      <version>13.0-rc1</version>
    </dependency>
            <!--dependency> <groupId>com.sun.faces</groupId> <artifactId>mojarra-jsf-api</artifactId> 
      <version>2.0.0-b04</version> </dependency> <dependency> <groupId>com.sun.faces</groupId> 
      <artifactId>mojarra-jsf-impl</artifactId> <version>2.0.0-b04</version> </dependency -->

Monday, January 2, 2012

GWT with JAX-RS (aka RPC/REST) Part 2


Come unto me all ye who are weary of heavy-laden clients and I will give you REST.

Continued from GWT with JAX-RS (aka RPC/REST) Part 1


We define the lower level REST API on an interface commonly shared between the client and server. We should consider the REST API as the lower level API, while considering the plain old Java object API (POJO-API) as the higher level API. For the purpose being lazy, I would like to use the acronym POJO-API henceforth.

Since the Java interface of the REST API is shared, both client and server share the same javadoc and json object documentation.

For example, in the interface declaration:

@Path("/hello/info")
interface RemoteCall{
  @Path ("/services/greet")
  @POST
  Person getGreeting(String userName, Message msg );
}

The client invokes the call by
Person veraswamy = getGreeting(String userName, Message msg );

The server listens for the path signature of `/hello/info/services/greet` and maps it to executing the mapped POJO-API by obtaining an instance of RemoteCall from the jax-rs-ware:

remotecalls.getGreeting(String userName, Message msg );

The server-side jax-rs-ware executes the impl of the method and returns Person as a response. The client-side of the jax-rs-ware decodes the response and the variable obama is assigned the value of Person as executed on the server-side.

See -no hands-

The programmer consuming the Java API is oblivious to the underlying REST API, but simply uses the POJO methods with a purely RPC attitude. Meanwhile, the REST API is designed by the developer providing the API, who would need to ensure uniqueness of the polymorphic signature of the API.

For async calls, we run a simple text utility script over the interface methods to produce the reciprocal async-client interface. So that the getGreeting method becomes

interface AsyncRemoteCall{
  @Path ("/services/greet")
  @POST
  void getGreeting(String userName, Message msg, CallBack<person> callback );
}

So, not only do the client and server share the interface, they also share the POJO DTOs, as long as the DTOs are serializable.

This is not exactly json-rpc as JSON-RPC has usually been done. But, this is RPC nonetheless. And the POJOs are carried as JSON over the wire. OTH, this is also a form of XML-RPC over JAX-RS, because we can switch the codec from JSON to XML. In fact, we can mix both XML-RPC and JSON-RPC together on the same server, using REST as the transport. May be, what I am doing should be called JSON-RPC (or XML-RPC) over REST-RPC.

I can say that my implementation of JSON-RPC over JAX_RS allows me to share the same set of POJO interfaces, DTO and documentation between client and server.

I could run enunciate over the interface to obtain the json object documentation (or the XML-schema). So, if you choose to, you could use PHP on the server side servicing the remote procedure call.