Tuesday, November 9, 2010

End of Java EE 6 show

Since last 2 days I have had lot of issues integrating JPA2 with my SLSB. Some of these are attributed to my new learning curve in Java EE 6. However with my quick exploration in last few days I can safely say that there are still serious holes in Java EE 6 world. It is slim trim and good for rapid development (unless you are on some unstable open source server) but lacks full power to drive a highly customizable and external configuration driven flexible application. These are some of my observations:

  1. Open source servers – Geronimo 3 and JBOSS 6 not yet ready. JBOSS 6 is still better. Guys for better adoption of open source we need documentation. Open source product and closed documentation will not promote this good products.
  2. Directly injecting persistence unit / entity manager results in severe cross cutting concerns. I take back my earlier word, although speed of development is important, good design goes a long way in maintenance. After writing some code in my session bean with JPA I was sad myself.
  3. Java EE 6 will not suffice if you need to build and app with good number of external configuration properties.
  4. Security – although I did not try much, but looks like is not as strong in terms of features that Spring security provides – especially easy integration with directory servers or SSO systems.
  5. If I want to clean up my session beans by moving data access code to a DAO, then I would have to build a factory to inject it. Ah Spring does a better job here. Does Java EE 6 promote code smell? I guess YES.
  6. I was feeling the need for those template classes when writing direct JPA code with entity manager.
  7. I had problems using the POSTGRES data source configured using JBOSS 6 console. The persistence unit could never connect. Finally I had to resort to old days of copy+paste the xml in the deploy directory.

Final conclusion

I am rolling back to stick to Spring 3 on Tomcat 6/7 with Primefaces and Hibernate or my home grown data mapper. I will also use JQUERY UI and JQUERY Mobile if my requirements are that way. I may consider JBOSS 5 / 6 if  there is need for JMS / MQ and there is multiple resource managers calling for JTA. But all core will be Spring. I think lot of dust has to settle over Java EE 6, even then it will still take lot of time to match the pluggability, flexibility and wide coverage of Spring with other good frameworks.

Next focus will on my own simple data mapper. I will put it on source forge.

Sunday, November 7, 2010

Adding and injecting the EJB3 session bean

In the last post the managed bean was creating the data. As a good practice the get method should never ideally do load from database or do complex time consuming operations. Its time to move the data retrieval code to a session bean( subsequently use JPA) method. In Java EE 6 it is no longer required to put the ejbs in jar files with tons of deployment descriptors. The ear file is no longer mandatory in Java EE 6. You can put your EJBs in the same war file as the web components. Ah! life is so easy and simple.
The stateless session beans(SLSB) are POJOs and can be marked as SLSB with the @Stateless annotation. Things are even easier with EJB 3.1. You no longer require the business interface. Just a concrete class will do. Although program to interface is a great principle, but for simplicity, speed of development and ease of maintenance I will stick to the new ways. The purists may frown but I cannot think when I changed an implementation midway or in later stages of a project for whatever reason in my entire career. When we select a technology stack we need to build competency and stick to it rather than continuing to chop and change.
Listing 1 shows the simple stateless session bean.
Listing 1 – ProductService.java
package com.windowshop.business;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.Stateless;

import com.windowshop.domain.entities.Product;

/**
* @author Dhrubo
*
*/
@Stateless
public class ProductService {

public List getProductsByMonth(){
System.out.println("Hurray!!!!! SLSB called");
//TODO - use JPA to fetch from db
List products = new ArrayList();
Product product = null;
for(int i = 1 ; i <= 34; i++) {
product = new Product(i,"Abc",new Date(),"","",i+1.20d,"Rs");
products.add(product);
}

return products;
} 
}


Now that we have the SLSB, its time to refactor the managed bean - “move method” to the session bean. The “getProductsByMonth” will undergo few more rounds of refactoring in the future for sure. Listing 2 shows the modified managed bean.
package com.windowshop.web.controller;

import java.util.List;

import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import com.windowshop.business.ProductService;
import com.windowshop.domain.entities.Product;

/**
* @author Dhrubo
*
*/
@ManagedBean(name="productController")
public class ProductController {
@EJB 
ProductService productService;
public List getProductsByMonth(){
return productService.getProductsByMonth();
}
}

So we can see that the SLSB is injected into the managed bean using @EJB annotation. The getProductsByMonth method is slimmer as the call is dedicated now to the SLSB. You will need to add some dependencies to the pom.xml file. Listing 3 shows the modified pom.xml file.

Listing 3 – 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>com.windowshop</groupId>
<artifactId>shopweb</artifactId>
<packaging>war</packaging>
<version>1.0.0</version>
<name>shopweb Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<!-- Prime faces , JSF -->

<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>2.2.RC1-SNAPSHOT</version>
<scope>runtime</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0.3</version>
<scope>provided</scope>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.0.3</version>
<scope>provided</scope>
<type>jar</type>
</dependency>

<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.5</version>
<scope>runtime</scope>
<type>jar</type>
</dependency>

<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>

</dependencies>
<repositories>
<repository>
<id>prime-repo</id>
<name>Prime Technology Maven Repository</name>
<url>http://repository.prime.com.tr/</url>
</repository>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
</repository>

</repositories>
<build>
<finalName>shopweb</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>


This was the easiest SLSB based project I have ever done in my life. Java EE 6 has been a refreshing experience so far. I intend to get more into depth and try out Java EE 6 and possibly all its facets possible with JBOSS 6. Now if you deploy this project you will the following lines in your JBOSS console confirming the deployment of EJB, registration in JNDI. You can launch the browser and check if the landing page is working as before. I did not find any problem.

JBOSS6 console

17:05:39,480 WARN  [InterceptorInfoRepository] EJBTHREE-1852: InterceptorInfoRepository is deprecated
17:05:40,347 INFO  [JBossASKernel] Created KernelDeployment for: shopweb.war
17:05:40,352 INFO  [JBossASKernel] installing bean: jboss.j2ee:jar=shopweb.war,name=ProductService,service=EJB3
17:05:40,352 INFO  [JBossASKernel]   with dependencies:
17:05:40,352 INFO  [JBossASKernel]   and demands:
17:05:40,352 INFO  [JBossASKernel]     jboss.ejb:service=EJBTimerService; Required: Described
17:05:40,353 INFO  [JBossASKernel]   and supplies:
17:05:40,353 INFO  [JBossASKernel]     jndi:ProductService
17:05:40,353 INFO  [JBossASKernel]     jndi:ProductService/no-interface
17:05:40,354 INFO  [JBossASKernel] Added bean(jboss.j2ee:jar=shopweb.war,name=ProductService,service=EJB3) to KernelDeployment of: shopweb.war
17:05:50,041 INFO  [TomcatDeployment] deploy, ctxPath=/shopweb
17:05:50,237 INFO  [config] Initializing Mojarra 2.0.2 (FCS b10) for context '/shopweb'
17:05:54,557 INFO  [AbstractNoInterfaceViewJNDIBinder] Binding the following entry in Global JNDI:

    ProductService/no-interface - EJB3.1 no-interface view

