Forums/Knowledge Bases/Micro Cloud Foundry Knowledge Base

PostgreSQL for Micro Cloud Foundry - Spring Tutorial

Xin Li
posted this on September 21, 2011 23:46

This tutorial explains how to use the PostgreSQL service for Micro Cloud Foundry from a java and Spring application. This application manages a basic guestbook page. Every visitor can sign the guestbook by filling a simple form. All visitors that have already singed are listed below the form with date.

Prerequisites

  • Micro Cloud Foundry
  • Ruby 1.8 or 1.9
  • VMC command line tool
  • JDK 6
  • Maven
  • Eclipse

Install and configure Micro Cloud Foundry

Go to http://www.cloudfoundry.com/micro to get the Micro Cloud Foundry virtual machine image, and follow blog http://support.cloudfoundry.com/entries/20316811-micro-cloud-foundr... to install and configure your Micro Cloud Foundry properly.

Once you get your Micro Cloud Foundry up and running, you should be able see similar console like this:

mcf_console.png

 

Type "7" to check the status of various services, including PostgreSQL:

mcf-services.png

Create the Sample Java Spring Application

Now stop thinking about cloud, focus on the java application for a while.

Creating a Maven Web Project

Please follow steps below to create an empty web application:

* Start Eclipse

* Open the [New Project] dialog box, e.g. by using File > New > Project...

* Select Maven > Maven Project and click Next.

* Verify that the Create a simple project checkbox is disabled and click Next.

* Enter maven-archetype-webapp as a filter, select maven-archetype-webapp in the artifact list and click Next.

* Enter Group Id (e.g. Guestbook), Artifact Id (e.g. Guestbook), Version (e.g. 1.0) and Package (guest), and click Finish to create the project.

To add dependency on the Spring framework and automatically download all required java package from Maven repository, open the pom.xml, copy and paste following to replace its content.

<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>Guestbook</groupId>
   <artifactId>Guestbook</artifactId>
   <packaging>war</packaging>
   <version>1.0</version>
   <name>Guestbook Maven Webapp</name>
   <url>http://maven.apache.org</url>
   <dependencies>
      <dependency>
         <groupId>javax.servlet</groupId>
         <artifactId>servlet-api</artifactId>
         <version>2.5</version>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.hibernate</groupId>
         <artifactId>hibernate-entitymanager</artifactId>
         <version>3.6.0.Final</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-webmvc</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-tx</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-orm</artifactId>
         <version>3.0.5.RELEASE</version>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.3.2</version>
            <configuration>
               <source>1.6</source>
               <target>1.6</target>
            </configuration>
         </plugin>
      </plugins>
      <finalName>Guestbook</finalName>
   </build>
</project>

Entity Class and Persistence Unit

To store objects in a database using JPA we need to define an entity class:

*  Right click the Guestbook project node (in the "Package Explorer" window), select New > Source Folder, enter src/main/java as Folder Name and click Finish.

* Open the [New Java Class] dialog box, e.g. by right clicking the new source directory node (in the [Package Explorer] window) and selecting New > Class.

* Enter guest as the package name - use exactly that case sensitive package name.

* Enter Guest as the class name - use exactly that case sensitive class name.

* Click Finish to create the new entity class.

* Copy and paste to replace the new source file content with following code:

package guest;

import java.io.Serializable;
import java.sql.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class Guest implements Serializable {
   private static final long serialVersionUID = 1L;

   // Persistent Fields:
   @Id
   @GeneratedValue
   Long id;
   private String name;
   private Date signingDate;

   // Constructors:
   public Guest() {
   }

   public Guest(String name) {
      this.name = name;
      this.signingDate = new Date(System.currentTimeMillis());
   }

   // String Representation:
   @Override
   public String toString() {
      return name + " (signed on " + signingDate + ")";
   }
}

We also need to configure JPA by setting a META-INF/persistence.xml file:

* Right click the src/main/resources node (in the "Project Explorer") and select New > Folder.

* The parent folder should be resources.

* Enter META-INF as a new folder name and click Finish.

* Right click the new MATA-INF folder in the "Project Explorer" window, select New > File, enter persistence.xml as file name and click Finish.

* Copy and paste following code to replace the new file content.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
   xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

   <persistence-unit name="GuestbookPU">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <properties>
         <property name="hibernate.session_factory_name" value="SESSION_FACTORY" />
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
         <property name="hibernate.hbm2ddl.auto" value="update" />
         <property name="hibernate.show_sql" value="true" />
         <property name="hibernate.cache.provider_class"
            value="org.hibernate.cache.HashtableCacheProvider" />
      </properties>
   </persistence-unit>

</persistence>

Define a Spring DAO Component

