ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 01.01.2026

Просмотров: 2634

Скачиваний: 0

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Advanced Web Application Topics

11.14. Accessing Session-Global Data

Applications typically need to access some objects from practically all user interface code, such as a user object, a business data model, or a database connection.This data is typically initialized and managed in the UI class of the application, or in the session or servlet.

For example, you could hold it in the UI class as follows:

class MyUI extends UI { UserData userData;

public void init() {

userData = new UserData();

}

public UserData getUserData() { return userData;

}

}

Vaadin offers two ways to access the UI object: with getUI() method from any component and the global UI.getCurrent() method.

The getUI() works as follows:

data = ((MyUI)component.getUI()).getUserData();

This does not, however work in many cases, because it requires that the components are attached to the UI.That is not the case most of the time when the UI is still being built, such as in constructors.

class MyComponent extends CustomComponent { public MyComponent() {

// This fails with NullPointerException Label label = new Label("Country: " +

getApplication().getLocale().getCountry());

setCompositionRoot(label);

}

}

The global access methods for the currently served servlet, session, and UI allow an easy way to access the data:

data = ((MyUI) UI.getCurrent()).getUserData();

The Problem

The basic problem in accessing session-global data is that the getUI() method works only after the component has been attached to the application. Before that, it returns null.This is the case in constructors of components, such as a CustomComponent:

Using a static variable or a singleton implemented with such to give a global access to user session data is not possible, because static variables are global in the entire web application, not just the user session. This can be handy for communicating data between the concurrent sessions, but creates a problem within a session.

The data would be shared by all users and be reinitialized every time a new user opens the application.

Accessing Session-Global Data

315

Advanced Web Application Topics

Overview of Solutions

To get the application object or any other global data, you have the following solutions:

Pass a reference to the global data as a parameter

Initialize components in attach() method

Initialize components in the enter() method of the navigation view (if using navigation)

Store a reference to global data using the ThreadLocal Pattern

Each solution is described in the following sections.

11.14.1. Passing References Around

You can pass references to objects as parameters. This is the normal way in object-oriented programming.

class MyApplication extends Application { UserData userData;

public void init() {

Window mainWindow = new Window("My Window"); setMainWindow(mainWindow);

userData = new UserData();

mainWindow.addComponent(new MyComponent(this));

}

public UserData getUserData() { return userData;

}

}

class MyComponent extends CustomComponent { public MyComponent(MyApplication app) { Label label = new Label("Name: " +

app.getUserData().getName());

setCompositionRoot(label);

}

}

If you need the reference in other methods, you either have to pass it again as a parameter or store it in a member variable.

The problem with this solution is that practically all constructors in the application need to get a reference to the application object, and passing it further around in the classes is another hard task.

11.14.2. Overriding attach()

The attach() method is called when the component is attached to the application component through containment hierarchy. The getApplication() method always works.

class MyComponent extends CustomComponent { public MyComponent() {

// Must set a dummy root in constructor setCompositionRoot(new Label(""));

316

Overview of Solutions


Advanced Web Application Topics

}

@Override

public void attach() {

Label label = new Label("Name: " + ((MyApplication)component.getApplication())

.getUserData().getName());

setCompositionRoot(label);

}

}

While this solution works, it is slightly messy. You may need to do some initialization in the constructor, but any construction requiring the global data must be done in the attach() method. Especially, CustomComponent requires that the setCompositionRoot() method is called in the constructor. If you can't create the actual composition root component in the constructor, you need to use a temporary dummy root, as is done in the example above.

Using getApplication() also needs casting if you want to use methods defined in your application class.

11.14.3. ThreadLocal Pattern

Vaadin uses the ThreadLocal pattern for allowing global access to the Application, UI, and Page objects of the currently processed server request with a static getCurrent() method in all the respective classes. This section explains why the pattern is used in Vaadin and how it works. You may also need to reimplement the pattern for some purpose.

The ThreadLocal pattern gives a solution to the global access problem by solving two sub-problems of static variables.

As the first problem, assume that the servlet container processes requests for many users (sessions) sequentially. If a static variable is set in a request belonging one user, it could be read or re-set by the next incoming request belonging to another user. This can be solved by setting the global reference at the beginning of each HTTP request to point to data of the current user, as illustrated in Figure 11.7.

Figure 11.7. Switching a static (orThreadLocal) reference during sequential processing of requests

The second problem is that servlet containers typically do thread pooling with multiple worker threads that process requests. Therefore, setting a static reference would change it in all threads running concurrently, possibly just when another thread is processing a request for another user.

ThreadLocal Pattern

317

Advanced Web Application Topics

The solution is to store the reference in a thread-local variable instead of a static. You can do so by using the ThreadLocal class in Java for the switch reference.

Figure 11.8. Switching ThreadLocal references during concurrent processing of requests

318

ThreadLocal Pattern



Chapter 12

Portal Integration

12.1. Deploying to a Portal ...........................................................................

