Jean-Michel Garcia

Developer…

Embedding a GWT / SmartGWT application in a Java Portlet (Liferay) using Maven

Posted date 4th mars 2012 and last modified on 19th septembre 2013, by Jean-Michel GARCIA 8 Comments

For a research project, I was once able to embed a GWT application using the SmartGWT framework in a Java Portlet. So, as I had faced some issues and problems, I’ve decided to post a small tutorial with guidelines to help people trying to achieve the same thing.

Little precisions:

  • The portlet was following the JSR 268
  • GWT version 2.3
  • SmartGWT version 2.5
  • Firefox was the only browser I was targeting
  • I was using Maven to manage my projects (but same thing could be done using Ant)

Thanks to « Antoniodb » from the SmartGWT community for providing some precious informations.

I do not intend to be an expert in those products. I’m only sharing my experience. There is another way of doing this (throught an html iframe) but I’m not detailing it.

    To integrate a SmartGWT application in a portlet, here are the steps I recommend to follow :
  • Create an empty JSR-268 portlet and configure it
  • Configure the SmartGWT app to work with the portlet
  • Mix the projects
  • Solve the Liferay CSS issues

The first part, is to create an empty JSR-268 portlet and configure it

No big deal in this part, we are going to create an empty portlet following the JSR 268 specification. In the main JSP page, we need to define an entry point for our SmartGWT module.

This is our jsp page

<%@ page contentType="text/html"%>
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %>
<%
        String gwtSource=(String) request.getAttribute("urlGWT");
        String urlSmartGWT=(String) request.getAttribute("urlSmartGWT");
%&gt;<script type="text/javascript">// <![CDATA[
var isomorphicDir='<%=urlSmartGWT %>' ;
// ]]></script>
<script type="text/javascript" src="&lt;%=gwtSource %&gt;">// <![CDATA[

 

The GWT compile process will generate a lot of html and javascript files. But the “applicationame.nocache.js” is our entry point one. The gwtSource will be used to set the url of this file.
The urlSmartGWT will be used to set the isomorphicDir (the directory where SmartGWT search for its resources).

We also added a div that will contain the whole SmartGWT application once launched.

 

Now we are going to use the doView method, to set properly « gwtSource » and « urlSmartGWT » :

String urlGWT = response.encodeURL(request.getContextPath()+ "/ModuleName/ModuleName.nocache.js");
request.setAttribute("urlGWT", urlGWT);
 
String urlSmartGWT = response.encodeURL(request.getContextPath()+ "/ModuleName/sc/");
request.setAttribute("urlSmartGWT", urlSmartGWT);

Configure the SmartGWT app to work with the portlet

To allow our SmartGWT module to be inserted into our JSP page, we have to add our outmermost layout manager into the div we defined before. We do that using this line of code instead of calling show() or draw():

RootPanel.get("myApplicationDIV").add("MyOutermostLayoutManager");

When I used this approach, SmartGWT had some problems finding the image dir. So I’ve added this in the beginning of my onModuleLoad() method :

if (GWT.isProdMode())
{
	Page.setAppImgDir("/MyPortletName/images/");
}

Another annoying problem is that SmartGWT uses high zIndex values (sometimes above 190 000), and this is not compliant with the Liferay zIndex. This results in your application getting rendered above the Liferay menus. To solve that, there is a possible solution :

To your outermost SmartGWT layout manager (any Canvas, Layout, etc), add this handler :

 

MyOutermostLayoutManager.addDrawHandler(new DrawHandler()
{
	@Override
	public void onDraw(DrawEvent event)
	{
		setZIndex(0);
	}
});

Mix the projects

This is the way I managed my java projects (maybe a better solution exists).

  1. One eclipse project containing my GWT / SmartGWT module.
  2. Another eclipse project containing my JSP portlet

When running in test mode, I only use the first project (using the embedded jetty servlet container).

When I was led to test the application under Liferay I used the second one.

Every time I wanted to deploy the portlet project, I copy the source files from SmartGWT project using the Maven Ant run plugin :

