Blog about Liferay development, Portal and System administration solutions.

Archive for May, 2013

Liferay + Direct Web Remoting(DWR)

Direct Web Remoting

DWR is a Java library that enables Java on the server and JavaScript in a browser to interact and call each other as simply as possible.

DWR will generate the JavaScript to allow web browsers to securely call into Java code almost as if it was running locally. It can marshal virtually any data including collections, POJOs, XML and binary data like images and PDF files. All that is required is a security policy that defines what is allowed.

For Information check this link.

SAMPLE APPLICATION

The sample application has been developed to show the integration of DWR, Liferay MVC Portlet and it doesn’t attempt to show all the features of these frameworks but only shows how the integration works. It sets the stage for developing more complex portlets which can extensively make use of these frameworks.

Sample application consists of 3 portlets:

  1. Orders
  2. Order details
  3. Customer details .

Dependency jars:

  • dwr.jar

Step 1: Create a New Liferay portlet project .

Step 2: Add dwr.jar to the your project in the /docroot/WEB-INF/lib directory.

Step3: Update web.xml file by adding the below code.This adds the DWR servlet to the application. This servlet is used in the background to process requests and send responses back to the browser.


<servlet>
<servlet-name>dwr-invoker</servlet-name>
<servlet-class>uk.ltd.getahead.dwr.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>

Step 4: Create a file called dwr.xml in the WEB-INF directory using the below code.This is the DWR configuration file, which tells the container which classes are available in JavaScript. DWR reads this XML file and dynamically generates JavaScript code to represent Java classes as JavaScript classes. This enables you to offer the functionality offered by those Java classes in the browser.


<?xml version="1.0"?>
<!DOCTYPE dwr PUBLIC
"-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
"http://www.getahead.ltd.uk/dwr/dwr10.dtd">
<dwr>
<allow>
<create creator="new" javascript="MessagingBean">
<param name="class" value="com.liferay.dwr.sample.portlet.connector.MessagingBean"/>
</create>
</allow>
</dwr>

Create MockupDB and MessagingBean java classes:

MockupDB is a singleton class that simulates a database of customer orders


package com.liferay.dwr.sample.portlet.database;

import java.util.Hashtable;
import java.util.Map;

public class MockupDB {

private static MockupDB instance=new MockupDB();

private String[] orders=new String[4];
private Map orderDetails=new Hashtable();
private Map customerDetails=new Hashtable();

private MockupDB()
{
String ordStart="ORD";
orders[0]=ordStart+"00112";
orders[1]=ordStart+"00221";
orders[2]=ordStart+"00312";
orders[3]=ordStart+"00445";

orderDetails.put(orders[0],"1. WebSphere Everyplace Connection Manager<br/>"+ "2. WebSphere Portal");
orderDetails.put(orders[1],"1. DB2 Universal Database<br/>2. DB2 Everyplace");
orderDetails.put(orders[2],"1. Tivoli Access Manager for e-business <br/>2."+ "Tivoli Directory Integrator");
orderDetails.put(orders[3],"1. IBM System z9<br/>2. IBM System p5 550 Express");

customerDetails.put(orders[0],"<b>Systems and Technology Group</b><br/>"+ "Some Road<br/>Finland");
customerDetails.put(orders[1],"<b>Global Financing</b><br/>Another Street"+ "<br/>Finland");
customerDetails.put(orders[2],"<b>Software</b><br/>Yet Another Road"+ "<br/>Finland");
customerDetails.put(orders[3],"<b>Global Services</b><br/>Still Another "+ "Street<br/>Finland");
}

public static MockupDB getInstance()
{
return instance;
}

public String[] getOrders()
{
return orders;
}

public String getOrderDetails(String orderNro)
{
return (String)orderDetails.get(orderNro);
}

public String getCustomerDetails(String orderNro)
{
return (String)customerDetails.get(orderNro);
}
}

MessagingBean is a simple POJO.


package com.liferay.dwr.sample.portlet.connector;

import javax.servlet.http.HttpSession;

import com.liferay.dwr.sample.portlet.database.MockupDB;

public class MessagingBean {

public MessagingBean()
{
}

public String getOrderDetails(String orderNumber,HttpSession httpSession)
{

String orderDetails=MockupDB.getInstance().getOrderDetails(orderNumber);
httpSession.setAttribute("orderDetailsOrderNumber",orderNumber);
httpSession.setAttribute("orderDetails",orderDetails);
return orderDetails;
}

public String getCustomerDetails(String orderNumber,HttpSession httpSession)
{
String customerDetails=MockupDB.getInstance().getCustomerDetails(orderNumber);
httpSession.setAttribute("customerDetailsOrderNumber",orderNumber);
httpSession.setAttribute("customerDetails",customerDetails);
return customerDetails;
}
}

Step 5:  Create init.jsp file in the /docroot/html/common directory :


<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet"%>

<%@ page contentType="text/html"%>

<%@ page import="javax.portlet.PortletSession"%>
<%@ page import="com.liferay.dwr.sample.portlet.database.MockupDB"%>

<portlet:defineObjects />

Create javascript.jsp file file in the /docroot/html/orders directory :

This file imports a JavaScript library from DWR (engine.js) and the dynamically created library MessagingBean.js. Notice that MessagingBean.js uses the same name as the Java bean introduced in dwr.xml file, DWR generates MessagingBean.js. The DWR framework uses the engine.js library.

sendOrderNr() functions call to the MessagingBean functions defined in MessagingBean POJO class. DWR adds the HttpSession automatically to the method call. The last parameter in the JavaScript function is the callback function.


<%@include file="/html/common/init.jsp"%>

