|
Vaadin supports running applications as portlets, as defined in the JSR-168 (Java Portlet API) and JSR-286 (Java Portlet API 2.0) standards. While providing generic support for all portals implementing the standards, Vaadin especially supports the Liferay portal and the needed portal-specific configuration is given below for Liferay. You can deploy the Vaadin demo package WAR (available from the download site) directly to a portal such as Liferay. It contains all the necessary portlet configuration files. For optimal performance with Liferay, you can install the Vaadin library and other needed resources in Liferay as described later in this section. You can find more documentation and examples from the Vaadin Developer's Site at Deploying a Vaadin application as a portlet is essentially just as easy as deploying a regular application to an application server. You do not need to make any changes to the application itself, but only the following:
Installing the widget set and themes to the portal is required for running two or more Vaadin portlets simultaneously in a single portal page. As this situation occurs quite easily, we recommend installing them in any case. In addition to the Vaadin library, you will need to copy the How you actually deploy a WAR package depends on the portal. In Liferay, you simply drop it to the While you can create the needed deployment descriptors manually for any existing Vaadin application, as described in subsequent sections, the Vaadin Plugin for Eclipse provides a wizard for easy creation of portal application projects. Creation of a portal application project is almost identical to the creation of a regular application project. For a full treatment of the New Project Wizard and the possible options, please see Section 2.4.1, “Creating the Project”.
To deploy a portlet WAR in a portal, you need to provide the basic The portlet WAR must include a portlet descriptor located at <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.0"
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">
<portlet>
<portlet-name>Portlet Example portlet</portlet-name>
<display-name>Vaadin Portlet Example</display-name>
<!-- Map portlet to a servlet. -->
<portlet-class>
com.vaadin.terminal.gwt.server.ApplicationPortlet2
</portlet-class>
<init-param>
<name>application</name>
<!-- The application class with package name. -->
<value>com.example.myportlet.MyportletApplication</value>
</init-param>
<!-- Supported portlet modes and content types. -->
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
<!-- Not always required but Liferay requires these. -->
<portlet-info>
<title>Vaadin Portlet Example</title>
<short-title>Portlet Example</short-title>
</portlet-info>
</portlet>
</portlet-app> Listing supported portlet modes in The portlet deployment descriptor for Portlet 1.0 API is largely the same as for Portlet 2.0. The main differences are:
Below is an example of a complete deployment descriptor for Portlet 1.0: <?xml version="1.0" encoding="UTF-8"?>
<portlet-app
version="1.0"
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
<portlet>
<!-- Must not be the same as servlet name. -->
<portlet-name>Portlet Example portlet</portlet-name>
<display-name>Vaadin Portlet Example</display-name>
<!-- Map portlet to a servlet. -->
<portlet-class>
com.vaadin.terminal.gwt.server.ApplicationPortlet
</portlet-class>
<init-param>
<name>application</name>
<!-- Must match the servlet URL mapping in web.xml. -->
<value>portletexample</value>
</init-param>
<!-- Supported portlet modes and content types. -->
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
<!-- Not always required but Liferay requires these. -->
<portlet-info>
<title>Vaadin Portlet Example</title>
<short-title>Portlet Example</short-title>
</portlet-info>
</portlet>
</portlet-app> The value of the application parameter must match the context in the <servlet-mapping>
<servlet-name>Portlet Example</servlet-name>
<url-pattern>/portletexample/*</url-pattern>
</servlet-mapping> In fact, it would also match the If you have just one Vaadin application that you ever need to run in your portal, you can just deploy the WAR as described above and that's it. However, if you have multiple applications, especially ones that use different custom widget sets, you run into problems, because a portal window can load only a single Vaadin widget set at a time. You can solve this problem by combining all the different widget sets in your different applications into a single widget set using inheritance or composition.
For example, the portal demos defined in the
<portlet>
...
<!-- Use the portal default widget set for all portal demos. -->
<init-param>
<name>widgetset</name>
<value>com.vaadin.portal.gwt.PortalDefaultWidgetSet</value>
</init-param>
...
The If your portlets are contained in multiple WARs, which can happen quite typically, you need to install the widget set and theme portal-wide so that all the portlets can use them. See Section 11.8.5, “Installing Vaadin in Liferay” on configuring the widget sets in the portal itself. Liferay requires a special Below is an example descriptor for the earlier portlet example: <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE liferay-portlet-app PUBLIC
"-//Liferay//DTD Portlet Application 4.3.0//EN"
"http://www.liferay.com/dtd/liferay-portlet-app_4_3_0.dtd">
<liferay-portlet-app>
<portlet>
<!-- Matches definition in portlet.xml. -->
<!-- Note: Must not be the same as servlet name. -->
<portlet-name>Portlet Example portlet</portlet-name>
<instanceable>true</instanceable>
<ajaxable>false</ajaxable>
</portlet>
</liferay-portlet-app> See Liferay documentation for further details on the The The following display configuration, which is included in the demo WAR, puts the Vaadin portlets under the "Vaadin" category, as shown in Figure 11.11, “Portlet Categories in Add Application Window”. <?xml version="1.0"?>
<!DOCTYPE display PUBLIC
"-//Liferay//DTD Display 4.0.0//EN"
"http://www.liferay.com/dtd/liferay-display_4_0_0.dtd">
<display>
<category name="Vaadin">
<portlet id="Portlet Example portlet" />
</category>
</display> See Liferay documentation for further details on how to configure the categories in the
The name=Portlet Example portlet short-description=myportlet module-group-id=Vaadin module-incremental-version=1 #change-log= #page-uri= #author= license=Proprietary portal-dependency-jars=\ vaadin.jar
The Hello World program that runs as a portlet is no different from a regular Vaadin application, as long as it doesn't need to handle portlet actions, mode changes, and so on. import com.vaadin.Application;
import com.vaadin.ui.*;
public class PortletExample extends Application {
@Override
public void init() {
Window mainWindow = new Window("Portlet Example");
Label label = new Label("Hello Vaadin user");
mainWindow.addComponent(label);
setMainWindow(mainWindow);
}
} In addition to the application class, you need the descriptor files, libraries, and other files as described earlier. Figure 11.12, “Portlet Project Structure in Eclipse” shows the complete project structure under Eclipse. Installed as a portlet in Liferay from the Add Application menu, the application will show as illustrated in Figure 11.13, “Hello World Portlet”. Loading widget sets, themes, and the Vaadin JAR from a portlet is possible as long as you have a single portlet, but causes a problem if you have multiple portlets. To solve this, Vaadin portlets need to use a globally installed widget set, themes, and Vaadin JAR. They, and all the required configuration, are bundled with Liferay 5.3 and later, but if you are using an earlier version of Liferay or use a custom widget set, custom themes, or a specific version of Vaadin, you will need to do the configuration manually. In these instructions, we assume that you use Liferay bundled with Apache Tomcat, although you can use many other application servers with Liferay just as well. The Tomcat installation is included in the Liferay installation package, under the
The Vaadin JAR should be put in
The widget set needs to be located at You need to define the widget set, the theme, and the JAR in the Below is an example of a # Path under which the VAADIN directory is located. # (/html is the default so it is not needed.) # vaadin.resources.path=/html # Portal-wide widget set vaadin.widgetset=com.vaadin.portal.gwt.PortalDefaultWidgetSet # Theme to use vaadin.theme=reindeer The allowed parameters are:
You will need to restart Liferay after creating or modifying the Portals such as Liferay are not AJAX applications but reload the page every time a user interaction requires data from the server. They consider a Vaadin application to be a regular web application that works by HTTP requests. All the AJAX communications required by the Vaadin application are done by the Vaadin Client-Side Engine (the widget set) past the portal, so that the portal is unaware of the communications. The only way a portal can interact with an application is to load it with a HTTP request; reloading does not reset the application. The Portlet 2.0 API supports four types of requests: render, action, resource, and event requests. The old Portlet 1.0 API supports only the render and action requests. Requests can be caused by user interaction with the portal controls or by clicking action URLs displayed by the portlet. You can handle portlet requests by implementing the
The
You need to have the You can also define portal actions that you can handle in the You add your portlet request listener to the application context of your application, which is a // Check that we are running as a portlet.
if (getContext() instanceof PortletApplicationContext2) {
PortletApplicationContext2 ctx =
(PortletApplicationContext2) getContext();
// Add a custom listener to handle action and
// render requests.
ctx.addPortletListener(this, new MyPortletListener());
} else {
getMainWindow().showNotification(
"Not initialized via Portal!",
Notification.TYPE_ERROR_MESSAGE);
} The handler methods receive references to request and response objects, which are defined in the Java Servlet API. Please refer to the Servlet API documentation for further details. The PortletDemo application included in the demo WAR package includes examples of processing mode and portlet window state changes in a portlet request listener. Portals support three portlet modes defined in the Portlet API: view, edit, and help modes. The view mode is the default and the portal can have buttons to switch the portlet to the other modes. In addition to the three predefined modes, the Portlet API standards allow custom portlet modes, although portals may support custom modes to a varying degree.
You need to define which portlet modes are enabled in the
<!-- Supported portlet modes and content types. -->
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>edit</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
Changes in the portlet mode are received as resource requests, which you
can handle with a The following complete example (for Portlet 2.0) shows how to handle the three built-modes in a portlet application. // Use Portlet 2.0 API
import com.vaadin.terminal.gwt.server.PortletApplicationContext2;
import com.vaadin.terminal.gwt.server.PortletApplicationContext2.PortletListener;
public class PortletModeExample extends Application
implements PortletListener {
Window mainWindow;
ObjectProperty data; // Data to view and edit
VerticalLayout viewContent = new VerticalLayout();
VerticalLayout editContent = new VerticalLayout();
VerticalLayout helpContent = new VerticalLayout();
@Override
public void init() {
mainWindow = new Window("Myportlet Application");
setMainWindow(mainWindow);
// Data model
data = new ObjectProperty("<h1>Heading</h1>"+
"<p>Some example content</p>");
// Prepare views for the three modes (view, edit, help)
// Prepare View mode content
Label viewText = new Label(data, Label.CONTENT_XHTML);
viewContent.addComponent(viewText);
// Prepare Edit mode content
RichTextArea editText = new RichTextArea();
editText.setCaption("Edit the value:");
editText.setPropertyDataSource(data);
editContent.addComponent(editText);
// Prepare Help mode content
Label helpText = new Label("<h1>Help</h1>" +
"<p>This helps you!</p>",
Label.CONTENT_XHTML);
helpContent.addComponent(helpText);
// Start in the view mode
mainWindow.setContent(viewContent);
// Check that we are running as a portlet.
if (getContext() instanceof PortletApplicationContext2) {
PortletApplicationContext2 ctx =
(PortletApplicationContext2) getContext();
// Add a custom listener to handle action and
// render requests.
ctx.addPortletListener(this, this);
} else {
mainWindow.showNotification("Not running in portal",
Notification.TYPE_ERROR_MESSAGE);
}
}
// Dummy implementations for the irrelevant request types
public void handleActionRequest(ActionRequest request,
ActionResponse response,
Window window) {
}
public void handleRenderRequest(RenderRequest request,
RenderResponse response,
Window window) {
}
public void handleEventRequest(EventRequest request,
EventResponse response,
Window window) {
}
public void handleResourceRequest(ResourceRequest request,
ResourceResponse response,
Window window) {
// Switch the view according to the portlet mode
if (request.getPortletMode() == PortletMode.EDIT)
window.setContent(editContent);
else if (request.getPortletMode() == PortletMode.VIEW)
window.setContent(viewContent);
else if (request.getPortletMode() == PortletMode.HELP)
window.setContent(helpContent);
}
}
Figure 11.14, “Portlet Modes in Action” shows the resulting portlet in the three modes: view, edit, and help. In Liferay, the edit mode is shown in the popup menu as a Preferences item. In some cases, it can be useful to implement certain modes of a portlet as pure HTML or JSP pages instead of running the full Vaadin application user interface in them. Common reasons for this are static pages (e.g. a simple help mode), integrating legacy content to a portlet (e.g. a JSP configuration interface) and providing an ultra-lightweight initial view for a portlet (for users behind slow connections).
Fully static modes that do not require the Vaadin server side
application to be running can be implemented by subclassing the portlet
class
Customizing the content for the standard modes
(view, edit, and
help) can be performed by overriding the methods
You need to define which portlet modes are enabled in the
The following example (for Portlet 2.0) shows how to create a static help page for the portlet.
<!-- Supported portlet modes and content types. -->
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
// Use Portlet 2.0 API
import com.vaadin.terminal.gwt.server.ApplicationPortlet2;
public class HtmlHelpPortlet extends ApplicationPortlet2 {
// override the help mode, let the Vaadin application handle the view mode
@Override
protected void doHelp(RenderRequest request, RenderResponse response)
throws PortletException, IOException {
// bypass the Vaadin application entirely
response.setContentType("text/html");
response.getWriter().println("This is the help text as plain HTML.");
// alternatively could use the dispatcher for e.g. JSP help pages:
// PortletRequestDispatcher dispatcher = getPortletContext()
// .getRequestDispatcher("/html/myhelp.jsp");
// dispatcher.include(request, response);
}
}
To produce pure HTML portlet content from a running Vaadin application
instead of statically outside an application, the
<portlet-class>com.vaadin.demo.portlet.HtmlModePortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
<portlet-mode>help</portlet-mode>
</supports>
public class CountApplication extends Application {
private int count = 0;
public void init() {
Window window = new Window("Portlet mode example");
window.addComponent(new Label("This is the Vaadin application."));
window.addComponent(new Label("Try opening the help mode."));
setMainWindow(window);
}
public int incrementCount() {
return ++count;
}
}
// Use Portlet 2.0 API
public class HtmlModePortlet extends AbstractApplicationPortlet {
@Override
protected void writeAjaxPage(RenderRequest request,
RenderResponse response, Window window,
Application application) throws PortletException, IOException {
if (PortletMode.HELP.equals(request.getPortletMode())) {
CountApplication app = (CountApplication) application;
response.setContentType("text/html");
response.getWriter().println("This is the HTML help, shown "
+ app.incrementCount() + " times so far.");
} else {
super.writeAjaxPage(request, response, window, application);
}
}
@Override
protected Class<? extends Application> getApplicationClass() {
return CountApplication.class;
}
}
The user can freely move between Vaadin and non-Vaadin portlet
modes with the user interface provided by the portal (for
standard modes) or the portlet (e.g. action links). Once the
server side application has been started, it continues to run
as long as the session is alive.
If necessary, specific portlet mode transitions can be
disallowed in
In the case of Portlet 1.0, both a portlet and a servlet are involved.
A render request is received by
To serve HTML-only content in the Portlet 1.0 case after starting the
server side application and calling the relevant listeners, the servlet
class |
Table of Contents
|