JBoss Community Archive (Read Only)

GateIn Portal 3.4

JavaScript Resource Management

Introduction

For the moment, JavaScript code deployed in GateIn portal is divided into multiple resources, which could be seen as an umbrella of multiple JavaScript files. The great advantage of resource over JavaScript file is that the dependency relations among groups of files are always simpler than dependency relations among files.

The new model of resource has been proving its power in term of

  1. Simplifying dependencies

  2. Orchestrating loading order

  3. Minimizing excess JavaScript code per request

Resource Management

Declare resource

The place to put resource configuration is WEB-INF/gatein-resources.xml file in any deployed web application.

Simple JavaScript resources
<module>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
  <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
  </script>
</module>

<scripts>
  <name>second_resource</name>
  <script>
     <name>DEF_script</name>
     <path>/def.js</path>
  </script>
</scripts>

Above XML element defines two simple resources named first_resource and second_resource wrapping two lists of physical JavaScript files whose paths (relative to the root directory of actual web application) are given in the <path> elements.

We notice that configurations for first_resource and second_resource are different in term of outer tag (<module> vs <scripts>). The two tags <module> and <scripts> determines resource's fetch-mode, a concept that we discuss later.

In addition to resource including local JavaScript files (deployed to the server), there is possibility to define a remote resource holding a single JavaScript file from external world.

remote JavaScript resource
<module>
  <name>remote_resource</name>
  <url>http:/ /jquery.com/releases/jquery-1.7.1.js</url>
</module>

Extra information on syntax of remote resource could be found in the schema gatein_resources_1_2_1.xsd.

That a resource is remote or local is made transparent to resource controlling in GateIn.

Scope

The sharing ability of resource is characterized by its scope. The three resource scope are SHARED, PORTAL and PORTLET.

  1. SHARED: The resource might involve in the rendering of any web page in portal.

  2. PORTAL: The resource might involve in the rendering of any web page belonging to a specified portal site.

  3. PORTLET: The resource might involve in the rendering of any web page containing window of a specified portlet.

Example of SHARED scope resource
<module>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
  <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
  </script>
</module>

<scripts>
  <name>second_resource</name>
  <script>
     <name>ABCXYZ_script</name>
     <path>/abcxyz.js
  </script>
</scripts>
Example of PORTAL scope resources
<portal>
  <name>classic_site</name>
  <module>
   <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
   </script>
   <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
   </script>
  </module>
</portal>

<portal>
  <name>acme_site</name>
  <module>
    <url>http:/ /abcxyz/foo.js</url>
  </module>
</portal>

<portal>
  <name>custom_site</name>
  <scripts>
     <script>
        <name>ABCXYZ_script</name>
        <path>/abcxyz.js</path>
     </script>
  </scripts>
</portal>
Example of PORTLET scope resources
<portlet>
  <name>first_portlet</name>
  <module>
   <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
   </script>
   <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
   </script>
  </module>
</portlet>

<portlet>
  <name>second_portlet</name>
  <module>
    <url>http:/ /abcxyz/bar.js</url>
  </module>
</portlet>

<portlet>
  <name>third_portlet</name>
  <scripts>
    <script>
      <name>ABCXYZ_script</name>
      <path>/abcxyz.js</name>
    </script>
    <script>
      <name>ABCXYZT_script</name>
      <path>/abcxyzt.js</path>
    </script>
  </scripts>
</portlet>
Notice: GateIn will not allow name duplication of resources in the same SCOPE, any duplicated scripts or modules will not be added to GateIn managed resources

Fetch Mode

The resource fetch mode indicates how JavaScript code under it is loaded into the browser.

IMMEDIATE

Resource with IMMEDIATE fetch mode is loaded synchronously into browser before the moment where DOMContentLoaded event is fired

Resources with IMMEDIATE fetch mode
<scripts>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
</scripts>

<portlet>
  <name>portlet_resource</name>
  <scripts>
   <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
   </script>
   <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
   </script>
  </scripts>
</portlet>