17:05:54,561 INFO  [SessionSpecContainer] Starting jboss.j2ee:jar=shopweb.war,name=ProductService,service=EJB3
17:05:54,573 INFO  [EJBContainer] STARTED EJB: com.windowshop.business.ProductService ejbName: ProductService
17:05:54,579 INFO  [JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:

Saturday, November 6, 2010

JSF 2.0 – First Managed Bean

The window shop, landing page is not complete. I have not shown the new product arrivals for this month in the center of the screen. In order to do that we need a managed bean which will retrieve data from the database. Later on we will integrate EJB 3.x stateless session beans to fetch the data for us. For now our managed bean will cook up the data to set the ball rolling. In this process we also discover the first domain object – Product. Going forward this will be turned into a JPA entity for CRUD operations.
Here is how the domain object looks like:
/**
* 
*/
package com.windowshop.domain.entities;

import java.util.Date;

import org.apache.commons.lang.builder.ToStringBuilder;

/**
* @author Dhrubo
* 
*/
public class Product {
private int productId;
private String productName;
private Date createdDate;
private String thumnailLocation;
private String model;
private double price;
private String currency;

public Product() {}

public Product(int productId, String productName, Date createdDate,
String thumnailLocation, String model, double price, String currency) {
super();
this.productId = productId;
this.productName = productName;
this.createdDate = createdDate;
this.thumnailLocation = thumnailLocation;
this.model = model;
this.price = price;
this.currency = currency;
}

public int getProductId() {
return productId;
}

public void setProductId(int productId) {
this.productId = productId;
}

public String getProductName() {
return productName;
}

public void setProductName(String productName) {
this.productName = productName;
}

public Date getCreatedDate() {
return createdDate;
}

public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}

public String getThumnailLocation() {
return thumnailLocation;
}

public void setThumnailLocation(String thumnailLocation) {
this.thumnailLocation = thumnailLocation;
}

public String getModel() {
return model;
}

public void setModel(String model) {
this.model = model;
}

public double getPrice() {
return price;
}

public void setPrice(double price) {
this.price = price;
}

public String getCurrency() {
return currency;
}

public void setCurrency(String currency) {
this.currency = currency;
}

public String toString() {
return ToStringBuilder.reflectionToString(this);
}
}


The managed bean is shown in the listing below
/**
* 
*/
package com.windowshop.web.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.bean.ManagedBean;

import com.windowshop.domain.entities.Product;

/**
* @author Dhrubo
*
*/
@ManagedBean(name="productController")
public class ProductController {

public List getProductsByMonth(){

//TODO - Remove to session bean and JPA to fetch from db
List products = new ArrayList();
Product product = null;
for(int i = 1 ; i <= 34; i++) {
product = new Product(i,"Abc",new Date(),"","",i+1.20d,"Rs");
products.add(product);
}

return products;
}
}


Note that with JSF 2 you can do away with faces-config.xml. This file is just optional. Instead you can turn a POJO into a managed bean with the ManagedBean annotation. One attribute is the name of the managed bean. In this case the managed bean is named “productController”. In case you do not want to name the managed bean it will by default be named with the class name part of the fully qualified class name. There are other attributes which I will take up as and when we come across the need for them. This managed bean will have a default request scope. I will discuss different scopes later. For the moment just know that for managed beans the default scope is request.

Now you will want to use this managed bean in JSF pages. The listing below (newproducts.xhtml) shows the new JSF which fills the missing piece.

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">

<f:view contentType="text/html">
<h:form>
<h:outputText value="New Products for November 2010"  style="font-size:.9em"/>

