JBoss.orgCommunity Documentation

Chapter 5. Development

5.1. Portal Lifecycle
5.1.1. Overview
5.1.2. Application Server start and stop
5.1.3. The Command Servlet
5.2. RTL (Right To Left) Framework
5.2.1. Groovy templates
5.2.2. Stylesheet
5.2.3. Images
5.2.4. Client side JavaScript
5.3. Internationalization Configuration
5.3.1. Overview
5.3.2. Locales configuration
5.3.3. ResourceBundleService
5.3.4. Navigation Resource Bundles
5.3.5. Portlets
5.4. XML Resources Bundles
5.4.1. Motivation
5.4.2. XML format
5.4.3. Portal support
5.5. Dynamic Layouts
5.5.1. Overview
5.5.2. Advanced Drag and Drop mechanism
5.6. JavaScript Inter Application Communication
5.6.1. Overview
5.6.2. Library
5.6.3. Syntax
5.6.4. Example of Javascript events usage
5.7. Upload Component
5.7.1. Upload Service
5.8. Deactivation of the Ajax Loading Mask Layer
5.8.1. Purpose
5.8.2. Synchronous issue
5.9. Accessing User Profile

The servlet is the main entry point for incoming requests, it also includes some init code when the portal is launched. This servlet (org.gatein.wci.command.CommandServlet) is automatically added during deployment and mapped to /tomcatgateinservlet.

This is equivalent to adding the following into web.xml.



<servlet>
  <servlet-name>TomcatGateInServlet</servlet-name>
  <servlet-class>org.gatein.wci.command.CommandServlet</servlet-class>
  <load-on-startup>0</load-on-startup>
</servlet>
  
<servlet-mapping>
  <servlet-name>TomcatGateInServlet</servlet-name>
  <url-pattern>/tomcatgateinservlet</url-pattern>
</servlet-mapping>

It is possible to filter on the CommandServlet by filtering the URL pattern used by the Servlet mapping.

The example below would create a servlet filter that calculates the time of execution of a portlet request.

The filter class:



package org.example;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class MyFilter implements javax.servlet.Filter {
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException
  {
    long beforeTime = System.currentTimeMillis();
    chain.doFilter(request, response);
    long afterTime = System.currentTimeMillis();
    System.out.println("Time to execute the portlet request (in ms): " + (afterTime - beforeTime));
  }
  public void init(FilterConfig config) throws ServletException
  {
  }
  public void destroy()
  {
  }
}

The Java EE web application configuration file (web.xml) of the portlet on which we want to know the time to serve a portlet request. As mentioned above nothing specific to GateIn 3.0 needs to be included, only the URL pattern to set has to be known.



<?xml version="1.0"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.5">
        
  <filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>org.example.MyFilter</filter-class>        
  </filter>

  <filter-mapping>
    <filter-name>MyFilter</filter-name>
    <url-pattern>/tomcatgateinservlet</url-pattern>
    <dispatcher>INCLUDE</dispatcher>  
  </filter-mapping>    
    
</web-app>

The text orientation depends on the current locale setting. The orientation is a Java 5 enum that provides a set of functionalities:

   LT, // Western Europe
   RT, // Middle East (Arabic, Hebrew)
   TL, // Japanese, Chinese, Korean
   TR; // Mongolian
   public boolean isLT() { ... }
   public boolean isRT() { ... }
   public boolean isTL() { ... }
   public boolean isTR() { ... }

The object defining the Orientation for the current request is the UIPortalApplication. However it should be accessed at runtime using the RequestContext that delegates to the UIPortalApplication.

In the case of a PortalRequestContext it is a direct delegate as the PortalRequestContext has a reference to the current UIPortalApplication.

In the case of a different context such as the PortletRequestContext, it delegates to the parent context given the fact that the root RequestContext is always a PortalRequestContext.

All GateIn 3.0 applications contain property files for various languages. They are packaged with the portlets applications in a WEB-INF/classes/locale/ directory.

These files are located in the classes folder of the WEB-INF directory, so as to be loaded by the ClassLoader.

All resource files are in a subfolder named locale.

For instance; the translations for the NavigationPortlet are located in web.war/WEB-INF/classes/locale/portlet/portal

NavigationPortlet_de.properties
NavigationPortlet_en.properties
NavigationPortlet_es.properties
NavigationPortlet_fr.properties
NavigationPortlet_nl.properties
NavigationPortlet_ru.properties
NavigationPortlet_uk.properties
NavigationPortlet_ar.xml

Inside those file are typical key=value Java EE properties. For example the French one:

javax.portlet.title=Portlet Navigation

There are also properties files in the portal itself. They form the portal resource bundle.