<plugin>
	<artifactId>maven-antrun-plugin</artifactId>
	<executions>
		<execution>
		<id>Copying sources from the original project </id>
			<phase>generate-sources</phase>
			<goals>
				<goal>run</goal>
			</goals>
			<configuration>
				<tasks>
					<copy todir="target/generated-sources/imported">							
						<fileset dir="../../application-directory/src/main/java" />
					</copy>
				</tasks>
			</configuration>
		</execution>
	</executions>
</plugin>

To make this approach work, we have to add this generated-sources/imported dir to the list of the known sources directories. Again this is easily done using the build helper Maven plugin :

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>build-helper-maven-plugin</artifactId>
	<executions>
		<execution>
			<id>add-portlet-source</id>
			<phase>process-sources</phase>
			<goals>
				<goal>add-source</goal>
			</goals>
			<configuration>
				<sources>
					<!-- use the imported sources -->
					<source>target/generated-sources/imported</source>
				</sources>
			</configuration>
		</execution>
	</executions>
</plugin>

After that, the Portlet project can compile the GWT code imported from the first project :

<plugin>
	<groupId>org.codehaus.mojo</groupId>
	<artifactId>gwt-maven-plugin</artifactId>
	<executions>
		<execution>
			<configuration>
				<style>OBF</style>
				</configuration>
					<goals>
						<goal>compile</goal>
					</goals>
		</execution>
	</executions>
</plugin>

Solve the Liferay CSS issues

Finally, if you are using the Liferay portal you will probably experience some issues regarding the scrollbars. I named this issue : « Scrollbars gone crazy » (more info here).

In a short way, the problem is that the Liferay CSS (defined in the theme) is interfering with the SmartGWT CSS. I filled an issue report at Liferay’s site( more info here) but no one seems to be interested on it.
There is many ways to solve this, but I choose the approach modifying the Liferay theme. So a small solution is to add this rule in the Liferay CSS (best place to do that is in the custom.css file) :

table {
	display:table;
	border-collapse:separate;
	margin-top:0;
	margin-bottom:0;
	-moz-box-sizing:border-box
	text-indent:0;
}

I don’t know if all these settings are mandatory, but they solved my issues whens using Firefox.

8 Responses so far.

  1. [...] for Liferay and Gwt Integration….Thanks & Regards Rewati Ramanoff-topic, but here it goes : http://www.jmichelgarcia.com/2012/gwt-smartgwt-in-a-liferay-portlet/ Flag Please sign in to flag this as [...]

  2. Tabitha dit :

    When someone writes an piece of writing he/she maintains the idea of
    a user in his/her mind that how a user can understand it.
    Therefore that’s why this article is outstdanding. Thanks!

  3. Bolat dit :

    Hi, there

    What does response means in the

    "String urlGWT = response.encodeURL(request.getContextPath()+ 
    "/ModuleName/ModuleName.nocache.js");"

    context?

    Is it RenderRequest or HttpServletRequest?

    I did all steps but there are some errors like

    • Jean-Michel GARCIA dit :

      Your comment was maybe filtered. What error are you encountering ? Take a look here for the response object : http://www.tutorialspoint.com/jsp/jsp_implicit_objects.htm

      • Bolat dit :

        Now I got it. I have to use doView() method in view.jsp page right?

        Then could you delete my last comment about portlet?

        Thank you in advance!

        • Jean-Michel GARCIA dit :

          done. That is it. Just take note that the :

          request.getAttribute();

          code is actually placed inside the JSP file itself.

          Regards.

          • Bolat dit :

            Hi, Jean-Michel

            I have some problems with rendering tables.

            GWT project successfully integrated into Liferay Portlet. Portlet shows one table and when user click on a cell it creates another table on the right corner. When I use your method (div container) table appear not properly ( in the bottom of page) even though I setWidth(), setHeight() to the VLayout. How can I fix this issue with wrong position while rendering tables?

          • Jean-Michel GARCIA dit :

            Try setting a fixed sized on the html DIV and then setting setWidth100() and setHeight100() on the outer VLayout. How are you rendering your tables ? Don’t use draw()