<p:dataGrid var="product" value="#{productController.productsByMonth}" columns="4"
rows="12" paginator="true" effect="true"
paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} 
{PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="8,12,16">

<p:column>
<p:panel header="#{product.model}" style="text-align:center">
<h:panelGrid columns="1" style="width:100%">
<!--
<p:graphicImage value="/images/cars/#{car.manufacturer}.jpg"/> 
-->
<h:outputText value="#{product.productName}" />

<p:commandLink title="View Detail" action="#">

</p:commandLink>
</h:panelGrid>
</p:panel>
</p:column>

</p:dataGrid>
</h:form>
</f:view>
</html>




The layout and other pages have been updated and they are now in the SVN.

Friday, November 5, 2010

Servlet 3.0 – Add frameworks as Plugins

With Servlet 3.0, it is now possible to include external or 3rd party frameworks as plug-ins to the web application. This is made possible by the ServletContainerInitializer interface. The documentation says that the implementation of this interface - “allows a library/runtime to be notified of a web application's startup phase and perform any required programmatic registration of servlets, filters, and listeners in response to it”. The servlet container finds the ServletContainerInitializer using the JAR services API during application startup. The framework implementing the ServletContainerInitializer needs to add a file named javax.servlet.ServletContainerInitializer in the META-INF/services directory of the JAR file. This file points to the implementation class of the ServletContainerInitializer.The JSF 2 Majorra implementation has used this feature. If we check the JSF-IMPL-2.x jar this file is located in META-INF/services folder and points to the class -  com.sun.faces.config.FacesInitializer. If we look into this class we will find the following lines -

	ServletRegistration reg = servletContext.addServlet("FacesServlet","javax.faces.webapp.FacesServlet");
reg.addMapping("/faces/*", "*.jsf", "*.faces");
servletContext.setAttribute(RIConstants.FACES_INITIALIZER_MAPPINGS_ADDED, Boolean.TRUE);

The ServletContainerInitializer thus registers the faces servlet and three URL mappings out of the box leading to clean web.xml. In fact web.xml is optional in Servlet 3.0.


A note on JBOSS 6 JSF application

JBOSS 6, JSF deployer is very special. It does some tricks with a JSF 2 web application. You can read it here - http://docs.jboss.org/jbossas/6/JSF_Guide/en-US/html/jsf.deployer.config.html

Wednesday, November 3, 2010

First Java EE 6 application

to create a Maven 2 Java EE 6 application. This will be primarily the UI part build with JSF. Primefaces is the library of choice to build the “windowshop” application. I will try to build a landing page similar to oscommerce. The figure 1 below shows a screenshot of the landing page mock up.

landing-proto

Figure 1 – Landing page prototype

Now let us create a Maven 2 web project using the - “maven-archetype-webapp”.

The listing below shows the pom.xml

Listing 1 – 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>com.windowshop</groupId>
    <artifactId>shopweb</artifactId>
    <packaging>war</packaging>
    <version>1.0.0</version>
    <name>shopweb Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.1</version>
            <scope>test</scope>
        </dependency>
        <!-- Prime faces , JSF -->
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>2.2.RC1-SNAPSHOT</version>
            <scope>runtime</scope>
            <type>jar</type>
        </dependency>

    </dependencies>
    <repositories>
        <repository>
            <id>prime-repo</id>
            <name>Prime Technology Maven Repository</name>
            <url>http://repository.prime.com.tr/</url>
        </repository>
        <repository>
            <id>maven2-repository.dev.java.net</id>
            <name>Java.net Repository for Maven</name>
            <url>http://download.java.net/maven/2/</url>
        </repository>     </repositories>
    <build>
        <finalName>shopweb</finalName>
    </build>
</project>


The web.xml need not have any entry as shown in listing 2. As per JSF 2 auto – registers FacesServlet which is required for JSF URL interpretation following the pluggability feature of Servlet 3. I will write about this feature and how this is enabled in JSF 2 in the next post. 


Listing.2 – web.xml

<web-app 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"
      version="3.0">
  <display-name>shopweb</display-name>
</web-app>

Now let us modify the index.jsp page to redirect to the default home landing page as shown in listing 3.


Listing 3 – index.jsp

<html>
<body>
<jsp:forward page="ui/home.jsf"></jsp:forward>
</body>
</html>

I will add the facelet templates and the home page. These are all in the SVN now. I am lazy copying them over here.


You can add the JBOSS 5 server adapter in Eclipse to start stop JBOSS 6 for now. Add the shopweb project and start the server. Once deployment is over, browse to - http://localhost:8080/shopweb/. This should display the guest home page. I will work to make this page similar to the prototype in Figure 1.

Tuesday, November 2, 2010

Rolling out Java EE 6 development environment

Step 0 – Download and install JDK 6

Download JDK 6 from the link - http://www.oracle.com/technetwork/java/javase/downloads/index.html. Install it under c:\java.

Step 1 – Download and install JBOSS 6

JBOSS6M5 can be downloaded from the following link - http://sourceforge.net/projects/jboss/files/JBoss/JBoss-6.0.0.M5. Once downloaded unzip the file to c:\jboss6.

Step 2 – Download and install Eclipse

Eclipse Helios 3.6.1 can be downloaded from the following link - http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/helios/SR1/eclipse-jee-helios-SR1-win32.zip. Once downloaded unzip the file to c:/eclipse

Step 3 – Install Maven 2 plug-in and extras

I will prefer to use Maven 2 as my build tool. This is very useful if we also have some continuous integration system set up in future. The Maven 2 eclipse plug-in update sites are located at - http://m2eclipse.sonatype.org/installing-m2eclipse.html. Launch Eclipse and install the plug-in core and extras. In case of the extras install only the WTP extension.

Once the M2E plug-in is installed,restarting Eclipse you may get some warnings as listed below:

Eclipse is running in a JRE, but a JDK is required
  Some Maven plugins may not work when importing projects or updating source folders.

You can resolve this by adding the following line to your eclipse.ini file. This file is located at c:\eclipse folder.

-vm
C:\Java\jdk1.6.0_22\bin\javaw.exe

This is a snapshot from my eclipse.ini file

openFile
--launcher.XXMaxPermSize
256M
-showsplash
-vm
C:\Java\jdk1.6.0_22\bin\javaw.exe
org.eclipse.platform

Step 4 – Install Subversion plug-in

I want to safe keep my learning on some subversion repository. So I went on to create a project on GOOGLE CODE called “windowshop” - http://code.google.com/p/windowshop/

You can add the subversion plug-in for Eclipse using the following update URL - http://subclipse.tigris.org/update_1.6.x

Step 5 – Configure SVN

Now I will commit and change code kept on the Google Code SVN. So I need to add the code repository. You can do so easily by going to the SVN repository view and adding the following URL - https://windowshop.googlecode.com/svn

The development environment is more or less setup. If I see that I have missed anything going forward, I will try to add it here.

Exploring Java EE 6

I have been using, learning and writing about Spring framework for last 5+ years now. It has done loads of good work to simplify life back in J2EE days. But off late I am seeing and participating in discussions where I see a transition back to the platform again. The reason being the Java EE 6 has adopted good ideas from frameworks like Spring, Hibernate etc and have come out with a lean and thin platform. This has not gone unnoticed in developer world.

Also in last couple of years Spring’s evolution has a framework has stalled to an extent. The core framework and extensions viz Spring MVC, Security etc being stable the guys at Spring Source have focused more on servers, OSGi, cloud and adding more products to Spring Source portfolio via acquisition route. The company itself was acquired by VMWare. So lots of things happening but nothing new or exciting enough in the core area to keep the developers attracted. This is really one bad thing that runs deep inside the Java developers’ veins. They are always in the lookout for something exciting new and better. This makes them restless to search for alternatives. The moribund around the core Spring and extensions stack and gradual evolution of Java EE 6 in the same time has acted as the new catalyst for excitement in the Java EE world.

I thought that this senior and experienced developers are showing interest for definite reason. I have been reviewing and reading about Java EE 6 for last few days and found it interesting, making things easier and I have a feeling that if you have half decent team Java EE 6 can cut down on development time significantly. So I thought of starting to explore this in greater detail. I have also got hold of the patterns book by Adam Bien and reading it. All in all things are looking good for the platform. I had a hard and reluctance to move to Spring from J2EE(I was a big fan of EJB in those days). But now I want to explore and make a quick transition back to Java EE 6.

I have decided to build some useful application to try and test all the different new features of Java EE 6. The application that I am trying to build is similar to OSCOMMERCE (http://www.oscommerce.com/), possibly a clone of this great application. I will try to build as many features as I can when I have time. Initially I thought of using Geronimo 3 for this, but I had to stumble upon some JSF issues possibly not compliant with JSF 2 and decided to switch to JBOSS 6M5 instead. Both these servers are very new in supporting the Java EE 6 specifications and catching up with documentation. Glassfish 3 seems to be there for sometime ready with Java EE 6. But since lot has already been written about Glassfish (including books from Apress), I thought its worthwhile exploring JBOSS (and later possibly Geronimo). Also I am a bit sceptical about the future of Glassfish. JONAS is still on Java EE 5. Before I end, here is the link to the JSF 2 and Geronimo 3 issue which I posted:

http://primefaces.prime.com.tr/forum/viewtopic.php?f=3&t=5635&p=24048#p24048

In my next post I will set up the development environment for Java EE 6 with Eclipse Helios 3.6.1 and JBOSS. Stay tuned!. The road will be pure Java EE 6 and then possibly some other frameworks if needed.

Sunday, September 26, 2010

Removing the border from header layout unit

As you have seen the layout contains layout units. You can put any element inside a layout unit. Now there is a border for each layout unit. For our online store, I do not want the border and the header title. In order to remove the border, you will need to override the CSS style and to remove the header just remove the header attribute (header="TOP") from the layout unit tag. This is shown in listing below
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">

<f:view contentType="text/html">

<h:head>
<title>Simple Store - Home</title>

<link type="text/css" rel="stylesheet"
href="#{request.contextPath}/themes/cupertino/skin.css" />

<style>

.ui-layout-unit-top .ui-layout-bd {
border: 0;
}

</style>


</h:head>

<h:body>


<p:layout fullPage="true">
<p:layoutUnit position="top" height="80">
<h:outputText value="Top content." />
</p:layoutUnit>
<p:layoutUnit position="bottom" header="BOTTOM" height="100">
<h:outputText value="Bottom content." />
</p:layoutUnit>
<p:layoutUnit position="left" header="LEFT" width="300">
<h:outputText value="Left content" />
</p:layoutUnit>
<p:layoutUnit position="right" header="RIGHT" width="200">
<h:outputText value="Right Content" />
</p:layoutUnit>
<p:layoutUnit position="center" header="CENTER">
<h:outputText value="Center Content" />
</p:layoutUnit>
</p:layout>



</h:body>



</f:view>
</html>



The result is shown in figure below

Creating the layout

Any web site has a layout. Layouts can be created with HTML tables, divs and with CSS with Javascript tricks. Prime Faces provides out of the box support for border layout. A border layout typically has 5 parts as shown below

TOP / HEADER
LEFT CENTER RIGHT
BOTTOM / FOOTER

This border layout works well for most websites. Prime faces border layout can be either applied to a full page or a specific element. It can respond to expand, collapse, close and resize events of each layout unit with ajax listeners. Let us create a full page layout for a simple shopping cart application similar to OSCOMMERCE - http://demo.oscommerce.com/

The listing below shows the modified home.xhtml code.

Listing 1 – home.xhtml

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">

<f:view contentType="text/html">

<h:head>
<title>Simple Store - Home</title>

<link type="text/css" rel="stylesheet"
href="#{request.contextPath}/themes/cupertino/skin.css" />




</h:head>

<h:body>


<p:layout fullPage="true">
<p:layoutUnit position="top" header="TOP" height="80">
<h:outputText value="Top content." />
</p:layoutUnit>
<p:layoutUnit position="bottom" header="BOTTOM" height="100">
<h:outputText value="Bottom content." />
</p:layoutUnit>
<p:layoutUnit position="left" header="LEFT" width="300">
<h:outputText value="Left content" />
</p:layoutUnit>
<p:layoutUnit position="right" header="RIGHT" width="200">
<h:outputText value="Right Content" />
</p:layoutUnit>
<p:layoutUnit position="center" header="CENTER">
<h:outputText value="Center Content" />
</p:layoutUnit>
</p:layout>



</h:body>



</f:view>
</html>



You can now see the home page layout as shown in figure below:


Blog - 4

Saturday, September 25, 2010

Adding color to Prime Faces

In my last post you have seen a command button. This command button uses the default Prime faces skin and is shown in grey. Let me now make things a bit colorful, by showing how to use the skins provided by Prime faces. Prime faces skins are all based on Jquery themeroller CSS framework. I am interested in cupertino font and I will download the same from - http://www.primefaces.org/themes/cupertino.zip. You can download lots of other ready made themes from - http://www.primefaces.org/themes.html.

In later posts I will show how to create, install and use custom theme or skin. Once downloaded unzip the theme to webapps/themes folder. This is shown in the figure below:

Blog - 2

Prime faces theme consists of a skin.css file and a set of images placed in images folder. Now modify your web.xml to tell Prime faces that it should no longer use the default theme sam. Here is the modified web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd" >


<context-param>
<param-name>primefaces.skin</param-name>
<param-value>none</param-value>
</context-param>


<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>


</web-app>

Finally add the css in your JSF source using the link tag as shown in the listing (home.xhtml) below:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">

<f:view contentType="text/html">

<h:head>
<title>PrimeFaces - ShowCase</title>

<link type="text/css" rel="stylesheet" href="#{request.contextPath}/themes/cupertino/skin.css" />


</h:head>

<h:body>
<h:form>
<p:commandButton value="Ajax Submit" />
</h:form>



</h:body>



</f:view>
</html>


Now just like in the previous post, build and deploy the application on tomcat and browse to the following URL - http://localhost:8080/hermesconsole/home.jsf. You will see the bluish button as shown in the figure below.


Blog - 3

Getting started with Prime faces 2

Prime faces is an amazing JSF framework from Cagatay Civici (http://cagataycivici.wordpress.com/). Its wonderful because it is easy to use, minimal dependencies, has probably the widest set of controls among all JSF frameworks, easy to integrate with Spring (including Spring Security) , Java EE EJBs, and last but not the least mobile UI support. So I decided to give Prime faces a try, before selecting it to use in my projects.

Step 1 – Create Maven 2 project

As a first step to integrating Prime faces, create a Maven 2 project in Eclipse. You will need to select ‘maven-archetype-webapp’.

Step 2 – Add repositories and dependencies in pom.xml

I will be using Prime faces 2 with JSF 2 on Tomcat 6. Since the dependencies for Prime Faces and JSF 2 (JSF 2.0.3 is required) are available on different repositories, I will add them to my pom file first. The listing below shows my 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>net.breezeware</groupId>
<artifactId>hermesconsole</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>hermesconsole Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>2.2.M1</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0.3</version>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.0.3</version>
</dependency>
</dependencies>


<repositories>
<repository>
<id>prime-repo</id>
<name>Prime Technology Maven Repository</name>
<url>http://repository.prime.com.tr/</url>
</repository>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/</url>
</repository>

</repositories>


<build>
<finalName>hermesconsole</finalName>
</build>
</project>



Step 3 – Change web.xml


Add the JSF faces servlet in the web.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd" >


<context-param>
<param-name>primefaces.skin</param-name>
<param-value>none</param-value>
</context-param>


<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>


</web-app>



Step 4 – Add a simple xhtml file – home.xhtml


Now let us see Prime faces in action, by adding a simple JSF snippet with 1 control from this library.

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.prime.com.tr/ui">

<f:view contentType="text/html">

<h:head>
<title>Hermes Console - Trying PrimeFaces</title>



</h:head>

<h:body>
<h:form>
<p:commandButton value="Ajax Submit" />
</h:form>



</h:body>



</f:view>
</html>

Step 5 – Build and deloy


Now that we are done, the next step is to build and create the war file and deploy it in Tomcat 6. Then point your browser to - http://localhost:8080/hermesconsole/home.jsf


You will see the following command button on your browser:


Blog - 1

Wednesday, July 7, 2010

Load your Spring beans as plug-ins

There are different ways of loading Spring beans in a web application – viz using the dispatcher servlet or the context loader listener. A more modular and flexible approach (which also allows you to minimize coupling and dependencies in your applications) is to load the barebones of your application with the core context loaders and load the rest of your beans in a pluggable way. For example you may be interested in loading your page controllers, business tier and data access code as three separate modules. Off course you can do this and then use import in a main spring config file or a comma separate list in your web.xml where you configure the spring bean definition xmls. But what if you just wanted to drop in a jar with Spring beans and be sure they will be loaded and registered in the container. This also eases the pain of swapping an implementation. The goal is to put all your Spring beans in a particular layer, package it as a jar with one or more configuration file(with one following a special naming convention which is used to load them). You can also choose to go for feature based plugin – for example for show employee details use case you can package your view (freemarker template + javascript + css = I will show you how to do this in a later post), page controller (Spring MVC annotated controller), business service (interface + pojo implementation) and data access (interface + implementation) in a jar with configuration file. But my experience with this is if you go for feature based plugin – you can very soon land up with tons of plugins difficult to manage. For the moment lets just focus on the class that makes this pluggable design possible.

/**
* @author dhrubo
*/
package com.middlewareteam.spring.web.context;

import java.io.IOException;

import javax.servlet.ServletConfig;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.web.context.support.XmlWebApplicationContext;

/**
* @author dhrubo
*
*/
public class PluggableXmlWebApplicationContext extends XmlWebApplicationContext {

public static final String PLUGIN_CONTEXT_CONFIG_NAME = "pluginContextConfigName";

private final Logger log = LoggerFactory.getLogger(PluggableXmlWebApplicationContext.class);

@Override
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader)
throws IOException {

super.loadBeanDefinitions(reader);

log.info("Loading plugin application contexts.");
log.info("Seeking plugin application context configuration name from servlet config ");

ServletConfig config = this.getServletConfig();
String resourceName = null;
if(config != null) {

resourceName = this.getServletConfig().getInitParameter(PLUGIN_CONTEXT_CONFIG_NAME);
log.info("Configured plugin resource name : {}",resourceName);
}

if(StringUtils.isEmpty(resourceName)) {
log.info("Seeking plugin application context configuration name from servlet context/web app context.");
resourceName = this.getServletContext().getInitParameter(PLUGIN_CONTEXT_CONFIG_NAME);
}

log.info("Final plugin resouce name : {}",resourceName);

ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
try {
Resource[] configResources = resourcePatternResolver
.getResources(resourceName);


if (configResources.length != 0) {
log.info("Plugins found");
for (Resource resource : configResources) {
log.info("Resource == " + resource);

}
reader.loadBeanDefinitions(configResources);
} else {
log.info("No Plugins found.");
}
} catch (IOException e) {
throw new RuntimeException("Error loading plugin definitions",e);
}

}

}



Now this is how you should configure this class in your Spring bean loading mechanism.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="dms" version="2.5">
<display-name>oollaasweb</display-name>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/config/log4j.xml</param-value>
</context-param>

<!-- security beans are here -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/spring-security.xml
</param-value>
</context-param>

<context-param>
<param-name>contextClass</param-name>
<param-value>
com.middlewareteam.spring.web.context.PluggableXmlWebApplicationContext
</param-value>
</context-param>

<context-param>
<param-name>pluginContextConfigName</param-name>
<param-value>
classpath*:pluginRootApplicationContext.xml
</param-value>
</context-param>


<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>


<!-- Root web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<!-- Spring security filters -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
<servlet-name>staticresourceservlet</servlet-name>
<servlet-class>com.middlewareteam.spring.web.servlet.ResourceServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>

<servlet>
<servlet-name>dmsservlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/config/spring-web.xml</param-value>
</init-param>
<init-param>
<param-name>contextClass</param-name>
<param-value>com.middlewareteam.spring.web.context.PluggableXmlWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>pluginContextConfigName</param-name>
<param-value>classpath*:pluginApplicationContext.xml</param-value>
</init-param>

<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>staticresourceservlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>dmsservlet</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>


<servlet-mapping>
<servlet-name>dmsservlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>


<servlet-mapping>
<servlet-name>dmsservlet</servlet-name>
<url-pattern>*.json</url-pattern>
</servlet-mapping>


<welcome-file-list>

<welcome-file>index.html</welcome-file>

</welcome-file-list>

</web-app>

Now just put your spring config xml with the name pluginRootApplicationContext.xml in the root of the jar and you are ready to roll out pluggable modules. You can use multiple configuration file here too. Just import them in the pluginRootApplicationContext.xml. Also if you use Maven 2 put the pluginRootApplicationContext.xml in the src/main/resources folder. Things will be much easier to package and deploy if you are using Maven.


There are few limitations to this model though. Since Spring does not yet support hot deployment (application context is read only at run time you cannot add beans while your app is running, you can refresh though but it is risky) you have to re-start your applications for the plugins to get listed in the Spring container. As I wrote earlier this is in line with Eclipse plugin architecture. Another limitation is we do not yet have a versioning. What this means is what if you are using application layer plugins and you have just modified a handful of classes. In that case you like that your plugin system can identify and register the new version and retire the old version during an application restart. However you can always delete the old jar and replace it with the new one till we have the version management.

Saturday, June 26, 2010

CKEDITOR 3.x - Simplest Ajax Submit Plugin

 

I have assumed that you have downloaded and got started with CKEDITOR.

Step 1 – The html file is shown below:

<html>
<head>
<title>Writer</title>
<meta content="text/html; charset=utf-8" http-equiv="content-type" />
<script type="text/javascript" src="ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="js/jquery-1.4.2.min.js"></script>
<style>

.cke_contents {
height: 400px !important;
}

</style>
</head>
<body>


<form action="sample_posteddata.php" method="post">


<textarea id="editor" > </textarea>


<script type="text/javascript">
//<![CDATA[




CKEDITOR.replace( 'editor',
{
fullPage : true,
uiColor : '#9AB8F3',
toolbar : 'MyToolbar'


});




//]]>
</script>

</form>

</body>
</html>



Note that the jquery js file is part of this html page.


Step 2: Create a folder called ‘ajaxsave’ under the plugin folder and save the plugin.js file in it. The source of this file is shown below:

CKEDITOR.plugins.add('ajaxsave',
{
init: function(editor)
{
var pluginName = 'ajaxsave';


editor.addCommand( pluginName,
{
exec : function( editor )
{
alert( "Executing a command for the editor name - " + editor.checkDirty() );


$.post("http://localhost:8080/test/TestServlet", { name: "John", time: "2pm" } );

alert('after ajax post');
},
canUndo : true
});

/*
editor.addCommand(pluginName, 
new CKEDITOR.dialogCommand(pluginName)

);
*/

editor.ui.addButton('Ajaxsave',
{
label: 'Save Ajax',
command: pluginName,
className : 'cke_button_save'
});
}
});

 


Thats all. You will now need to add this new button to the CKEDITOR toolbar. This is added in the config.js under ckeditor folder as shown below:




CKEDITOR.editorConfig = function( config )
{
// Define changes to default configuration here. For example:
// config.language = 'fr';
// config.uiColor = '#AADC6E';

config.uiColor = '#AADC6E';
config.resize_enabled = false;




config.toolbar = 'MyToolbar';

config.toolbar_MyToolbar =
[
['NewPage','Preview'],
['Cut','Copy','Paste','PasteText','PasteFromWord','-','Scayt'],
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
['Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak'],
'/',
['Styles','Format'],
['Bold','Italic','Strike'],
['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
['Link','Unlink','Anchor','Ajaxsave'],
['Maximize','-','About']
];


config.extraPlugins = 'ajaxsave';

};

Saturday, May 29, 2010

Part V : A Simple and Smart Result Mapper

The examples so far only deal with single table. But it is very much possible to join multiple tables and still use this mapper. As an example consider three entities as shown below:
T_REPOSITORY
REPOSITORY_ID int
REPOSITORY_NAME varchar
CONNECTOR_ID int
T_CONNECTOR
CONNECTOR_ID int
CONNECTOR_NAME varchar
URL varchar
OWNER_ID int
T_OWNER
OWNER_ID int
OWNER_NAME varchar
OWNER_KEY varchar
The relationship is clear - a repository has a connector and a connector has a owner. So how can you populate a Repository object containing a Connector Object which in turn has an Owner object. This is just simple. Execute this query.
SELECT r.repository_id "repositoryId", r.repository_name "repositoryName",
c.connector_id "connector.connectorId",
c.connector_name "connector.connectorName",
c.url "connector.url",
o.owner_id "connector.owner.ownerId",
o.owner_name "connector.owner.ownerName",
o.owner_key "connector.owner.ownerKey"
FROM
t_repository r,t_connector c, t_owner o
WHERE
r.repository_id = ?
AND c.connector_id = r.connector_id
AND o.owner_id = c.owner_id


The mapper automatically checks if the child object exists, if not it creates one and then populates the properties. The Javabeans are listed below for reference.
Listing - Repository.java
import org.apache.commons.lang.builder.ToStringBuilder;
public class Repository {
private int repositoryId;
private String repositoryName;
private Connector connector;
/**
* @return the repositoryId
*/
public int getRepositoryId() {
return repositoryId;
}
/**
* @param repositoryId the repositoryId to set
*/
public void setRepositoryId(int repositoryId) {
this.repositoryId = repositoryId;
}
/**
* @return the repositoryName
*/
public String getRepositoryName() {
return repositoryName;
}
/**
* @param repositoryName the repositoryName to set
*/
public void setRepositoryName(String repositoryName) {
this.repositoryName = repositoryName;
}
/**
* @return the connector
*/
public Connector getConnector() {
return connector;
}
/**
* @param connector the connector to set
*/
public void setConnector(Connector connector) {
this.connector = connector;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {

return ToStringBuilder.reflectionToString(this);
}


}


Listing - Connector.java
import org.apache.commons.lang.builder.ToStringBuilder;
public class Connector {
private int connectorId;
private String connectorName;
private String url;
private Owner owner;
/**
* @return the connectorId
*/
public int getConnectorId() {
return connectorId;
}
/**
* @param connectorId the connectorId to set
*/
public void setConnectorId(int connectorId) {
this.connectorId = connectorId;
}
/**
* @return the connectorName
*/
public String getConnectorName() {
return connectorName;
}
/**
* @param connectorName the connectorName to set
*/
public void setConnectorName(String connectorName) {
this.connectorName = connectorName;
}
/**
* @return the url
*/
public String getUrl() {
return url;
}
/**
* @param url the url to set
*/
public void setUrl(String url) {
this.url = url;
}


/**
* @return the owner
*/
public Owner getOwner() {
return owner;
}
/**
* @param owner the owner to set
*/
public void setOwner(Owner owner) {
this.owner = owner;
}

/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {

return ToStringBuilder.reflectionToString(this);
}
}


Listing - Owner.java
import org.apache.commons.lang.builder.ToStringBuilder;


/**
* @author dhrubo
*
*/
public class Owner {
private long ownerId;
private String ownerName;
private String ownerKey;



/**
* @return the ownerId
*/
public long getOwnerId() {
return ownerId;
}



/**
* @param ownerId the ownerId to set
*/
public void setOwnerId(long ownerId) {
this.ownerId = ownerId;
}



/**
* @return the ownerName
*/
public String getOwnerName() {
return ownerName;
}



/**
* @param ownerName the ownerName to set
*/
public void setOwnerName(String ownerName) {
this.ownerName = ownerName;
}



/**
* @return the ownerKey
*/
public String getOwnerKey() {
return ownerKey;
}



/**
* @param ownerKey the ownerKey to set
*/
public void setOwnerKey(String ownerKey) {
this.ownerKey = ownerKey;
}



@Override
public String toString() {

return ToStringBuilder.reflectionToString(this);
}
}

Part IV : A Simple and Smart Result Mapper

In my last post, I have shown how the dao support class changed to convert list of maps to list of domain objects. Now the DAO implementation class must also change to use these new methods. Here is the modified DAO class.
Listing – UserDaoImpl.java
package net.sf.dms.security.dao.impl;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.dms.security.dao.api.UserDao;
import net.sf.dms.security.domain.User;
import net.sf.spring.dao.AbstractBaseDaoSupport;

/**
* @author dhrubo
* 
*/
public class UserDaoImpl extends AbstractBaseDaoSupport implements UserDao {

private Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);
@Override
public List<User> listUsers() {
return (List<User>)this.queryForList("listUsers", User.class);
}

@Override
public void save(User user) {
this.insert("saveUser", user.getEmail(),
user.getPassword(), user.getFirstName(), user.getLastName());
}

@Override
public void update(User user) {

}
@Override
public User findUserByUserName(String username) {
logger.debug("Loading user details as part of authentication");
return (User)this.queryForObject("findUserByUserName", User.class, username);  
}

@Override
public List<User> findUsersStartingWith(String nameStartsWith) {
return (List<User>)this.queryForList("findUsersStartingWith", User.class, nameStartsWith + "%");  
}
}


Now you can see clearly that the list or finder queries have been reduced to just 1 line. I guess this code reduction is same as in any ORM or datamapper. Now let us see how the SQL has changed. I have tested this code on Postgresql 8.3 and should work with any sensible database available.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="secSqlMap" class="org.springframework.beans.factory.config.MapFactoryBean">
<property name="sourceMap">
<map>
<entry key="listUsers">
<value>
<![CDATA[
SELECT first_name "firstName",last_name "lastName",email "userCode",user_id "userId" FROM t_user

]]>

</value>

</entry>

<entry key="saveUser">
<value>
<![CDATA[
INSERT INTO t_user(user_id, email, password, first_name,last_name) VALUES (nextval('t_user_seq'), ?, ?, ?, ?)

]]>

</value>

</entry>

<entry key="findUserByUserName">
<value>
<![CDATA[
SELECT first_name "firstName",last_name "latName",email "userCode",user_id "userId" FROM t_user WHERE email = ?

]]>

</value>

</entry>

<entry key="findUsersStartingWith">
<value>
<![CDATA[
SELECT first_name "firstName",last_name "latName",email "userCode",user_id "userId" FROM t_user 
WHERE first_name LIKE ?;

]]>

</value>

</entry>

</map>


</property>
</bean>

</beans>

Now you can see my source of meta data and how I use them to run this simple data mapper and move towards my goal of lightweight persistence and database independence.

Part III : A Simple and Smart Result Mapper

Now a days we make extensive use of Annotations. Whether it is a good or bad practice to mix configuration meta data with code is debatable, but its better than proprietary XML tags. Since we are so used to mixing meta data in our Java code, why not make use of same tactics in building our data mapper.
SQL statements in all databases supports something called an alias for column names. I will use this to map a SQL result column to a property in my bean. This is better because even if my column name changes but my alias remains same my bean will be populated properly.
I use JODD bean utils. You can download the JODD distribution here.  A problem with JODD is that it is not available in any of the global maven repositories. So you need install the same in your local repository by running the following command 
C:\&gt;mvn install:install-file -Dfile=jodd-3.0.9.jar&nbsp; -DgroupId=jodd -DartifactId=
jodd -Dversion=3.0.9 -Dpackaging=jar 
Use the GUI screens if you are using Archiva repository manager. 
I am on windows and I have kept my jar is located at C:\jodd-3.0.9.jar. It has no other dependencies. 

Correction - As pointed out below in the comments section JODD is now available on Maven.

<dependency>
    <groupId>org.jodd</groupId>
    <artifactId>jodd-wot</artifactId>
    <version>3.1.0</version>
</dependency>



Here is the modified abstract dao support class.
package net.breezeware.spring.dao;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jodd.bean.BeanUtil;


import org.apache.commons.lang.reflect.ConstructorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;

/**
* @author dhrubo
*
*/
public abstract class AbstractBaseDaoSupport extends SimpleJdbcDaoSupport{
private Logger logger = LoggerFactory.getLogger(AbstractBaseDaoSupport.class);

private Map<String, String> sqlMap;


protected List<?> queryForList(String id, Class primaryType, Object ...params) {
String sql = sqlMap.get(id);
List<Map<String, Object>> mappedResultList = this.getSimpleJdbcTemplate().queryForList(sql, params);

return this.preapreList(mappedResultList, primaryType);
}

protected List<?> queryForList(String id, Class primaryType) {
List<Object> result = new ArrayList<Object>();
String sql = sqlMap.get(id);

List<Map<String, Object>> mappedResultList = this.getSimpleJdbcTemplate().queryForList(sql, new HashMap());
return this.preapreList(mappedResultList, primaryType);
}


protected Object queryForObject(String id, Class type, Object ...params) {
String sql = sqlMap.get(id);
Map<String, ?> dataMap = this.getSimpleJdbcTemplate().queryForMap(
sql, params);

return prepareObject(dataMap,type);
}

protected void insert(String id, Object ...params ) {
String sql = sqlMap.get(id);
this.getSimpleJdbcTemplate().update(sql, params);
}

private List<?> preapreList(List<Map<String, Object>> mappedResultList,Class primaryType) {
List<Object> result = new ArrayList<Object>();
Object holder = null;
for(Map<String, Object> resultMap : mappedResultList) {
holder = prepareObject(resultMap,primaryType);
result.add(holder); 
}

return result;
}
private Object prepareObject(Map<String, ?> resultMap, Class primaryType) {
Iterator<String> it = resultMap.keySet().iterator();
Object holder = getNewObjectInstance(primaryType);

String name = null;
Object value = null;

//set all the properties
while(it.hasNext()) {


name = it.next();
value = resultMap.get(name);

logger.debug("Mapping property = {}, value = {}",name,value);

BeanUtil.setPropertyForcedSilent(holder, name, value);
}

return holder;

}



private Object getNewObjectInstance(Class clazz) {
Object object = null;
try {
object = ConstructorUtils.invokeExactConstructor(clazz, null);
} catch (Exception e) {
throw new RuntimeException(e);
}
return object;
}

/**
* @param sqlMap the sqlMap to set
*/
public void setSqlMap(Map<String, String> sqlMap) {
this.sqlMap = sqlMap;
}


}




This class is by no means complete and is evolving. But it has the essential methods to get the ball rolling. This class uses the Spring JDBC to execute the SQL statements. The SQL statements are picked up from the externalized cache. It utilizes the meta data or column names in the SQL result set retrieved and populated by Spring JDBC as keys in those row maps. Note that in case a column does not have corresponding bean property, it will escape silently. With smart configuration (will show examples soon), this can support nested properties.

Part II : A Simple and Smart Result Mapper

I am a big fan of Spring JDBC. The reasons are simple -
  • Full control over SQL. I can optimize, tweak and tune them to my free will. Let me think in terms of those tables and not objects.
  • Cuts down my DAO code significantly.
  • Takes care of all boilerplate code.
  • Integrates well with other parts of my application which mostly uses other Spring components.
  • Simple and easy to setup and get running at high speed
  • Minimal learning curve
One area where Spring framework does not do a good job is that of list/finder queries returning n number of records. Lets say you want to find the employees in a certain department. The query is executed and you get a map of records, but then you need to return a list of domain objects to the business tier. You will loop through the map list returned by Spring JDBC, for each of your record create a Javabean populate each field and then add to another list which will be finally returned. So there is lot of boilerplate code here.  Look at the example code below, which fetches all users in my system.
public List<User> listUsers() {
String SQL_LIST_USER = "SELECT first_name,last_name,email,user_id FROM t_user";
        List<Map<String,Object>> users = this.getSimpleJdbcTemplate().queryForList(SQL_LIST_USERS,new HashMap());
        List<User> userList = new ArrayList<User>();
        User userHolder = null;
        for(Map<String,Object> user : users) {
            userHolder = new User();
            userHolder.setFirstName((String)user.get("first_name"));
            userHolder.setLastName((String)user.get("last_name"));
            userHolder.setUserCode((String)user.get("email"));
            userHolder.setUserId((Integer)user.get("user_id"));
            userList.add(userHolder);
        }
        return userList;
    }
There is significant redundant code here. If you notice carefully, if a column name changes this code will lead to errors. You may consider this mapping and listing in a row mapper, but still you need to write this code and unnecessarily add new classes per such list method for Spring JDBC callbacks.
So I looked for a data mapper. The best solution in this regard is iBatis. It is much simpler and has less learning curve compared to ORM and tries to do limited things. While playing with it I was once again struck by XML meta data hell. This time mapping each SQL with different maps. This could be some XML to maintain in a decently large project. Also it queries database multiple time if I need to populate object graphs. Also my attempts to integrate iBatis 3 with Maven 2 and Spring 3 failed with ClassNotFoundException. Hence my journey with iBatis ended very abruptly. I was looking for a smarter solution, which I could configure very easily, should be very simple, no learning curve, efficient and intuitive.
The solution was in Spring framework, bit of SQL trick and an external super efficient bean manipulation library called JODD - http://jodd.org/doc/beanutil.html
As a first step towards building this simple and smart data mapper, I want to externalize my SQLs. So I introduce an abstract dao support class which does load externalized SQLs from a Spring configuration file. Note I am not using any additional XML file for this. This will again lead same problems as in iBatis. Instead its better to stick to what I know best. Here is the first version of this abstract class.
Listing – AbstractBaseDaoSupport.java
package net.sf.webplug.spring.dao;  
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;  
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;  
/**
* @author dhrubo
*
*/
public abstract class AbstractBaseDaoSupport extends SimpleJdbcDaoSupport{
    private Logger logger = LoggerFactory.getLogger(AbstractBaseDaoSupport.class);
    private Map<String, String> sqlMap;  
    /**
     * @param sqlMap the sqlMap to set
     */
    public void setSqlMap(Map<String, String> sqlMap) {
        this.sqlMap = sqlMap;
    }
    public String getSql(String id) {

return this.sqlMap.get(id);
    } }
Now I change my Dao class to use this abstract class instead.
Listing – UserDaoImpl.java
package net.sf.dms.security.dao.impl;  
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;  
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.simple.SimpleJdbcDaoSupport;  
import net.sf.dms.security.dao.api.UserDao;
import net.sf.dms.security.domain.User;  
/**
* @author dhrubo
* 
*/
public class UserDaoImpl extends AbstractBaseDaoSupport implements UserDao {  
    private Logger logger = LoggerFactory.getLogger(UserDaoImpl.class);  
    @Override
    public List<User> listUsers() {
        String sql = this.getSql("listUsers");
        List<Map<String,Object>> users = this.getSimpleJdbcTemplate().queryForList(sql,new HashMap());
        List<User> userList = new ArrayList<User>();
        User userHolder = null;
        for(Map<String,Object> user : users) {
            userHolder = new User();
            userHolder.setFirstName((String)user.get("first_name"));
            userHolder.setLastName((String)user.get("last_name"));
            userHolder.setUserCode((String)user.get("email"));
            userHolder.setUserId((Integer)user.get("user_id"));
            userList.add(userHolder);
        }
        return userList;
    }  
} 
The sql is now moved to an Spring config file (separate just for SQLs)
Listing – sql-repository.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  
    <bean id="secSqlMap" class="org.springframework.beans.factory.config.MapFactoryBean">
        <property name="sourceMap">
            <map>
                <entry key="listUsers">
                    <value>
                        <![CDATA[
                            SELECT first_name ,last_name ,email ,user_id  FROM t_user
                        ]]>
                    </value>
                </entry>
                
            </map>
        </property>
    </bean>  
</beans> 
Now that I have externalized the SQLs, its time to look into the main configuration file. There is something interesting here too.
Listing – applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <import resource="sql-repository.xml"/>
       <bean id="secDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.postgresql.Driver"/>
        <property name="url" value="jdbc:postgresql://localhost:5432/dms"/>
        <property name="username" value="postgres"/>
        <property name="password" value="postgres"/>
    </bean>
    <bean id="abstractSecBaseDaoSupport" class="net.sf.spring.dao.AbstractBaseDaoSupport" abstract="true">
            <property name="dataSource" ref="secDataSource"/>
            <property name="sqlMap" ref="secSqlMap"/>
    </bean>
    <bean id="userDao" class="net.sf.dms.security.dao.impl.UserDaoImpl" parent="abstractSecBaseDaoSupport" />
    <bean id="roleDao" class="net.sf.dms.security.dao.impl.RoleDaoImpl" parent="abstractSecBaseDaoSupport"/>
    <bean id="userRoleDao" class="net.sf.dms.security.dao.impl.UserRoleDaoImpl" parent="abstractSecBaseDaoSupport"/>
</beans> 
Note the abstract class configuration. I do not need to configure the data source property for each dao class anymore. This ends my first step of clean up. In the next post I will show how to extend the abstract class to provide mapper functions.

Part I : A Simple and Smart SQL Result Mapper

I am not at all a fan of ORM solutions/frameworks like Hibernate. I have already written and presented my view on different forums and discussions the reasons for my disliking. I truly empathize with Ted Neward that ORM are “Vietnam of Computer Science”.
http://www.codinghorror.com/blog/2006/06/object-relational-mapping-is-the-vietnam-of-computer-science.html
http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx
Followup - http://blogs.tedneward.com/2006/06/27/Thoughts+On+Vietnam+Commentary.aspx
http://stackoverflow.com/questions/404083/is-orm-still-the-vietnam-of-computer-science
Some counter punches
http://www.codeproject.com/KB/architecture/ORM_Vietnam.aspx?display=Print

  • I am not convinced as to why should I learn HQL or similar QLs provided by other OR Mapping solutions? Why should I not write and benefit from SQLs which have been proven to be so powerful over the ages and often outlive the lifetime of an application. So many times I have seen SQLs and Stored procedures being reused as applications moved from say .NET to Java and vice-versa.
  • There is significant learning curve to an ORM add to those fancy concepts like lazy loading(if you need lazy loading you must first think that there is some problem, why are you afraid of object creation with modern day JVM and hardware or is it that you fear you will create too many objects?).
  • Why do I generate, tweak so many XMLs worry about so much XML based syntaxes, how do I efficiently manage these XMLs and alter later if required? There are too many XML elements and attributes some hidden undocumented? Oh this is real pain. Annotations solve some of the meta data hell, but I am still in a dilemma if mixing meta data with code is a good practice?
  • Why do think of my joins in terms of objects when they are best done with relational tables? Sorry I can only think of joining tables and not my objects.Live and let them live in their own world.
  • There is no doubt ORMs are powerful and tries to make life easy. But the learning curve and deadline pressures often forces developers with somehow acquired knowledge by reading few articles and getting started guides from here and there to code and then finally when issues crop up especially too many objects, JVM crashes and sever performance worries the application falls apart and you focus more on solving these than business logic.
  • Even dangerous trend that I see these days is the advent of ORM specific profilers. What does this imply? Yes the ORMs are serious cause for performance bottlenecks in your applications. I know someone came to me few months back, asking why his JVM crashes when he is running his search queries and paging? His table just had about 150k records and JVM heap was 2GB. Not a bad setting at all? Is it because the ORM was fetching a significant subset of the records based on the search criteria,first to application server before starting pagination? or my friend had a bad QL statement?
  • I know ORMs can help with optimistic lock? But do they help with phantom records problem?
  • Why should I cache on application server and allow or create a slightest possibility of my JVM to burst? Does caching on JVM really increase the application performance? I always knew and still continue to believe the best place to cache database records is in the database memory. Can we not gain on performance by keeping these data to where it belongs, which have been long tuned and proven to optimize performance, reducing network trips, setting tips to bulk fetch data when required, fetch data in optimal blocks? You may be tempted to use caching systems which hides behind the ORM. But think in case of an issue you have the pain of learning another framework and then fixing your errors, if Googling does not help.
  • How does your ORM populate the object graph? Does it fire query after query going down the graph? If yes think about the domain model? Or think about your ORM implementation? Is there any way out? My answer is yes, smart SQL + smart mapping. I will try to show this with an example.
  • However, ORMs are good, if you have indepth knowledge of the framework under consideration. Then with an ORM you can significantly cut down code in your DAO layer. This is also a myth. With Spring JDBC you can reduce your code even more or equal to what you can with an ORM. You can read an article I wrote long back on OTN(actually wrote in erstwhile BEA DEV2DEV) here to start thinking about this - http://www.oracle.com/technology/pub/articles/dev2arch/2006/10/spring-jdbc-dao.html
  • One area I thought I might use ORM is when I design a product which needs to support multiple databases. But then I realised this is not true, if we manage to externalize our SQL and have an efficient strategy to map SQL result set to our domain object we can achieve database independence. 99% of the applications are not meant to be db independent. If your customer has investment so much money to procure license, build competency buy hardware for that big blackbox for Java developers called RDBMS why would he want that box of money, time and effort go down the drain by replacing it with another. So if you are trying to sell me an ORM for db independence I will not simply not buy in.
  • ORMs dependent on several 3rd party libraries. Do I need to increase 3rd party dependencies? Yes you will need 3rd party jars but we must make effort to keep them to minimal. There may be version collisions between 3rd party libraries used by your ORM and main framework.

Thursday, May 20, 2010

A custom plug-in system for web applications

Recently I was trying to put together a plugin system for web applications. The idea is similar to Eclipse plugins. Where you bundle your extension in a jar and then drop them in Eclipse-Home/plugins folder, restart Eclipse and you are ready to use it. Note that Eclipse plugins are OSGi plugins.

So my initial effort was to see if I could build a pluggable web application with OSGi. After few experiments with Equinox (the Eclipse OSGi engine) and Felix, I moved on to check out Spring DM as well as Spring DM server. But all I all I felt that

  • OSGi / DM involves significant learning curve.
  • The web server bundles are “probably” not of enterprise strength.
  • Still trying to gel with JEE.
  • Significant extra effort required to port applications to OSGi platform.

All in all  OSGi / DM has to go few more miles before we build Enterprise server apps using those containers / bundles. But its a very good start and promises a lot in the future.

So what to do? I started digging dip into Spring framework for a while and soon came up with an idea of a simple plug-in system for web applications. This plug-in system should allow you to package your application components(controllers,business objects, data acccess)  in a jar file with mandatory Spring config file. This jar file should be dropped in WEB-INF/lib and should be ready for use once the web container is restarted or this application is restarted. It should also allow you to package your view components as well in the jar.

In the next few posts I will try to show how such a simple yet effective system can be build by extending the Spring framework. I will also show some good practices that I learnt while building applications with this framework extension which I call WebPlug. The code and documentation will be available soon on Sourceforge. 

Saturday, April 24, 2010

SecurityContextPersistenceFilter

This bean is configured as shown below:
<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"/>
This bean has two main tasks and they are very important
  • In a typical web application like Skyphoto the user will login once and then subsequently do several operations or click several links and buttons generating several authenticated requests to the server. Since the user was authenticated once it is important to store the security context somewhere and by some means. Otherwise he/she has to authenticate for each request and will sooner or later never use Skyphoto. In a typical web application you will store an user object in HttpSession and each time a request comes in, the server identifies this session with a session id and you get the user object. It is the responsibility of the server to cache/store and manage these session objects during the lifetime of the session.
“In Spring Security, the responsibility for storing the SecurityContext between requests falls to the SecurityContextPersistenceFilter, which by default stores the context as an HttpSession attribute between HTTP requests. It restores the context to the SecurityContextHolder for each request….”
  • The SecurityContextPersistenceFilter stores the security context in ThreadLocal for the current execution. Hence it is essential to clear this thread local object in a web application as the server uses a pool of thread and chances are that this thread will be reused. If this security context is not cleared there is a high possibility that the set information will be used for request from a different user leading to unpredictable results and possible violation of security.
The SecurityContextPersistenceFilter takes care of clearing the security context object from thread local once the request completes.
This filter MUST be executed BEFORE any authentication processing filter. Authentication processing mechanisms used in those filters expect the SecurityContextHolder to contain a valid SecurityContext by the time they execute.
The task of saving and retrieving the security context is delegated to a separate strategy interface SecurityContextRepository. The interface is shown below:
public interface SecurityContextRepository {
  SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder);
  void saveContext(SecurityContext context, HttpServletRequest request,
         HttpServletResponse response);
}
“The HttpRequestResponseHolder is simply a container for the incoming request and response objects, allowing the implementation to replace these with wrapper classes. The returned contents will be passed to the filter chain.”
The default implementation of SecurityContextRepository is the HttpSessionSecurityContextRepository class. As the name suggests it stores the security context as an HttpSession attribute.This class has an important attribute - allowSessionCreation  which by default is set to true. Hence this class can create a new session if it needs to for storing security context of an authenticated user. Note that session is only created after authentication is done and contents of security context now has been changed with authenticated user information. If you want to prevent session creation, then set this parameter to false. A sample configuration is shown below.
<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter"> <property name='securityContextRepository'>
<bean class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'> <property name='allowSessionCreation' value='false' />
</bean>
</property>
</bean>

How the filter chain works?

Going back to the filter chain configuration in my last post, you can see a chain filters configured as shown below:
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/SkyPhotoWeb/**" filters=" securityContextPersistenceFilterWithASCFalse, basicAuthenticationFilter, exceptionTranslationFilter, filterSecurityInterceptor" />
<sec:filter-chain pattern="/**" filters=" securityContextPersistenceFilterWithASCTrue, formLoginFilter, exceptionTranslationFilter, filterSecurityInterceptor" />
</sec:filter-chain-map>
</bean>
Let us assume that a request is send as http://www.skyphoto.com/SkyPhotoWeb/dosomething.html the request runs through the filters as shown in picture below:
blog1
In my next post I will explain all these and few other important filters in greater detail.