Operations on the database will be performed by an instance of a Data Access Object (DAO) that we will define in this step as a Spring MVC component:

* Open the [New Java Class] dialog box by right clicking the guest package node (in the "Package Explorer" window) and selecting New > Class.

* The package name should be guest.

* Enter GuestDao as the class name - use exactly that case sensitive class name.

* Click Finish to create the new DAO Spring component class.

* Again, copy and paste following code to replace the new file content.

package guest;

import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
public class GuestDao {
   // Injected database connection:
   @PersistenceContext
   private EntityManager em;

   // Stores a new guest:
   @Transactional
   public void persist(Guest guest) {
      em.persist(guest);
   }

   // Retrieves all the guests:
   public List<Guest> getAllGuests() {
      TypedQuery<Guest> query =
            em.createQuery("SELECT g FROM Guest g ORDER BY g.id", Guest.class);
      return query.getResultList();
   }
}

Add a Controller Class

In this step we will add a Spring Controller to manage guestbook web requests:

* Open the [New Java Class] dialog box by right clicking the guest package node (in the "Package Explorer" window) and selecting New > Class.

* The package name should be guest.

* Enter GuestController as the class name - use exactly that case sensitive class name.

* Click Finish to create the new Spring Controller class.

* Copy and paste following code to replace the new file content.

package guest;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class GuestController {

   @Autowired
   private GuestDao guestDao;

   @RequestMapping(value = "/guest")
   public ModelAndView guestbook(HttpServletRequest request) {
      // Handle a new guest (if any):
      String name = request.getParameter("name");
      if (name != null)
         guestDao.persist(new Guest(name));

      // Prepare the result view (guest.jsp):
      return new ModelAndView("guest.jsp", "guestDao", guestDao);
   }
}

Add a JSP page

In this step we will add the JSP that generates the guestbook HTML output:

* Open the "New JSP File" dialog box by right clicking WEB-INF under src/main/webapp (in the "Package Explorer" window), selecting New > Other... > Web > JSP File and clicking Next.

* The parent folder should be WEB-INF (to prevent direct access to the JSP bypassing Spring).

* Enter guest as the jsp file name - use exactly that case sensitive class name.

* Click Finish to create the new JSP file.

* Copy and paste following code to replace the new file content.

<%@page contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@page import="guest.*"%>

<jsp:useBean id="guestDao" type="guest.GuestDao" scope="request" />

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>JPA Guestbook Web Application Tutorial - Powered by
PostgreSQL service in Cloud Foundry</title>
</head>

<body>
<form method="POST" action="guest.html">Name: <input type="text"
    name="name" /> <input type="submit" value="Add" /></form>

<hr>
<ol>
    <%
       for (Guest guest : guestDao.getAllGuests()) {
    %>
    <li><%=guest%></li>
    <%
       }
    %>
</ol>
<hr>
</body>
</html>

And replace the generated index.jsp with:

<jsp:forward page="guest.html" />

Set the Spring XML

To integrate the Spring Framework into a web application we have to add the definition of the Spring dispatcher servlet to the web.xml configuration file and to configure that servlet using another xml configuration file.

Open the web.xml file (under src/main/webapp/WEB-INF) in a text editor, copy and paste to replace the default content of the web.xml file with the following new content:

<?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">

   <servlet>

      <servlet-name>spring</servlet-name>

      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

      <load-on-startup>2</load-on-startup>

   </servlet>

   <servlet-mapping>

      <servlet-name>spring</servlet-name>

      <url-pattern>*.html</url-pattern>

   </servlet-mapping>

   <session-config>

      <session-timeout>30</session-timeout>

   </session-config>

   <welcome-file-list>

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

   </welcome-file-list>

</web-app>

Additional spring configuration is set in another XML file (whose name is derived from the name of the Spring dispatcher servlet in web.xml). To generate that file:

* Right click the WEB-INF node in the "Package Explorer" window, select New > Other... > XML > XML File and click Next.

* The parent folder should be Guestbook/src/main/webapp/WEB-INF.

* Enter spring-servlet as the File Name.

* Click Finish to create the XML file.

* Copy and paste following code to replace the file content.

<?xml version="1.0" encoding="windows-1252"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop"
   xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">

   <!-- Use @Component annotations for bean definitions -->
   <context:component-scan base-package="guest" />

   <!-- Use @Controller annotations for MVC controller definitions -->
   <mvc:annotation-driven />

   <bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
      <property name="url" value="jdbc:hsqldb:mem:guest" />
      <property name="username" value="sa" />
      <property name="password" value="" />
   </bean>

   <bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="jpaVendorAdapter">
         <bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
      </property>
   </bean>

   <!-- Add Transaction support -->
   <bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
      <property name="entityManagerFactory" ref="emf" />
   </bean>

   <!-- Use @Transaction annotations for managing transactions -->
   <tx:annotation-driven transaction-manager="myTxManager" />

   <!-- View resolver -->
   <bean
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/" />
   </bean>

