Download as ppt, pdf, or txt
Download as ppt, pdf, or txt
You are on page 1of 34

Direct Web Remoting,

Hibernate and Dojo.E

“Easy Ajax for Java”


Joel Barciauskas
October 3, 2008
What is DWR?
• “Easy Ajax for Java” implies two parts
– Server – Java servlet
– Client – JavaScript auto-generated by the Java
servlet
• Enables JSON to JavaBean serialization
• Exposes selected methods and JavaBean
properties on the server as client-side
JavaScript methods and objects
• Reverse Ajax – IMB-like functionality
Why use DWR? Why not?
• Pros
– Avoid replication of effort defining model objects on both
server and client
– No XHR boilerplate required
– No serialization boilerplate
– JSON is fastest format to serialize/deserialize in the browser
• Cons
– Less control over network requests
 E.g., harder to bundle requests
– Not RESTful, all requests processed through POST data
rather than URLs
 Best for single-page applications
Let’s see it
• Application: Simple database create and
read
• Using: JavaScript, DWR 2.0, Hibernate
3.0, Derby
• Shell:
http://source.nexaweb.com/svn/repos/trunk/tu
Create your domain class
(JavaBean)
• src/events/Event.java
package events;
import java.util.Date;
public class Event {
private Long id;
private String title;
private Date date;
public Event() {}
public Long getId() { return id; }
private void setId(Long id) { this.id = id; }
public Date getDate() { return date; }
public void setDate(Date date) { this.date = date; }
public String getTitle() { return title; }
public void setTitle(String title) { this.title = title; }
}
Create Hibernate XML Mapping
• src/events/Event.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-
//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-
mapping-3.0.dtd">
<hibernate-mapping>
<class name="events.Event" table="EVENTS">
</class>
</hibernate-mapping>
Add Property Mappings
• src/events/Event.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping
DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-
3.0.dtd">
<hibernate-mapping>
<class name="events.Event" table="EVENTS">
<id name="id" column="EVENT_ID">
<generator class="native"/>
</id>
<property name="date" type="timestamp"
column="EVENT_DATE"/>
<property name="title"/>
</class>
</hibernate-mapping>
Create Hibernate Configuration
• src/hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">org.apache.derby.jdbc.EmbeddedDriver</property>
<property name="connection.url“>jdbc:derby:eventDB;create=true</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.DerbyDialect</property>
<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">create</property>
<mapping resource="events/Event.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Create SessionFactory instance
• src/util/HibernateUtil.java
package util;
import org.hibernate.*;
import org.hibernate.cfg.*;
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try { // Create the SessionFactory from hibernate.cfg.xml
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
// Make sure you log the exception, as it might be swallowed
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() { return sessionFactory; }
}

Note: This can also be achieved through the Spring integration – “use the Spring
OpenSessionInViewFilter which will ensure that a Hibernate Session is open” (http://
directwebremoting.org/dwr/server/hibernate)
Create an Event Manager
• src/events/EventManager.java
package events;
import org.hibernate.Session;
import java.util.Date;
import java.util.List;
import util.HibernateUtil;
public class EventManager {
public void createAndStoreEvent(String title, Date theDate) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDate(theDate);
session.save(theEvent);
session.getTransaction().commit();
}

public List listEvents() {


Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List result = session.createQuery("from Event").list();
session.getTransaction().commit();
return result;
}
}
Add the DWR servlet to web.xml
• WebContent/WEB-INF/web.xml
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<display-name>DWR Servlet</display-name>
<servlet-class>
org.directwebremoting.servlet.DwrServlet
</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dwr-invoker</servlet-name>
<url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
Create a Remote Proxy and Expose Remote Methods

• Src/events/EventManager.java
package events;
import org.directwebremoting.annotations.RemoteMethod;
import org.directwebremoting.annotations.RemoteProxy;
import org.hibernate.Session;
import java.util.Date;
import java.util.List;
import util.HibernateUtil;

@RemoteProxy
public class EventManager {
@RemoteMethod
public void createAndStoreEvent(String title, String theDate) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
Event theEvent = new Event();
theEvent.setTitle(title);
theEvent.setDateString(theDate);
session.save(theEvent);
session.getTransaction().commit();
}

@RemoteMethod
public List listEvents() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
List result = session.createQuery("from Event").list();
session.getTransaction().commit();
return result;
}
}
Annotate Event as a Data Transfer
Object
• src/events/Event.java
package events;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.directwebremoting.annotations.DataTransferObject;
import org.directwebremoting.annotations.RemoteProperty;