<script type="text/javascript"
src='<%=renderResponse.encodeURL(renderRequest.getContextPath()
+ "/dwr/interface/MessagingBean.js")%>'></script>
<script type="text/javascript"
src='<%=renderResponse.encodeURL(renderRequest.getContextPath()
+ "/dwr/engine.js")%>'></script>

<script type="text/javascript">
function <portlet:namespace />sendOrderNr(orderNr) {
document.getElementById("orderDetailsOrderNumber").innerHTML = orderNr;
document.getElementById("customerDetailsOrderNumber").innerHTML = orderNr;
MessagingBean.getOrderDetails(orderNr,
<portlet:namespace />showOrderDetails);
MessagingBean.getCustomerDetails(orderNr,
<portlet:namespace />showCustomerDetails);

return false;
}

function <portlet:namespace />showOrderDetails(orderDetails) {
document.getElementById("orderDetails").innerHTML = orderDetails;
return false;
}

function <portlet:namespace />showCustomerDetails(customerDetails) {
document.getElementById("customerDetails").innerHTML = customerDetails;
return false;
}
</script>

Create view.jsp file file in the /docroot/html/orders directory :


<%@ include file="/html/common/init.jsp"%>
<%-- <%@ include file="/html/orders/javascript.jsp" %> --%>

<jsp:include page="/html/orders/javascript.jsp" />

<div style="margin: 6px">
<H4 style="margin-bottom: 3px">Orders</H4>
<table cellspacing="0" cellpadding="5" border="1">
<%
MockupDB database = MockupDB.getInstance();

String[] orders = database.getOrders();
for (int i = 0; i < orders.length; i++) {
%>
<tr>

<td><%="000" + String.valueOf(i + 1)%></td>
<td><a href=""
onclick="return <portlet:namespace />sendOrderNr('<%=orders[i]%>');"><%=orders[i]%></a></td>
</tr>
<%
}
%>

</table>
</div>

Create view.jsp file in the /docroot/html/orderdetails directory :


<%@include file="/html/common/init.jsp"%>

<div style="margin: 6px">

<H4 style="margin-bottom: 3px">Order details</H4>

<table border="1">
<tr>
<th>Order number</th>
<th>Order details</th>
</tr>

<tr>
<%
String orderDetailsOrderNumber = (String) renderRequest
.getPortletSession().getAttribute(
"orderDetailsOrderNumber",
PortletSession.APPLICATION_SCOPE);
String orderDetails = (String) renderRequest.getPortletSession()
.getAttribute("orderDetails",
PortletSession.APPLICATION_SCOPE);

if (orderDetailsOrderNumber == null) {
orderDetailsOrderNumber = "";
}

if (orderDetails == null) {
orderDetails = "";
}
%>
<td><div id="orderDetailsOrderNumber"><%=orderDetailsOrderNumber%></div></td>
<td><div id="orderDetails"><%=orderDetails%></div></td>
</tr>

</table>
</div>

Create view.jsp file in the /docroot/html/customerdetails directory :


<%@include file="/html/common/init.jsp"%>

<div style="margin: 6px">

<H4 style="margin-bottom: 3px">Customer details</H4>
<table cellspacing="0" cellpadding="5" border="1">
<tr>
<th>Order number</th>
<th>Customer details</th>
</tr>

<tr>
<%
String customerDetailsOrderNumber = (String) renderRequest
.getPortletSession().getAttribute(
"customerDetailsOrderNumber",
PortletSession.APPLICATION_SCOPE);
String customerDetails = (String) renderRequest.getPortletSession()
.getAttribute("customerDetails",
PortletSession.APPLICATION_SCOPE);

if (customerDetailsOrderNumber == null) {
customerDetailsOrderNumber = "";
}

if (customerDetails == null) {
customerDetails = "";
}
%>
<td><div id="customerDetailsOrderNumber"><%=customerDetailsOrderNumber%></div></td>
<td><div id="customerDetails"><%=customerDetails%></div></td>
</tr>

</table>
</div>

Portlet.xml

<?xml version="1.0"?>

<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd" version="2.0">

<portlet>
<portlet-name>orders</portlet-name>
<display-name>Orders Portlet</display-name>
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
<init-param>
<name>view-template</name>
<value>/html/orders/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<resource-bundle>content/Language</resource-bundle>
<portlet-info>
<title>Orders Portlet</title>
<short-title>Orders Portlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
<portlet>
<portlet-name>customerdetails</portlet-name>
<display-name>Customer Details Portlet</display-name>
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
<init-param>
<name>view-template</name>
<value>/html/customerdetails/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>Customer Details Portlet</title>
<short-title>Customer Details Portlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
<portlet>
<portlet-name>orderdetails</portlet-name>
<display-name>Order Details Portlet</display-name>
<portlet-class>com.liferay.util.bridges.mvc.MVCPortlet</portlet-class>
<init-param>
<name>view-template</name>
<value>/html/orderdetails/view.jsp</value>
</init-param>
<expiration-cache>0</expiration-cache>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<resource-bundle>content/Language</resource-bundle>
<portlet-info>
<title>Order Details Portlet</title>
<short-title>Order Details Portlet</short-title>
<keywords></keywords>
</portlet-info>
<security-role-ref>
<role-name>administrator</role-name>
</security-role-ref>
<security-role-ref>
<role-name>guest</role-name>
</security-role-ref>
<security-role-ref>
<role-name>power-user</role-name>
</security-role-ref>
<security-role-ref>
<role-name>user</role-name>
</security-role-ref>
</portlet>
</portlet-app>

CheckPoint:

dwr