</beans>

The settings above guides Spring to support annotations (for components, controllers and transactions), to inject a JPA EntityManager, to manage transactions and to look for JSP pages in the WEB-INF directory.

Build the project and deploy to Micro Cloud Foundry

Open a command prompt (Windows) or terminal (Linux) and "cd" to the location of the Guest project in the Eclipse workspace. Type command "mvn package" to generate war file Guestbook.war

mvn package

[...]

[INFO] ------------------------------------------------------------------------

[INFO] BUILD SUCCESSFUL

[INFO] ------------------------------------------------------------------------

[INFO] Total time: 3 seconds

[INFO] Finished at: Mon Aug 08 23:59:32 GMT-08:00 2011

[INFO] Final Memory: 31M/428M

[INFO] ------------------------------------------------------------------------

Now we are ready to push the application to Micro Cloud Foundry. Change to the target directory before doing vmc push. Here, I will call my application "'guestbook"

$vmc push

Would you like to deploy from the current directory? [Yn]: y

Application Name: guestbook

Application Deployed URL: 'guestbook.yourcloud.cloudfoundry.me'?

Detected a Java SpringSource Spring Application, is this correct? [Yn]: y

Memory Reservation [Default:512M] (64M, 128M, 256M or 512M)

Creating Application: OK

Would you like to bind any services to 'guestbook'? [yN]: y

Would you like to use an existing provisioned service [yN]? n

The following system services are available::

1. mongodb

2. mysql

3. postgresql

4. redis

Please select one you wish to provision: 3

Specify the name of the service [postgresql-9a305]: guestbook

Creating Service: OK

Binding Service: OK

Uploading Application:

  Checking for available resources: OK

  Processing resources: OK

  Packing application: OK

  Uploading (9M): OK  

Push Status: OK

Staging Application: OK                                                        

Starting Application: OK

Now your application is running inside the Micro Cloud Foundry! You can also use "vmc services", "vmc apps" commands to retrieve service and application information.

vmc-services.png

 

 vmc-apps.png

Now you can go to http://guestbook.yourcloud.cloudfoundry.me and see the web page:

guestbook-mcf-blank.png

Type anything you want and click on "Add', what you just type will appear in the page, and of course stored in PostgreSQL database.

guestbook-mcf-entry.png

Deploy to Cloud Foundry

Now it's time to deploy this sample application to a bigger cloud: www.cloudfoundry.com and see how the application works without any change in code and configuration!

First, use vmc target command to point to Cloud Foundry:

$vmc target api.cloudfoundry.com

Successfully targeted to [http://api.cloudfoundry.com]

$vmc login

Email: [Your Cloud Foundry email]

Password: [Your Cloud Foundry password]

Successfully logged into [http://api.cloudfoundry.com]

Then use the same vmc push command used above to deploy the application:

$vmc push

Would you like to deploy from the current directory? [Yn]: y

Application Name: guestbook-mycloud

Application Deployed URL: 'guestbook-mycloud.cloudfoundry.com'?

Detected a Java SpringSource Spring Application, is this correct? [Yn]: y

Memory Reservation [Default:512M] (64M, 128M, 256M or 512M)

Creating Application: OK

Would you like to bind any services to 'guestbook-postgresql'? [yN]: y

Would you like to use an existing provisioned service [yN]? n

The following system services are available::

1. mongodb

2. mysql

3. postgresql

4. rabbitmq

5. redis

Please select one you wish to provision: 3

Specify the name of the service [postgresql-a9x55]: guestbook

Creating Service: OK

Binding Service: OK

Uploading Application:

  Checking for available resources: OK

  Processing resources: OK

  Packing application: OK

  Uploading (9M): OK  

Push Status: OK

Staging Application: OK                                                        

Starting Application: OK

The application behaves exactly the same as in Micro Cloud Foundry:

guestbook-cf.png

 Benefit of developing applications using Micro Cloud Foundry

Micro Cloud Foundry™ is a complete instance of Cloud Foundry on your own computer. It brings all services that a developer needs to his/her own computer, without bothering IT and waiting for service provisioning. Developer can deploy application to Micro Cloud Foundry environment in development and QA cycle, once the application is certified for production, just deploy to a bigger cloud environment Cloudfoundry.com, it runs without any change! It's superior to traditional method of software development, in that it's fast and developer self-service.

 

 
Topic is closed for comments