319

12.2. Creating a Portal Application Project in Eclipse ..................................

320

12.3. Portlet Deployment Descriptors ...........................................................

322

12.4. Portlet Hello World ...............................................................................

327

12.5. Installing Vaadin in Liferay ...................................................................

327

12.6. Handling Portlet Requests ...................................................................

329

12.7. Handling Portlet Mode Changes ..........................................................

330

12.8. Non-Vaadin Portlet Modes ...................................................................

332

12.9. Vaadin IPC for Liferay ..........................................................................

335

Vaadin supports running applications as portlets, as defined in the JSR-286 (Java Portlet API 2.0) standard. While providing generic support for all portals implementing the standard, Vaadin especially supports the Liferay portal and the needed portal-specific configuration is given in this chapter for Liferay.

Because of pressing release schedules to get this edition to your hands, we were unable to completely update this chapter. The content is up-to-date with Vaadin 7 to some extent, but some topics still require revision. Please consult the web version once it is updated, or the next print edition.

12.1. Deploying to a Portal

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:

• Application packaged as a WAR

Book of Vaadin

319

Portal Integration

WEB-INF/portlet.xml descriptor

WEB-INF/web.xml descriptor for Portlet 1.0 portlets

WEB-INF/liferay-portlet.xml descriptor for Liferay

WEB-INF/liferay-display.xml descriptor for Liferay

WEB-INF/liferay-plugin-package.properties for Liferay

Widget set installed to portal (optional)

Themes installed to portal (optional)

Vaadin library installed to portal (optional)

Portal configuration settings (optional)

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 have the portlet.jar in your project classpath. However, notice that you must not put the portlet.jar in the same WEB-INF/lib directory as the Vaadin JAR or otherwise include it in the WAR to be deployed, because it would create a conflict with the internal portlet library of the portal. The conflict would cause errors such as "ClassCastException: ...VaadinPortlet cannot be cast to javax.portlet.Portlet".

How you actually deploy a WAR package depends on the portal. In Liferay, you simply drop it to the deploy subdirectory under the Liferay installation directory. The deployment depends on the application server under which Liferay runs; for example, if you use Liferay bundled with Tomcat, you will find the extracted package in the webapps directory under the Tomcat installation directory included in Liferay.

12.2. Creating a Portal Application Project in Eclipse

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 portlet application project is almost identical to the creation of a regular Vaadin servlet application project. For a full treatment of the New Project Wizard and the possible options, please see Section 2.5.1, “Creating the Project”.

1. Start creating a new project by selecting from the menu File New Project...

320

Creating a Portal Application Project in Eclipse


Portal Integration

2.

In the New Project window that opens, select Web Vaadin 7 Project and click Next.

3.

In the Vaadin Project step, you need to set the basic web project settings. You need

 

to give at least the project name, the runtime, select Generic Portlet for the Deployment

 

configuration; the default values should be good for the other settings.

You can click Finish here to use the defaults for the rest of the settings, or click Next.

4.The settings in the Web Module step define the basic servlet-related settings and the structure of the web application project. All the settings are pre-filled, and you should normally accept them as they are and click Next.

5.The Vaadin project step page has various Vaadin-specific application settings. These are largely the same as for regular applications. Setting them here is easiest - later some of the changes require changes in several different files. The Create portlet template option should be automatically selected. You can give another portlet title of you want. You can change most of the settings afterward.

Creating a Portal Application Project in Eclipse

321

Portal Integration

Create project template

Creates an application class and all the needed portlet deployment descriptors.

Application name

The application name is used in the title of the application window, which is usually invisible in portlets, and as an identifier, either as is or with a suffix, in various deployment descriptors.

Base package name

Java package for the application class.

Application class name

Name of the application class. The default is derived from the project name.

Portlet version

Same as in the project settings.

Portlet title

The portlet title, defined in portlet.xml, can be used as the display name of the portlet (at least in Liferay). The default value is the project name. The title is also used as a short description in liferay-plugin-package.properties.

Vaadin version

Same as in the project settings.

Finally, click Finish to create the project.

6.Eclipse may ask you to switch to J2EE perspective. A Dynamic Web Project uses an external web server and the J2EE perspective provides tools to control the server and manage application deployment. Click Yes.

12.3.Portlet Deployment Descriptors

To deploy a portlet WAR in a portal, you need to provide the basic portlet.xml descriptor specified in the Java Portlet API 2.0 standard (JSR-286). In addition, you may need to include possible portal vendor specific deployment descriptors.The ones required by Liferay are described below.

Portlet 2.0 Deployment Descriptor

The portlet WAR must include a portlet descriptor located at WebContent/WEB-INF/portlet.xml. A portlet definition includes the portlet name, mapping to a servlet in web.xml, modes supported by the portlet, and other configuration. Below is an example of a simple portlet definition in portlet.xml descriptor.

<?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>

322

Portlet Deployment Descriptors