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.