@DataTransferObject
public class Event {

@RemoteProperty
private Long id;
@RemoteProperty
private String title;
private Date date;
public Event() {}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
@RemoteProperty
public String getDateString() {
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
return sdf.format(this.date);
}

[continued on next slide]


Annotate Event as a Data Transfer Object
(con’t)
• src/events/Event.java [continued]

@RemoteProperty
public void setDateString(String dateStr) {
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
try {
this.date = sdf.parse(dateStr);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}

Note: We added getDateString and setDateString here, because there is no implicit conversion available between
JavaScript dates and Java dates – mostly arrays, strings, BigNumber, and primitives. See
http://directwebremoting.org/dwr/server/dwrxml/converters for more information.
Update web.xml
• WebContent/WEB-INF/web.xml
<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class>
<init-param>
<param-name>classes</param-name>
<param-value>
events.Event,
events.EventManager
</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
Using DWR Debug Mode
• Go to
http://localhost:8080/DWRExample/dwr/
– Click “EventManager”
– Enter “Event 1” in the first parameter of
createAndStoreEvent
– Enter “10/01/2008” in the second parameter

• Click the Execute button


• Click the Execute button next to
listEvents()
Let’s add DWR on the client side
• File->New->Web->HTML->
WebContent/index.html
• Open and edit title “DWR Example”
• Go back to
http://localhost:8080/DWRExample/dwr/test/E
and copy and paste the script tags
More Dojo boilerplate
• Paste the following too:
<script type="text/javascript" src="js/dojo/dojo/dojo.js"
djConfig="isDebug: true, parseOnLoad: true"></script>
<link rel="stylesheet" type="text/css"
href="js/dojo/dojo/resources/dojo.css" />
<link rel="stylesheet" type="text/css"
href="js/dojo/dijit/themes/tundra/tundra.css" />
<link rel="stylesheet" type="text/css"
href="js/dojo/dojox/grid/_grid/Grid.css" />
<link rel="stylesheet" type="text/css"
href="js/dojo/dojox/grid/_grid/tundraGrid.css" />

<script type="text/javascript">
dojo.require("dijit.form.Button");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.DateTextBox");
dojo.require("dojox.grid.Grid");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dojoe.dojoe");
</script>
Add Dojo.E
• Add tundra class to body tag:
<body class="tundra">
• Create XML file
WebContent/dwrDojoE.xml
• And add tag
<script type="text/xml"
dojoType="dojoe.XmlScript"
src="dwrDojoE.xml"></script>
Edit Dojo.E
• WebContent/dwrDojoE.xml
<ui xmlns="html" xmlns:dijit="dijit"
xmlns:dojox="dojox">
<dijit:form.Button>
Refresh
</dijit:form.Button>
<dojox:grid.Grid id="gridNode" jsId="grid"
elasticView="0" style="height:300px;
width:500px"/>
</ui>
Where’s the Grid?!?
Create a grid layout
• WebContent/index.html
<body class="tundra">'
<script type="text/javascript">
var layout = [{
cells: [[
{
name: 'Event ID',
field: 'id',
width: 'auto'
},
{
name: 'Date',
field: 'dateString',
width: 'auto'
}, {
name: 'Event',
field: 'title',
width: 'auto'
}]]
}];
</script>

Note the correlation between the field values above and the RemoteProperty defintions of Event.java
Add the layout to the Grid
• WebContent/dwrDojoE.xml
<ui >
<dijit:form.Button>
Refresh
</dijit:form.Button>
<dojox:grid.Grid id="gridNode"
structure=“layout”
jsId="grid" elasticView="0"
style="height:300px; width:500px"/>
</ui>
Now let’s get some data
• WebContent/index.html
var putEvents = function(list){
var dataStore = new Array;
dataStore["items"] = list;
dataStore["label"] = "title";

var model = new dojox.grid.data.DojoData(null, null, {


jsId: 'model',
store: new dojo.data.ItemFileReadStore({
data: dataStore
}),
query: {
title: '*'
}
});

grid.setModel(model);
grid.refresh();
grid.render();
};
Update Dojo.E
• WebContent/dwrDojoE.xml
<ui>
<dijit:form.Button
onClick="EventManager.listEvents(putEvents)">
Refresh
</dijit:form.Button>
<dojox:grid.Grid id="gridNode" jsId="grid"
elasticView="0" style="height:300px;
width:500px"/>
</ui>
Click Refresh
Create a method to create an
event
• WebContent/index.html
var createEvent = function(titleId, dateId){
var title = dojo.byId(titleId).value;
var date = dojo.byId(dateId).value;
EventManager.createAndStoreEvent(title,
date);
EventManager.listEvents(putEvents);
};
Let’s Add Input Controls
• WebContent/dwrDojoE.xml
<ui >
<dijit:form.Button onClick="EventManager.listEvents(putEvents)">
Refresh
</dijit:form.Button>
<dojox:grid.Grid id="gridNode" jsId="grid" structure="layout" elasticView="0“
style="height:300px; width:500px"/>
<label for="eventTitle" style="float: left;">Event Title:</label>
<dijit:form.TextBox style="float: left;" id="eventTitle" value=""/>
<label for="eventDate" style="float: left;">Event Date:</label>
<dijit:form.DateTextBox id="eventDate" value="" style="float: left;"/>
<dijit:form.Button style="float: left;“
onclick="createEvent('eventTitle', 'eventDate')" label="Add Event">
</dijit:form.Button>
</ui>
Reload the page
Enter a title and date
Load data at startup
• WebContent/index.html
dojo.addOnLoad(function() {
EventManager.listEvents(putEvents);
});
Final note
• If using more complex object models with
Hibernate, use the
HibernateBeanConverter3 – See http://
directwebremoting.org/dwr/server/hibernate

You might also like