From a portlet you can then access translations from the portlet itself or shared at the portal level, both are aggregated when you need them.

Translation in XML format

It is also possible to use a proprietary XML format to define translations. This is a more convenient way to translate a document for some languages such as Japanese, Arabic or Russian. Property files have te be ASCII encoded, while the XML file can define its encoding. As a result it's easier for a human being to read (and fix) a translation in XML instead of having to decode and encode the property file.

For more information refer to: Section 5.4, “XML Resources Bundles”

Various languages are available in the portal package. The configuration below will define which languages are shown in the "Change Language" section and made available to users.

The 02portal.war:/WEB-INF/conf/common/common-configuration.xml file of your installation contains the following section:


<component>
  <key>org.exoplatform.services.resources.LocaleConfigService</key>
  <type>org.exoplatform.services.resources.impl.LocaleConfigServiceImpl</type>
  <init-params>
    <value-param>
      <name>locale.config.file</name>
      <value>war:/conf/common/locales-config.xml</value>
    </value-param>
  </init-params>
</component>

This configuration points to the locale configuration file.

The locale configuration file (02portal.war:/WEB-INF/conf/common/locales-config.xml) contains the following code:

<?xml version="1.0" encoding="UTF-8"?>
<locales-config>
  <locale-config>
    <locale>en(1)</locale>
    <output-en(2)coding>UTF-8</output-encoding>
    <input-enc(3)oding>UTF-8</input-encoding>
    <descripti(4)on>Default configuration for english locale</description>
  </locale-config>
 
  <locale-config>
    <locale>fr</locale>
    <output-encoding>UTF-8</output-encoding>
    <input-encoding>UTF-8</input-encoding>
    <description>Default configuration for the french locale</description>
  </locale-config>
 
  <locale-config>
    <locale>ar</locale>
    <output-encoding>UTF-8</output-encoding>
    <input-encoding>UTF-8</input-encoding>
    <description>Default configuration for the arabic locale</description>
    <orientati(5)on>rt</orientation>
  </locale-config>
</locales-config>
1

locale The locale has to be defined such as defined here http://ftp.ics.uci.edu-pub-ietf-http-related-iso639.txt. In this example "ar" is Arabic.

2

output-encoding deals with character encoding. It is recommended that UTF-8 be used.

3

input-encoding In the java implementation, the encoding parameters will be used for the request response stream. The input-encoding parameter will be used for request setCharacterEncoding(..).

4

description Description for the language

5

description The default orientation of text and images is Left-To-Right. GateIn 3.0 supports Right-To-Left orientation. Modifying text orientation is explained in Section 5.2, “RTL (Right To Left) Framework”.

The resource bundle service is configured in: 02portal.war:/WEB-INF/conf/common/common-configuration.xml:

<component>
  <key>org.exoplatform.services.resources.ResourceBundleService</key>
  <type>org.exoplatform.services.resources.impl.SimpleResourceBundleService</type>
  <init-params>
    <values-param>
      <name>cl(1)asspath.resources</name>
      <description>The resources  that start with the following package name should be load from file system</description>
      <value>locale.portlet</value>      
    </values-param>      
    <values-param>
      <name>in(2)it.resources</name>
      <description>Initiate the following resources during the first launch</description>
      <value>locale.portal.expression</value>
      <value>locale.portal.services</value>
      <value>locale.portal.webui</value>
      <value>locale.portal.custom</value>
      <value>locale.navigation.portal.classic</value>
      <value>locale.navigation.group.platform.administrators</value>
      <value>locale.navigation.group.platform.users</value>
      <value>locale.navigation.group.platform.guests</value>
      <value>locale.navigation.group.organization.management.executive-board</value>               
    </values-param>      
    <values-param>
      <name>po(3)rtal.resource.names</name>
      <description>The properties files of  the portal ,  those file will be merged 
        into one ResoruceBundle properties </description>
      <value>locale.portal.expression</value>
      <value>locale.portal.services</value>
      <value>locale.portal.webui</value>
      <value>locale.portal.custom</value>        
    </values-param>      
  </init-params>
</component>
1

classpath.resources are discussed in a later section.

2

init.resources TODO

3

portal.resource.names Defines all resources that belong to the Portal Resource Bundle.

These resources are merged to a single resource bundle which is accessible from anywhere in GateIn 3.0. All these keys are located in the same bundle, which is separated from the navigation resource bundles.

Portlets are independent applications and deliver their own resource files.

All shipped portlet resources are located in the locale/portlet subfolder. The ResourceBundleService parameter classpath.resources defines this subfolder.

See the portlet specification for more details about portlet internationalization.

The Inter Application Communication library is found in 01eXoResources.war:/javascript/eXo/core/Topic.js