<portal>
  <name>classic_resource</name>
  <scripts>
     <script>
        <name>ABCXYZ_script</name>
        <path>/abcxyz.js</path>
     </script>
  </scripts>
</portal>

ON-LOAD

Resource with ON-LOAD fetch mode is loaded asynchronously thanks to the 'async' attribute of <script> element (most of modern browsers support that attribute). JavaScript code not required for HTML rendering could be loaded after DOMContentLoaded event and that increase the HTML displaying speed.

Resources with ON-LOAD fetch mode
<module>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
</module>

<portlet>
  <name>portlet_resource</name>
  <module>
   <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
   </script>
   <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
   </script>
  </module>
</portlet>

<portal>
  <name>classic_site</name>
  <module>
    <script>
      <name>XYZ_script</name>
      <path>/xyz.js</path>
    </script>
  </module>
</portal>

Dependency

Like artifact dependency model in Maven, GateIn introduces the concept of dependency between JavaScript resources that responds to the requirement of managing loading order of JavaScript code. For each dependency relation, both dependent resource and its dependency are forced to have the same fetch mode.

With such rule on dependency relation, the whole set of JavaScript resources makes up two no-cycled directed graphs. One graph whose vertices are IMMEDIATE resources, and the other consists of ON-LOAD resources.

ON-LOAD resource dependencies example
<module>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
  <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
  </script>
</module>

<module>
  <name>second_resource</name>
  ...
</module>

<!-- Notice the element <module> under <depends> -->
<portal>
  <name>classic_site</name>
  <module>
     <depends>
        <module>first_resource</module>
     </depends>
     <depends>
        <module>second_resource</module>
     </depends>
  </module>
<portal>
IMMEDIATE resource dependencies example
<scripts>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
  <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
  </script>
</scripts>

<scripts>
  <name>second_resource</name>
  ...
</scripts>

<!-- Notice the element <scripts> under <depends> -->
<portal>
  <name>classic_site</name>
  <scripts>
     <depends>
        <scripts>first_resource</scripts>
     </depends>
     <depends>
        <scripts>second_resource</scripts>
     </depends>
  </scripts>
<portal>

It is important to keep in mind that among the set of SHARED, PORTAL and PORTLET resources, only the SHARED resources are eligible to be dependencies.

Use resource

With configuration in gatein-resources.xml, the _new_resource resource is managed on the server side. Anyway, we need extra work to make its JavaScript code available in the hypertext sent back to client.

Denote a resource available if its JavaScript code takes part in the rendering portal page. GateIn resource controller assures:

  1. PORTLET resource is available if rendering portal page contains a window of portlet associated with that resource

  2. PORTAL resource is available if rendering portal page belongs to the site associated with that resource

  3. As one resource is available, all of its dependencies (either direct or indirect) are made available

Resource could be made available in either declarative or programmatic manner.

Declarative

PORTLET resource

Resource for portlet A
<portlet>
   <name>A</name>
   <module>
      ...
   </module>
</portlet>

As mentioned previously, the resource configuration is enough to make PORTLET resource available. However, there are two constraints upon PORTLET resource:

  • gatein-resources.xml file must be located in the portlet application containing portlet A.

  • Resource name must equal to the name of portlet definition in portlet.xml.

PORTAL resource

Resource for classic_site site
<portal>
   <name>classic_site</name>
   <module>
      ...
   </module>
</portal>

classic_site resource is available in any page from classic_site site.

SHARED resource

The only declarative way to make SHARED resource available is to configure it as dependency (direct or indirect) of available resource.

Direct dependency to make SHARED resource available
<portlet>
   <name>A</name>
   <module>
      <depends>
         <module>new_resource</module>
      </depends>
   </module>
</portlet>

<module>
  <name>new_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
  <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
  </script>
</module>
Indirect dependency to make SHARED resource available
<portlet>
   <name>A</name>
   <module>
      <depends>
         <module>first_resource</module>
      </depends>
   </module>
</portlet>

<module>
  <name>first_resource</name>
  <script>
     <name>ABC_script</name>
     <path>/abc.js</path>
  </script>
  <depends>
     <module>second_resource</module>
  </depends>
</module>

