GWT + Spring MVC + JPA Web Application
by IntelliBitz Technologies
http://www.intellibitz.com
===========
Objective:
===========
Create and run a fully functional GWT + Spring MVC + Hibernate JPA Web
Application.
We'll have 3 parts, explaining each of the GWT, Spring MVC, JPA
integration part.
=========================================
PART ONE - GWT with RemoteServiceServlet
=========================================
Lets first make sure we can independently build a GWT RPC application:
We can use the standard tools available (Netbeans, eclipse gwt
plugins) and create our GWT RPC application.
We'll name our package to be 'com.ibt.intelligrade'. Now based on the
GWT coding conventions we need to have the following packages:
'com.ibt.intelligrade' ==> holds the gwt.xml configuration file
'com.ibt.intelligrade.public' ==> holds the html file displayed in
browser
'com.ibt.intelligrade.client' ==> holds the client file which are
translated to Javascript
'com.ibt.intelligrade.server' ==> holds the servlet file (RPC)
We'll look at each of the packages one by one with their respective
source files.
package: 'com.ibt.intelligrade'
============================
CourseServiceClient.gwt.xml
============================
package: 'com.ibt.intelligrade.public'
============================
CourseServiceClient.html
============================
CourseServiceClient
package: 'com.ibt.intelligrade.client'
============================
CourseServiceClient.java
============================
package com.ibt.intelligrade.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.ServiceDefTarget;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
public class CourseServiceClient implements EntryPoint {
// Variable that stores the string retrieved from the server
String returnedString = null;
public void onModuleLoad() {
final Label label = new Label ("status");
Button b = new Button("GWT + Spring MVC + Hibernate JPA Demo",
new ClickListener() {
public void onClick(Widget sender) {
// Call remote service
runCourseService(label);
}
});
RootPanel.get().add(b);
RootPanel.get().add(label);
}
// In this method, you do invoke a method of the remote service.
// You also provide the callback method.
void runCourseService(final Label status){
// (1) Create the client proxy. Note that although you are
creating the
// service interface proper, you cast the result to the async
version of
// the interface. The cast is always safe because the
generated proxy
// implements the async interface automatically.
//
CourseServiceAsync myserv = (CourseServiceAsync) GWT
.create(CourseService.class);
// (2) Specify the URL at which our service implementation is
running.
// Note that the target URL must reside on the same domain and
port from
// which the host page was served.
//
ServiceDefTarget endpoint = (ServiceDefTarget) myserv;
String moduleRelativeURL = GWT.getModuleBaseURL() +
"gwt.smvc";
endpoint.setServiceEntryPoint(moduleRelativeURL);
// (3) Create an async callback to handle the result.
//
AsyncCallback callback = new AsyncCallback() {
public void onSuccess(Object result) {
status.setText ((String)result);
}
public void onFailure(Throwable caught) {
status.setText ("Failure occurred:
"+caught.getMessage());
}
};
// (4) Make the call. Control flow will continue immediately
and later
// 'callback' will be invoked when the RPC completes.
//
// Provide your own name.
myserv.runGwtSprMvcHibJpaDemo("Testing Demo", callback);
}
}
====================
CourseService.java
====================
package com.ibt.intelligrade.client;
import com.google.gwt.user.client.rpc.RemoteService;
public interface CourseService extends RemoteService{
public String runGwtSprMvcHibJpaDemo(String s);
}
============================
CourseServiceAsync.java
============================
package com.ibt.intelligrade.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface CourseServiceAsync {
public void runGwtSprMvcHibJpaDemo(String s, AsyncCallback
callback);
}
package: 'com.ibt.intelligrade.server'
============================
CourseServiceImpl.java
============================
package com.ibt.intelligrade.server;
import com.ibt.intelligrade.client.CourseService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
public class CourseServiceImpl extends RemoteServiceServlet implements
CourseService {
// Provide implementation logic.
public String runGwtSprMvcHibJpaDemo(String s) {
// run server logic here
// we'll add our spring mvc + jpa integration in next part
return "DONE " + s + "!";
}
}
We'll compile and run our GWT RPC application now. The GWT jars
required are:
gwt-user.jar
gwt-dev-linux.jar (or windows based on your operating system)
Compile using GWT compiler and make sure the application can be run in
hosted mode without any issues. Bundle the
'com.ibt.intelligrade.server' package as a jar, so we can use them in
our Spring MVC - GWT RPC integration project.
=========================
Here's the second part...
=========================
========================================
PART TWO - GWT + SPRING MVC INTEGRATION
========================================
We now create a Spring MVC + JPA Web application project. We'll group
all our application source files under 'com.ibt.intelligrade' package
again.
We'll focus only on the GWT + Spring MVC integration and will ignore
the usual spring configuration steps.
Add the following GWT jars to your library:
gwt-servlet.jar
========
STEP 1:
========
Copy the entire translated GWT web files
('com.ibt.intelligrade.CourseServiceClient') into your web folder.
Edit 'CourseServiceClient.html' in
'com.ibt.intelligrade.CourseServiceClient' folder under web packages
and make the following changes:
==================================================================
com.ibt.intelligrade.CourseServiceClient/CourseServiceClient.html
==================================================================
Hello
========
STEP 2:
========
Write an abstract GWTSpringController for GWT RPC servlet integration.
==========================
GWTSpringController.java
==========================
package com.ibt.intelligrade.mvc;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.WebApplicationContext;
import
org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
public abstract class GWTSpringController extends RemoteServiceServlet
implements Controller, ServletContextAware {
private ServletContext servletContext;
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
public ServletContext getServletContext() {
return servletContext;
}
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
super.doPost(request, response);
return null;
}
}
Now make the GWT RPC Servlet 'CourseServiceImpl' to extend this one,
instead of the RemoteServiceServlet.
NOTE: This already exists from the GWT project, edit the same one and
make the changes as mentioned above.
=======================
CourseServiceImpl.java
=======================
package com.ibt.intelligrade.server;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.ibt.intelligrade.client.CourseService;
import com.ibt.intelligrade.mvc.GWTSpringController;
import com.ibt.intelligrade.service.CourseManager;
import org.springframework.web.context.WebApplicationContext;
import
org.springframework.web.context.support.WebApplicationContextUtils;
public class CourseServiceImpl extends GWTSpringController implements
CourseService {
// Provide implementation logic.
public String runGwtSprMvcHibJpaDemo(String s) {
// run server logic here
WebApplicationContext applicationContext =
(WebApplicationContext)
WebApplicationContextUtils.getWebApplicationContext(getServletContext());
CourseManager courseManager = (CourseManager)
applicationContext.getBean("courseManager");
String result = courseManager.testSpringMvcJpaIntegration();
return result;
}
}
========
STEP 3:
========
Create 'intelligrade-servlet.xml' in WEB-INF folder to wire our GWT
RPC controller configuration along with the other Spring MVC beans.
=========================
intelligrade-servlet.xml
=========================
courseControllercourseServiceController
=========================
Here's the final part...
=========================
=================================================
PART THREE - GWT + SPRING MVC + JPA INTEGRATION
=================================================
========================
1. CONFIGURATION FILES
========================
Under Web folder
WEB-INF
========
web.xml
========
contextConfigLocation
/WEB-INF/applicationContext-intelligrade.xml
org.springframework.web.context.ContextLoaderListener
intelligrade
org.springframework.web.servlet.DispatcherServlet
2intelligrade*.html
30
index.jsp
WEB-INF
===================================
intelligrade-servlet.xml (already defined above)
====================================
applicationContext-intelligrade.xml
====================================
In Source folder..
Create an Persistence Unit configuration file called persistence.xml
- Name must be persistence.xml (the required META-INF folder will be
automatically created by NetBeans)
META-INF
================
persistence.xml
================
org.hibernate.ejb.HibernatePersistence
==================
2. DOMAIN CLASSES
==================
Create the following Domain Classes
- We have 2 domain objects named 'Course.java' and
'QuestionBank.java'
============
Course.java
============
package com.ibt.intelligrade.domain;
import com.ibt.intelligrade.domain.QuestionBank;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.*;
@Entity
@Table(name="course")
public class Course implements java.io.Serializable {
@Id @GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Basic()
private String name;
@Basic()
private String description;
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
private Set
questionBanks = new
HashSet (10);
/** Creates a new instance of Course */
public Course() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Set getQuestionBanks() {
return questionBanks;
}
public void setQuestionBanks(Set questionBanks) {
this.questionBanks = questionBanks;
}
public String toString() {
String retValue;
retValue = " Course Id: " + getId()
+ " Course Name: " + getName()
+ " Course Description: " + getDescription();
return retValue;
}
}
==================
QuestionBank.java
==================
package com.ibt.intelligrade.domain;
import java.io.Serializable;
import javax.persistence.*;
@Entity
@Table(name="questionbank")
public class QuestionBank implements Serializable{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@Basic()
private String name;
@Basic()
private String description;
@ManyToOne(fetch=FetchType.LAZY)
private Course parent;
/** Creates a new instance of QuestionBank */
public QuestionBank() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Course getParent() {
return parent;
}
public void setParent(Course parent) {
this.parent = parent;
}
public String toString() {
String retValue;
retValue = " QuestionBank Id: " + getId()
+ " QuestionBank Parent : " + getParent().getName()
+ " QuestionBank Name: " + getName()
+ " QuestionBank Description: " + getDescription();
return retValue;
}
}
===============================
3. Spring Service / DAO layer
===============================
===============
CourseDao.java
===============
package com.ibt.intelligrade.service;
import com.ibt.intelligrade.domain.Course;
import java.util.List;
public interface CourseDao {
void persist (Course course);
Course getReference (Course course);
List getAllCourse ();
void remove(Course crs);
}
===================
CourseDaoImpl.java
===================
package com.ibt.intelligrade.service;
import com.ibt.intelligrade.domain.Course;
import java.util.List;
import javax.persistence.*;
import org.springframework.orm.jpa.support.JpaDaoSupport;
public class CourseDaoImpl
implements CourseDao{
@PersistenceContext()
private EntityManager entityManager;
/** Creates a new instance of CourseDaoImpl */
public CourseDaoImpl() {
}
public void persist (Course course)
{
getEntityManager().persist(course);
}
public Course getReference (Course course)
{
return getEntityManager().getReference(course.getClass(),
course.getId());
}
public List getAllCourse (){
return getEntityManager().createQuery("from
Course").getResultList();
}
public void remove(Course crs) {
getEntityManager().remove (crs);
}
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
===================
CourseManager.java
===================
package com.ibt.intelligrade.service;
import com.ibt.intelligrade.domain.Course;
import java.util.List;
public interface CourseManager {
void persistCourse (Course course);
String testSpringMvcJpaIntegration();
}
=======================
CourseManagerImpl.java
=======================
package com.ibt.intelligrade.service;
import com.ibt.intelligrade.domain.Course;
import com.ibt.intelligrade.domain.QuestionBank;
import java.util.List;
import java.util.Set;
public class CourseManagerImpl implements CourseManager{
private CourseDao courseDao;
/**
* Creates a new instance of CourseManagerImpl
*/
public CourseManagerImpl() {
}
public CourseDao getCourseDao() {
return courseDao;
}
public void setCourseDao(CourseDao courseDao) {
this.courseDao = courseDao;
}
public void persistCourse (Course course)
{
courseDao.persist (course);
}
// Business method.. Testing the JPA Integration through DAO
public String testSpringMvcJpaIntegration() {
// PERSIST COURSE
Course course = new Course();
course.setName("JAVA");
course.setDescription("JAVA Standard Edition");
persistCourse (course);
StringBuilder stringBuilder = new StringBuilder ();
stringBuilder.append("
");
stringBuilder.append(" SAVED Course: "+course);
stringBuilder.append("
");
// PERSIST COURSE WITH QUESTION BANK COLLECTION
QuestionBank questionBank = new QuestionBank();
questionBank.setName("Java Question Bank");
questionBank.setDescription("JAVA question bank descritpion");
questionBank.setParent(course);
course = courseDao.getReference(course);
course.getQuestionBanks().add(questionBank);
persistCourse (course);
stringBuilder.append("
");
stringBuilder.append(" SAVED Course with QuestionBank:
"+questionBank);
stringBuilder.append("
");
// RETREIVE THE COURSE AND TEST IT
// DELETE THEM FINALLY
List courses = courseDao.getAllCourse();
for (Course crs : courses) {
stringBuilder.append("
");
stringBuilder.append(" RETREIVED Course: "+crs);
stringBuilder.append("
");
Set qbs = crs.getQuestionBanks();
for (QuestionBank qb : qbs) {
stringBuilder.append("
");
stringBuilder.append(" QuestionBank: "+qb);
stringBuilder.append("
");
}
// DELETE COURSE (AND THE QUESTION BANK COLLECTION)
courseDao.remove(crs);
stringBuilder.append("
");
stringBuilder.append("REMOVED Course: "+crs);
stringBuilder.append("
");
}
return stringBuilder.toString();
}
}
=========================
4. The Spring Controller
=========================
Write a pure spring 'CourseController' which would be the landing
page.
=======================
CourseController.java
=======================
package com.ibt.intelligrade.mvc;
import com.ibt.intelligrade.domain.Course;
import com.ibt.intelligrade.domain.QuestionBank;
import com.ibt.intelligrade.service.CourseManager;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.ParameterizableViewController;
import javax.persistence.*;
import java.util.*;
public class CourseController extends ParameterizableViewController {
/** Creates a new instance of HomeController */
public CourseController() {
}
protected ModelAndView handleRequestInternal(HttpServletRequest
request, HttpServletResponse response)
throws Exception {
return super.handleRequestInternal(request, response);
}
}
====================================
GWT + Spring MVC + JPA integration DONE!
**. Run your project and Enjoy!!
====================================