/**
 * publish is used to publish an event to the other subscribers to the given channels
 * @param {Object} senderId is a string that identify the sender
 * @param {String} topic is the topic that the message will be published
 * @param {Object} message is the message that's going to be delivered to the subscribers to the topic
 */
Topic.prototype.publish = function(/*Object*/ senderId, /*String*/ topicName, /*Object*/ message ) { ... }

/**
 * isSubscribed is used to check if a function receive the events from a topic
 * @param {String} topic The topic.
 * @param {Function} func is the name of the function of obj to call when a message is received on the topic
 */
Topic.prototype.isSubscribed = function(/*String*/ topic, /*Function*/ func) { ... }

/**
 * subscribe is used to subscribe a callback to a topic
 * @param {String} topic is the topic that will be listened
 * @param {Function} func is the name of the function of obj to call when a message is received on the topic
 * 
 * func is a function that take a Object in parameter. the event received have this format:
 * {senderId:senderId, message:message, topic: topic}
 *
 */
Topic.prototype.subscribe = function(/*String*/ topic, /*Function*/ func) { ... }

/**
 * unsubscribe is used to unsubscribe a callback to a topic
 * @param {String} topic is the topic
 * @param {Object} id is the id of the listener we want to unsubscribe
 */
Topic.prototype.unsubscribe = function(/*String*/ topic, /*Object*/ id) { ... }

Topic.prototype.initCometdBridge = function() { ... }

The service is defined by the class: org.exoplatform.upload.UploadService;

This can be configured with the following xml code:


<component>
   <type>org.exoplatform.upload.UploadService</type>
     <init-params>
       <value-param>
        <name>upload.limit.size</name>
        <description>Maximum size of the file to upload in MB</description>
        <value>10</value>
      </value-param>
    </init-params>  
  </component>

This code allows for a default upload size limit for the service to be configured. The value unit is in MegaBytes.

This limit will be used by default by all applications if no application-specific limit is set. Setting a different limit for applications is discussed in a later section.

If the value is set at 0 the upload size is unlimited.

Procedure 5.2. How to use the upload component

  1. Create an object type org.exoplatform.webui.form.UIFormUploadInput.

    Two constructors are available for this:

    public UIFormUploadInput(String name, String bindingExpression)
    

    or:

    public UIFormUploadInput(String name, String bindingExpression, int limit)
    

    This is an example using the second form :

    PortletRequestContext pcontext = (PortletRequestContext)WebuiRequestContext.getCurrentInstance();
    
    PortletPreferences portletPref = pcontext.getRequest().getPreferences();
    int limitMB = Integer.parseInt(portletPref.getValue("uploadFileSizeLimitMB", "").trim());
    UIFormUploadInput uiInput = new UIFormUploadInput("upload", "upload", limitMB);
  2. To obtain the limit from the xml configuration, this piece of code can be added to the either portlet.xml or portlet-preferences.xml :

    
    <preference>
      <name>uploadFileSizeLimitMB</name>
      <value>30</value>
      <read-only>false</read-only>
    </preference>

    Again, a 0 value means an unlimited upload size, and the value unit is set in MegaBytes.

  3. Use the getUploadDataAsStream() method to get the uploaded data:

    UIFormUploadInput input = (UIFormUploadInput)uiForm.getUIInput("upload");
    
    InputStream inputStream = input.getUploadDataAsStream();
    ...
    jcrData.setValue(inputStream);
  4. The upload service stores a temporary file on the filesystem during the upload process. When the upload is finished, the service must be cleaned in order to:

    1. Delete the temporary file.

    2. Delete the classes used for the upload.

    Use theremoveUpload() method defined in the upload service to purge the file:

    UploadService uploadService = uiForm.getApplicationComponent(UploadService.class) ;
    
    UIFormUploadInput uiChild = uiForm.getChild(UIFormUploadInput.class) ;
    uploadService.removeUpload(uiChild.getUploadId()) ;

    Saving the uploaded file

    Ensure the file is saved before the service is cleaned.

The following code retrieves the details for a logged-in user:

// Alternative context: WebuiRequestContext context = WebuiRequestContext.getCurrentInstance() ;

PortalRequestContext context = PortalRequestContext.getCurrentInstance() ;
// Get the id of the user logged
String userId = context.getRemoteUser();
// Request the information from OrganizationService:
OrganizationService orgService = getApplicationComponent(OrganizationService.class) ;
if (userId != null)
  {
  User user = orgService.getUserHandler().findUserByName(userId) ;
  if (user != null)
  {
    String firstName = user.getFirstName();
    String lastName = user.getLastName();
    String email = user.getEmail();
  }
}

Below are two alternatives for retrieving the Organization Service: