Build and Deploy Cloud Aware Java EE 6 PostgreSQL 9.2 Applications Inside Eclipse

You can build ,deploy, and manage your OpenShift Java applications right from within the Eclipse IDE using the JBoss Tools OpenShift plugin. This blog will guide you through installation, setup, application creation, and managing your application from within Eclipse. During this post, we will develop a Java EE 6 PostgreSQL 9.2 application and deploy it on the JBoss EAP 6(JBoss Enterprise Application Platform 6) application server running on OpenShift.

OpenShift has best in class Java support with Tomcat 6 , Tomcat 7 , JBoss AS7, and JBoss EAP 6 servers bundled with it. You can also run Jetty or GlassFish servers on it using DIY cartridges. OpenShift also provides support for Jenkins continuous integration server as well.

In this blog, we will use four Java EE 6 specifications -- JPA , Bean Validation , CDI , and JAX-RS to build a todo application.

Prerequisite

  1. Basic Java knowledge is required.

  2. Install the latest Java Development Kit (JDK) on your operating system. You can either install OpenJDK 7 or Oracle JDK 7. OpenShift supports OpenJDK 6 and 7.

  3. Download the latest Eclipse package for your operating system from the official Eclipse website. At the time of writing this blog, the latest Eclipse package is called Kepler.

Download Eclipse

It is very easy to install eclipse , just extract the downloaded package and you are done. On linux or mac machines , open a new command line terminal and type command shown below.$ tar -xzvf eclipse-jee-kepler-R-.tar.gz . On windows you can extract the zip file using winzip or 7-zip or any other software. After you have extracted the Eclipse, there will be a folder named *eclipse in the directory where you extracted Eclipse. You can optionally create a shortcut of the executable file.

  1. Sign up for an OpenShift Account. It is free and instant. Red Hat gives every user three free Gears on which to run your applications. At the time of this writing, the combined resources allocated for each user is 1.5 GB of memory and 3 GB of disk space.

Step 1 : Install JBoss Developer Tools Eclipse Plugin

Once you have downloaded and extracted the Eclipse Kepler IDE for Java EE, open Eclipse and navigate to your project workspace. Go to Help > Eclipse Marketplace and you will see a screen as shown below.

Eclipse Marketplace Screenshot

In the search box, type "jboss tools" and press the Go button.

JBoss Tools in Search Box

After pressing the Go button, you will see "JBoss Tools(Kepler)" as the first result as shown below.

JBoss Tools (Kepler)

Now press the install button, and you will get a list of plugins which you can install. As the purpose of this blog is to demonstrate OpenShift, we will only choose "JBoss OpenShift Tools" as shown below. After selecting "JBoss OpenShift Tools" press the "Confirm" button.

JBoss OpenShift Tools Plugin

Next you will be asked to accept the license. Click "I accept the terms of the license agreement" radio button and press the Finish button as shown below.

Accept License

Eclipse will next show security warning as plugin is unsigned. Press OK button and you will be asked to restart the Eclipse so that changes can be applied. Press Yes to restart Eclipse.

Restart Eclipse

Step 2 : Create SSH Keys

OpenShift requires SSH for :

  1. Performing Git operations.
  2. Remote access your application gear.

So we need to create a RSA key to deploy the work with OpenShift. Eclipse makes it very easy to create RSA keys. To create keys, follow the steps mentioned below.

  1. Access the menu: Window> Preferences.
  2. With the preferences window still open, go to: General> Network Connection> SSH2
  3. Click on Tab Key Management and then the button Generate RSA Key ...
  4. Copy the code key
  5. Finally click the Save Private Key and Ok as image below

Creating SSH Keys

Step 3: Upload the Generated SSH key to OpenShift

After creating the ssh keys in the previous step, we need to upload the public key to OpenShift. Go to https://openshift.redhat.com/app/console/keys/new and add a new ssh key as shown below. You can find the public key in .ssh folder under your user home directory. The file will have a name id_rsa.pub. You can add multiple keys like one for your office and one for your home.

Upload Public SSH Key Preview

Step 4 : Create OpenShift Application

After we have uploaded the SSH keys to OpenShift account , we are ready to create OpenShift applications using JBoss Tools OpenShift support. Go to your eclipse and click File > New > Other > OpenShift Application as shown below and click next as shown below.