<module>
  <name>second_resource</name>
  <script>
     <name>XYZ_script</name>
     <path>/xyz.js</path>
  </script>
</module>

Programmatic

JavascriptManager

The single-request object JavascriptManager is an entry to interact with JavaScript stuff in the scope of one HTTP request. The object exposes methods that enables us to make resource available.

org.exoplatform.web.application.JavascriptManager
public void loadScriptResource(String name) //load a SHARED resource

public void loadScriptResource(ResourceScope scope, String name)

During portal page rendering phase, if there is call to loadScriptResource for resource new_resource, the resource will take part in final hypertext.

Example of Groovy template that makes new_resource _available_
JavascriptManager jsmanager = _ctx.getRequestContext().getJavascriptManager();

jsmanager.loadScriptResource("new_resource");

Portlet API

In a particular use case where we need SHARED resources for a portlet window, GateIn provides alternative and better solution using JSR 168/286 API.

Make resource _available_ to portlet via JSR 168/286 API
public void render(RenderRequest req, RenderResponse resp) throws PortletException, IOException {
   resp.addProperty("org.gatein.javascript.dependency", "first_resource");
   resp.addProperty("org.gatein.javascript.dependency", "second_resource");
}

As we could learn from above code, the work consists of customizing GateIn's two predefined portlet response properties during render phase of portlet.

  • org.gatein.javascript.dependency: This multivalued property specifies list of SHARED resources (can be declared as <scripts> or <module> in gatein-resources.xml)  available to actual portlet window

Loading order

The loading order here refers to the order by which JavaScript code is loaded into the browser of clients.

Script ordering

Loading order of scripts wrapped in a resource is determined by top-to-bottom order of <script> elements. Following configuration ensures that abc.js is loaded before xyz.js, that is crucial in case xyz.js requires abc.js.

<module>
      <name>new_resource</name>
      <script>
         <name>ABC_script</name>
         <path>/abc.js</path>
      </script>
      <script>
         <name>XYZ_script</name>
         <path>/xyz.js</path>
      </script>
</module>

Resource ordering

As resource A depends on resource B (either directly or recursively), JavaScript code from resource A is loaded after that from resource B.

<module>
      <name>new_resource</name>
      <script>
         <name>ABC_script</name>
         <path>/abc.js</path>
      </script>
      <script>
         <name>XYZ_script</name>
         <path>/xyz.js</path>
      </script>

      <depends>
         <module>dependency_resource</module>
      </depends>
   </module>

   <module>
      <name>dependency_resource</name>
      <script>
         <name>UVW_script</name>
         <path>/uvw.js</path>
      </script>
   </module>

Localization

GateIn offers the possibility to link JavaScript code with localization defined in properties/xml files.

<module>
      <name>new_resources</name>
      <supported-locale>de</supported-locale>
      <supported-locale>en</supported-locale>
      <supported-locale>fr</supported-locale>
      <supported-locale>ru</supported-locale>
      <supported-locale>vi</supported-locale>

      <script>
        <name>ABC_script</name>
        <path>/abc.js</path>
        <resource-bundle>file_path</resource-bundle>
      </script>
</module>

As the server retrieves content of /abc.js, it detects pattern ${key_expression} and replaces matched subsequences with the value from L10n files under file_path whose key is key_expression.

abc.js
weekdays : [
      "${weekdays.sun}",
      "${weekdays.mon}",
      "${weekdays.tue}",
      "${weekdays.wed}",
      "${weekdays.thu}",
      "${weekdays.fri}",
      "${weekdays.sat}"
  ]

At runtime, the content of abc.js depends on the local.

abc.js as locale is fr
weekdays : [
      "Lundi",
      "Mardi",
      "Merdcredi",
      "Jeudi",
      "Vendredi",
      "Samedi",
      "Dimanche"
  ]

Unlike the value of <path> element, the file_path is not required to be in the same web application as actual gatein-resources.xml file. Anyway, the file_path must be visible to the merged class loader of Portal Container.

JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-10 12:45:39 UTC, last content change 2013-06-19 11:52:01 UTC.