Create OpenShift Application on Eclipse

After pressing the 'Next' button, you will be asked to provide your OpenShift account credentials. If you have not signed up for OpenShift account, you can click the sign up here link on the wizard to create your OpenShift account. Enter your OpenShift account username and password. Check the 'Save password' checkbox so that you don't have to enter password with every command and click 'Next'.

Sign In to OpenShift

Next you will be asked to create an OpenShift domain name. Every account needs to have one domain name which should be unique among all OpenShift users. One account can have only one domain name. Domain name forms part of the url that OpenShift assigns to an application. For example, if your application name is awesomeapp and namespace is onopenshiftcloud, then the url of application will be http://awesomeapp-onopenshiftcloud.rhcloud.com. Enter your unique domain name and press finish.

Domain Name Details

After domain is created, you will be directed to the application creation wizard. You will be asked to enter the details required to create an application like name of the application, type of application, gear profile(whether you want small instance or medium instance.For FreeShift users,you can only create small instances), scaled application or non scaled application, and whether you want to embed any or multiple cartridges like mysql, postgresql, mongodb etc. We will create an application named todoapp which uses jbosseap-6 and postgresql-9.2 cartridges.

Create OpenShift Application

Next you will be asked to set up todoapp and configure server adapter settings. Choose the default and click next as shown below.

Setup OpenShift Application

The next screen will ask you to specify the location where you want to clone the git repository and name of the git remote. This is shown below.

Import Application

Finally, press the finish button and you are done. This will create an application container for us, called a gear, and setup all of the required SELinux policies and cgroup configuration. OpenShift will install the PostgreSQL 9.2 cartridge on the application gear and JBoss tools OpenShift plugin will show an information box with details as shown below.

PostgreSQL Database Details

OpenShift will also setup a private git repository for you and clone the repository to your local system. Next, OpenShift will propagate the DNS to the outside world. Finally, the project will be imported in your eclipse workspace as shown below.

Todo App in Eclipse

You can view the application running online by going to the following url: http://todoapp-{domain-name}.rhcloud.com. Please replace {domain-name} with your OpenShift account domain name.

Step 5 : Look at Generated Code

Now we will take a look at the template project created by OpenShift. Below is the listing of all the content in todoapp project created by OpenShift.

$ cd todoapp
 
$ $ ls -la
 
drwxr-xr-x  11 shekhargulati  staff   374 Aug 28 14:02 .git
-rw-r--r--   1 shekhargulati  staff    69 Aug 28 14:02 .gitignore
drwxr-xr-x   6 shekhargulati  staff   204 Aug 28 14:02 .openshift
-rw-r--r--   1 shekhargulati  staff   179 Aug 28 14:02 README.md
drwxr-xr-x   3 shekhargulati  staff   102 Aug 28 14:02 deployments
-rwxr--r--   1 shekhargulati  staff  2152 Aug 28 14:02 pom.xml
drwxr-xr-x   3 shekhargulati  staff   102 Aug 28 14:02 src

Lets take a look them :

1 .git is your local git repository which contains all the information required by git. Git does not create .git folder in ever sub-directory like svn.You can refer to this article for more information about what's in the .git directory.

2 .gitignore is a file used to specify which all files or file types you want to ignore so that they are not committed to the git repository. This can include files like .classpath, .project, etc.

3 .openshift is an OpenShift specific folder which exists in every OpenShift application. This folder has four sub-directories -- action_hooks,config, cron, and markers as shown below.

$ ls -la .openshift/
 
drwxr-xr-x   3 shekhargulati  staff  102 Aug 28 14:02 action_hooks
drwxr-xr-x   4 shekhargulati  staff  136 Aug 28 14:02 config
drwxr-xr-x   8 shekhargulati  staff  272 Aug 28 14:02 cron
drwxr-xr-x   3 shekhargulati  staff  102 Aug 28 14:02 markers

The action_hooks folder hosts scripts which developer can use to hook into application life cycle and do things like create a database before starting the application, expose an environment variable, or install a Maven dependency etc. The config folder contains a JBoss configuration file called standalone.xml and modules folder to put your own jars and property files in the classpath. The cron folder contains files which can be used to run cron jobs on application gear. The cron functionality is only enabled when you embed Cron cartridge in to the application. The markers folder is used to define marker files. Currently you can have the following files in the markers folder. Adding marker files with the following names to this directory will have the following effects:

  • enable_jpda - Will enable the JPDA socket based transport on the java virtual machine running the JBoss AS 7 application server. This enables you to remotely debug code running inside the JBoss AS 7 application server.

  • skip_maven_build - Maven build step will be skipped

  • force_clean_build - Will start the build process by removing all non essential Maven dependencies. Any current dependencies specified in your pom.xml file will then be re-downloaded.

  • hot_deploy - Will prevent a JBoss container restart during build/deployment. Newly build archives will be re-deployed automatically by the JBoss HDScanner component.

  • java7 - Will run JBoss EAP with Java7 if present. If no marker is present then the baseline Java version will be used (currently Java6)

4 README.md file contains information about the project layout. You can over-write this file with useful information about your project.

5 deployments folder is for binary deployment i.e. war or ear file instead of source deployment. So, if you want to deploy war rather than pushing source code, then add war or ear file in this folder, add it to git repository, commit it, and then finally push the war file.

6 pom.xml is a standard Maven project object model file. The pom.xml contained in template project include Java EE 6 dependencies. This makes writing Java EE 6 applications very easy. The most important thing specified in pom.xml is a Maven profile named "openshift". This is the profile which is invoked when you do deploy the code to OpenShift.

<profiles>
        <profile>
            <id>openshift</id>
            <build>
                <finalName>todoapp</finalName>
                <plugins>
                    <plugin>
                        <artifactId>maven-war-plugin</artifactId>
                        <version>2.1.1</version>
                        <configuration>
                            <outputDirectory>deployments</outputDirectory>
                            <warName>ROOT</warName>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </profile>
</profiles>

7 src folder is where you will write your application source code. It follows the same convention as followed by every maven project.

Step 6: Make your First Change

Let's make our first change to the application in order to understand development workflow with with OpenShift. Open index.html and change heading as shown below.

<h1>
    Welcome to TodoApp -- Your Online Todo Manager
</h1>

Go to servers view , then right click on todoapp OpenShift server, and click Publish as shown below.

Publish Change to OpenShift

When we clicked Publish, it performed a couple different tasks. First, it committed the changes to local git repository and then pushed the changes to todoapp application gear. After changes have been pushed, OpenShift invokes the maven build by executing "mvn -e clean package -Popenshift -DskipTests" command. This builds a war file with name ROOT and deploy the WAR in JBoss EAP 6. You can view the change by opening browser and visiting http://todoapp-{domain-name}.rhcloud.com. Please replace {domain-name} with your OpenShift account domain name.

The disadvantage of using Publish is that you will not be able to give your commit messages. It will use "Commit from JBoss Tools" as commit message. It is a quick way to test your changes.

Step 7 : View Logs

Logs are very useful for debugging errors in case something goes wrong on the server. OpenShift Eclipse tooling makes it very easy to tail the log files. In the server view, right click on the todoapp server , and then go to OpenShift Tail files.

Tail Log Files

You can view the logs in console view.

View Logs in Console View

Step 8 : Define Todo Model class

We will start developing our application by creating domain model for our Todo application. JPA specification defines an API for the management of persistence and object/relational mapping using a Java domain model. It defines a mapping between database table and Entity class. Entity is a POJO with public no-arg constructor which is used to define mapping with relation database table.

The application will have a single entity called Todo. Create a new package( File > New > Other > Package) com.todoapp.domain under src/main/java source folder. Next, create a new class( File > New > Other > Class) called Todo in com.todoapp.domain package. Each entity class is annotated with @Entity annotation and has instance variables which represent persistent state of the entity. Each instance variable corresponds to a column in a table.

The entity shown below is a JPA entity with JPA and bean validation annotations. Bean Validation JSR 303 provides a class-level constraint declaration and validation facility for Java applications.

package com.todoapp.domain;
 
import java.util.Date;
import java.util.List;
 
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
 
@Entity
public class Todo {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    @NotNull
    @Size(min = 10, max = 40)
    private String todo;
 
    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(name = "Tags", joinColumns = @JoinColumn(name = "todo_id"))
    @Column(name = "tag")
    @NotNull
    private List<String> tags;
 
    @NotNull
    private Date createdOn = new Date();
 
    public Todo(String todo) {
        this.todo = todo;
    }
 
    public Todo() {
    }
 
    public Long getId() {
        return id;
    }
 
    public void setId(Long id) {
        this.id = id;
    }
 
    public String getTodo() {
        return todo;
    }
 
    public void setTodo(String todo) {
        this.todo = todo;
    }
 
    public Date getCreatedOn() {
        return createdOn;
    }
 
    public void setCreatedOn(Date createdOn) {
        this.createdOn = createdOn;
    }
 
 
    public void setTags(List<String> tags) {
        this.tags = tags;
    }
 
    public List<String> getTags() {
        return tags;
    }
 
    @Override
    public String toString() {
        return "Todo [id=" + id + ", todo=" + todo + ", tags=" + tags
                + ", createdOn=" + createdOn + "]";
    }
 
 
 
}

The code shown above:

  1. The entity class shown above has a public no-arg constructor.

  2. The Todo class in annotated with @Entity annotation and has four instance variables. The identity field is defined by the id field and is annotated with @Id.

  3. The @NotNull and @Size are bean validation annotation. They make sure that values are not null and size of todo field is between 10 and 40 characters.

  4. The @ElementCollection annotation signifies that tags field are listed in a different table. This annotation defines a collection of instances of a basic type or embeddable class.

Step 9 : Create persistence.xml file

In JPA, entities are managed within a persistent context. Within persistence context, entities are managed by entity manager. In Java EE , entity manager is managed by Java EE container. The configuration of entity manager is defined in an xml file called persitence.xml.

So we have to create persistence.xml file. The persistence.xml file is a standard configuration file in JPA. It needs to be included in the META-INF directory inside the JAR file that contains the entity beans. The persistence.xml file must define a persistence-unit with a unique name. Create a META-INF folder under src/main/resources and then create a persistence.xml file as shown below.

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
    version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
 
    <persistence-unit name="todos" transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:jboss/datasources/PostgreSQLDS</jta-data-source>
        <class>com.todoapp.domain.Todo</class>
        <properties>
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="create" />
        </properties>
 
    </persistence-unit>
</persistence>

In the xml shown above :

  1. The name of persistence unit is todos.

  2. The transaction type attribute is JTA. This means JTA datasource will be used. The JTA datasource will be defined using jta-data-source element.

  3. The provider element specifies the name of persistence provider. We will be using hibernate as persistence provider.

  4. The class element specifies the entity class to be managed. To specify multiple entity classes you can use multiple class elements.

  5. The properties element is used to specify standard JPA and vendor specific properties.

Step 10 : Create TodoService

Next we will create a TodoService class in com.todoapp.service package which will perform CRUD operation using EntityManager as shown below.

package com.todoapp.service;
 
import java.util.List;
 
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
 
import com.todoapp.domain.Todo;
 
@Stateless
public class TodoService {
 
    @PersistenceContext
    private EntityManager entityManager;
 
 
    public Todo create(Todo todo) {
        entityManager.persist(todo);
        return todo;
    }
 
    public Todo find(Long id) {
        Todo todo = entityManager.find(Todo.class, id);
        return todo;
    }
 
}

In the code shown above :

  1. The TodoService class is a Stateless session bean as it defines @Stateless annotation. Stateless session bean does not contain any conversational state.

  2. The container managed EntityManager is injected into the service class using @PersistenceContext annotation.

  3. A new entity is persisted in the database using EntityManager persist method. The entity is persisted into database at transaction commit.

  4. The EntityManager find method is used to find the entity by id.

Step 11 : Enable CDI

CDI or Context and Dependency injection is a Java EE 6 specification which enables dependency injection in a Java EE 6 project. CDI defines type-safe dependency injection mechanism in Java EE. Almost any POJO can be injected as a CDI bean.

To enable CDI in your project, create a beans.xml file in src/main/webapp/WEB-INF folder.

<beans 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/beans_1_0.xsd">
</beans>

Step 12 : Expose RESTful web service

JAX-RS defines annotation-driven API for writing RESTful services.

Before exposing RESTful web service for Todo entity we have to active JAX-RS in our application. To enable JAX-RS, create a class which extends javax.ws.rs.core.Application and specify the application path using javax.ws.rs.ApplicationPath annotation as shown below.

package com.todoapp.rest;
 
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
 
@ApplicationPath("/rest")
public class JaxRsActivator extends Application {
   /* class body intentionally left blank */
}

Next we will create TodoRestService class which will expose two methods to create and read a Todo object. The service will consume and produce JSON.

package com.todoapp.rest;
 
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder;
 
import com.todoapp.domain.Todo;
import com.todoapp.service.TodoService;
 
@Path("/todos")
public class TodoRestService {
 
    @Inject
    private TodoService todoService;
 
    @POST
    @Consumes("application/json")
    public Response create(Todo entity) {
        todoService.create(entity);
        return Response.created(
                UriBuilder.fromResource(TodoRestService.class)
                        .path(String.valueOf(entity.getId())).build()).build();
    }
 
    @GET
    @Path("/{id:[0-9][0-9]*}")
    @Produces(MediaType.APPLICATION_JSON)
    public Todo lookupTodoById(@PathParam("id") long id) {
        Todo todo = todoService.find(id);
        if (todo == null) {
            throw new WebApplicationException(Response.Status.NOT_FOUND);
        }
        return todo;
    }
 
}

In the code shown above :

  1. We annotated TodoRestService with @Path annotation. TodoRestService is a POJO class and is published at todos path by adding @Path annotation.

  2. Next we injected TodoService using @Inject annotation. This is enabled by CDI.

  3. The create method is annotated with @POST annotation. This method will be invoked when HTTP post request is made at */todos * url. The @Consumes annotation means that this method will consume data in json format. Container will automatically unmarshall json into Todo object.

  4. The lookupTodoById method is annotated with @GET annotation. This method will be invoked when a HTTP GET is made to todos/id where id can be any number. The method find todo item using TodoService find method and returns todo entity back. The @Produces annotation makes sure that container will marshal the java object into JSON.

Step 13 : Commit and Push changes to OpenShift

Now we need to commit the changes to local git repository and publish changes to application gear. To do that, go to Window > Show View > Other > Git > Git Staging as show below.

Open Git Staging View

You will see a new view called "Git Staging" in the bottom.

Git Staging View

Select the todoapp project and you will see unstaged changes for todoapp project.

Git Unstaged Changes

Select all unstaged changes and drag them to staged changes.

Git Staged Changes

Add a commit message and press "Commit and Push" button.

Commit and Push Changes

Finally we can test our REST web service using curl.To create a todo execute the curl command as shown below.

$ curl -i -X POST -H "Content-Type: application/json" -d '{"todo":"Learning OpenShift","tags":["openshift","cloud","paas"]}' https://todo-{domain-name}.rhcloud.com/rest/todos
 
HTTP/1.1 201 Created
Date: Wed, 23 Jan 2013 14:16:50 GMT
Server: Apache-Coyote/1.1
Location: http://todo-openshiftbook.rhcloud.com/rest/todos/1
Content-Length: 0
Strict-Transport-Security: max-age=15768000, includeSubDomains

To read the Todo entity execute the curl command as shown below

$ curl -i -H "Accept: application/json" https://todo-{domain-name}.rhcloud.com/rest/todos/1
HTTP/1.1 200 OK
Date: Wed, 23 Jan 2013 14:17:23 GMT
Server: Apache-Coyote/1.1
Content-Type: application/json
Vary: Accept-Encoding
Strict-Transport-Security: max-age=15768000, includeSubDomains
Transfer-Encoding: chunked
 
{"id":1,"todo":"Learning OpenShift","tags":["openshift","cloud","paas"],"createdOn":1359541249762}

Conclusion

In this blog we covered how you can use Eclipse IDE and OpenShift JBoss tooling support to build Java EE applications. OpenShift Eclipse plugin makes it very easy to work with OpenShift. So, if you are a Java (EE) developer looking for a deployment platform then give OpenShift a try.

What's Next?