[exo-jcr-commits] exo-jcr SVN: r2409 - in jcr/trunk/docs/userguide/en/src/main/docbook/en-US: modules and 1 other directory.
do-not-reply at jboss.org
do-not-reply at jboss.org
Wed May 19 09:40:28 EDT 2010
Author: nzamosenchuk
Date: 2010-05-19 09:40:27 -0400 (Wed, 19 May 2010)
New Revision: 2409
Added:
jcr/trunk/docs/userguide/en/src/main/docbook/en-US/modules/portal-container.xml
Modified:
jcr/trunk/docs/userguide/en/src/main/docbook/en-US/master.xml
Log:
EXOJCR-706: Uploading converted from confluence document about portal container.
Modified: jcr/trunk/docs/userguide/en/src/main/docbook/en-US/master.xml
===================================================================
--- jcr/trunk/docs/userguide/en/src/main/docbook/en-US/master.xml 2010-05-19 13:15:14 UTC (rev 2408)
+++ jcr/trunk/docs/userguide/en/src/main/docbook/en-US/master.xml 2010-05-19 13:40:27 UTC (rev 2409)
@@ -57,6 +57,9 @@
<xi:include href="modules/performance.xml"
+ xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="modules/portal-container.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
</book>
Added: jcr/trunk/docs/userguide/en/src/main/docbook/en-US/modules/portal-container.xml
===================================================================
--- jcr/trunk/docs/userguide/en/src/main/docbook/en-US/modules/portal-container.xml (rev 0)
+++ jcr/trunk/docs/userguide/en/src/main/docbook/en-US/modules/portal-container.xml 2010-05-19 13:40:27 UTC (rev 2409)
@@ -0,0 +1,2516 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<part>
+ <title>How to extend my GateIn instance?</title>
+
+ <chapter id="Introduction">
+ <title>Introduction</title>
+
+ <section id="Overview">
+ <title>Overview</title>
+
+ <para>Since GateIn beta 2, we added a set of features in order to
+ customize a GateIn instance without modifying the GateIn binary, this
+ usecase will be called <emphasis>portal extension</emphasis> in this
+ documentation. Those features are also required to be able to launch
+ several portal instances at the same time, in "eXo terminology" that
+ means to have several "portal.war".</para>
+ </section>
+
+ <section id="Motivations">
+ <title>Motivations</title>
+
+ <para>Up to now, to create an application over an eXo portal such as
+ DMS, WCM, CS and KS, we need to modify files into the "portal.war". This
+ has many painful consequences, such as:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>It is quite hard to manage from the support point of view
+ since we never know if or how the customer changed his eXo
+ product.</para>
+ </listitem>
+
+ <listitem>
+ <para>It is hard to be able to package several eXo products (WCM,
+ CS...) as we need to merge everything manually which is quite error
+ prone.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Finally, at the very beginning, eXo was developed to be able to
+ support several portal instances (which also means several portal
+ containers) but with the time several bad practices made it impossible.
+ So it was important to review the whole code base in order to
+ help/enforce all the GateIn developers to follow the "good
+ practices".</para>
+ </section>
+ </chapter>
+
+ <chapter id="Prerequisites">
+ <title>Prerequisites</title>
+
+ <para>To be able to migrate an application to GateIn, the first thing we
+ need to do is to ensure that our application supports properly several
+ portal container instances. The following section aims to help you to be
+ compatible with GateIn.</para>
+
+ <section id="Removeallthehardcodedportalcontainernamei.e.portal">
+ <title>Remove all the hard coded portal container name (i.e.
+ "portal")</title>
+
+ <para>Now if we need to get the portal container name (even in a
+ standalone mode: in case of standalone mode the default value will be
+ returned), we can:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>If the component is instantiated by Pico container, you can
+ add in the constructor of your component, the component
+ <emphasis>ExoContainerContext</emphasis>, then call the method
+ <emphasis>getPortalContainerName()</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>If the component is not instantiated by Pico container, you
+ can call at runtime the static method
+ <emphasis>PortalContainer.getCurrentPortalContainerName()</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>In js files, you can use the variable
+ <emphasis>currentContext</emphasis> if your script must be loaded
+ before the variable <emphasis>eXo.env.server.context</emphasis>,
+ otherwise use <emphasis>eXo.env.server.context</emphasis>
+ instead.</para>
+ </listitem>
+
+ <listitem>
+ <para>In jsp files, you can use
+ <emphasis>request.getContextPath()</emphasis>.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="Removeallthehardcodedrestcontextnamei.e.rest">
+ <title>Remove all the hard coded rest context name (i.e. "rest")</title>
+
+ <para>Now if we need to get the rest context name (even in a standalone
+ mode: in case of standalone mode the default value will be returned), we
+ can:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>If the component is instantiated by Pico container, you can
+ add in the constructor of your component, the component
+ <emphasis>ExoContainerContext</emphasis>, then call the method
+ <emphasis>getRestContextName()</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>If the component is not instantiated by Pico container, you
+ can call at runtime the static method
+ <emphasis>PortalContainer.getCurrentRestContextName()</emphasis></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="Removeallthehardcodedrealmnamei.e.exodomain">
+ <title>Remove all the hard coded realm name (i.e. "exo-domain")</title>
+
+ <para>Now if we need to get the realm name (even in a standalone mode:
+ in case of standalone mode the default value will be returned), we
+ can:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>If the component is instantiated by Pico container, you can
+ add in the constructor of your component, the component
+ <emphasis>ExoContainerContext</emphasis>, then call the method
+ <emphasis>getRealmName()</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>If the component is not instantiated by Pico container, you
+ can call at runtime the static method
+ <emphasis>PortalContainer.getCurrentRealmName()</emphasis></para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="MakeyourHttpFilterscompatible">
+ <title>Make your Http Filters compatible</title>
+
+ <para>Now all your Http Filters that need to get the current
+ <emphasis>ExoContainer</emphasis> must extends
+ <emphasis>org.exoplatform.container.web.AbstractFilter</emphasis>. You
+ just need to call the method <emphasis>getContainer()</emphasis> to get
+ the current <emphasis>ExoContainer</emphasis>.</para>
+ </section>
+
+ <section id="MakeyourHttpServletscompatible">
+ <title>Make your HttpServlets compatible</title>
+
+ <para>Now all your HttpServlets that need to get the current
+ <emphasis>ExoContainer</emphasis> must extends
+ <emphasis>org.exoplatform.container.web.AbstractHttpServlet</emphasis>.
+ This abstract class will ensure that the environment has been properly
+ set, so you will be able to call the usual methods such as
+ <emphasis>ExoContainerContext.getCurrentContainer()</emphasis> (if it
+ must also be compatible with the standalone mode) or
+ <emphasis>PortalContainer.getInstance()</emphasis> (if it will only work
+ on a portal environment mode).</para>
+
+ <para>If you had to implement the method
+ <emphasis>service(HttpServletRequest req, HttpServletResponse
+ res)</emphasis>, now you will need to implement
+ <emphasis>onService(ExoContainer container, HttpServletRequest req,
+ HttpServletResponse res)</emphasis>, this method will directly give you
+ the current <emphasis>ExoContainer</emphasis> in its signature.</para>
+
+ <important>
+ <title>Useful Information</title>
+
+ <para>In the class
+ <emphasis>org.exoplatform.container.web.AbstractHttpServlet</emphasis>
+ you have a method called
+ <emphasis>requirePortalEnvironment()</emphasis> that is used to
+ indicate that we would like the abstract class to setup or not the
+ full portal environment ( <emphasis>PortalContainer</emphasis>,
+ <emphasis>ClassLoader</emphasis> and
+ <emphasis>ServletContext</emphasis>) before executing the servlet.
+ This value should return true when the servlet is executed within the
+ web application of a portal container. By default, it checks if the
+ name of the current <emphasis>ServletContext</emphasis> is a portal
+ container name, it is sufficient in most cases but you can still
+ overload this method if you already know that the servlet will always
+ been executed within the web application of portal container (i.e. the
+ method always return true) or will never be executed within the web
+ application of a portal container (i.e. the method always return
+ false) .</para>
+ </important>
+ </section>
+
+ <section id="MakeyourHttpSessionListenerscompatible">
+ <title>Make your HttpSessionListeners compatible</title>
+
+ <para>Now all your HttpSessionListeners that need to get the current
+ <emphasis>ExoContainer</emphasis> must extends
+ <emphasis>org.exoplatform.container.web.AbstractHttpSessionListener</emphasis>.
+ This abstract class will give you the current
+ <emphasis>ExoContainer</emphasis> directly in the signature of the
+ methods to implement which are _ onSessionCreated(ExoContainer
+ container, HttpSessionEvent event)\_ and
+ <emphasis>onSessionDestroyed(ExoContainer container, HttpSessionEvent
+ event)</emphasis></para>
+
+ <para>You will also need to implement the method called
+ <emphasis>requirePortalEnvironment()</emphasis> that is used to indicate
+ that we would like the abstract class to setup or not the full portal
+ environment ( <emphasis>PortalContainer</emphasis> and
+ <emphasis>ClassLoader</emphasis>) before processing the event. This
+ value should return true when the event is processed within the web
+ application of a portal container.</para>
+ </section>
+
+ <section id="UseinittasksifyouneedaPortalContainertoinitializeanHttpFilteroranHttpServlet">
+ <title>Use init tasks if you need a PortalContainer to initialize an
+ Http Filter or an HttpServlet</title>
+
+ <para>If your Http <emphasis>Filter</emphasis> or your
+ <emphasis>HttpServlet</emphasis> requires a PortalContainer to
+ initialize, you need to convert your code in order to launch the code
+ responsible for the initialization in the method
+ <emphasis>onAlreadyExists</emphasis> of an
+ <emphasis>org.exoplatform.container.RootContainer.PortalContainerInitTask</emphasis>.</para>
+
+ <para>We need to rely on init tasks, in order to be sure that the portal
+ container is at the right state when the task is executed, in other
+ words the task could be delayed if you try to execute it too early. Each
+ task is linked to a web application, so when we add a new task, we first
+ retrieve all the portal containers that depend on this web application
+ according to the <emphasis>PortalContainerDefinitions</emphasis>, and
+ for each container we add the task in a sorted queue which order is in
+ fact the order of the web applications dependencies defined in the
+ <emphasis>PortalContainerDefinition</emphasis>. If no
+ <emphasis>PortalContainerDefinition</emphasis> can be found we execute
+ synchronously the task which is in fact the old behavior (i.e. without
+ the starter).</para>
+
+ <para>The supported init tasks are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The
+ <emphasis>org.exoplatform.container.RootContainer.PortalContainerPreInitTask</emphasis>
+ which are executed before the portal container has been
+ initialized</para>
+ </listitem>
+
+ <listitem>
+ <para>The
+ <emphasis>org.exoplatform.container.RootContainer.PortalContainerPostInitTask</emphasis>
+ which are executed after the portal container has been
+ initialized</para>
+ </listitem>
+
+ <listitem>
+ <para>The
+ <emphasis>org.exoplatform.container.RootContainer.PortalContainerPostCreateTask</emphasis>
+ which are executed after the portal container has been fully created
+ (i.e. after all the post init tasks).</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>A init task is defined as below</para>
+
+ <note>
+ <title>PortalContainerPreInitTask</title>
+
+ <programlisting> /**
+ * This interface is used to define a task that needs to be launched at a given state during the
+ * initialization of a portal container
+ */
+ public static interface PortalContainerInitTask
+ {
+
+ /**
+ * This method allows the implementation to define what the state "already exists"
+ * means for a portal container
+ *
+ * @param portalContainer the value of the current portal container
+ * @return <code>true</code> if the portal container exists according to the task
+ * requirements, <code>false</code> otherwise
+ */
+ public boolean alreadyExists(PortalContainer portalContainer);
+
+ /**
+ * This method is called if the related portal container has already been registered
+ *
+ * @param context the servlet context of the web application
+ * @param portalContainer the value of the current portal container
+ */
+ public void onAlreadyExists(ServletContext context, PortalContainer portalContainer);
+
+ /**
+ * Executes the task
+ *
+ * @param context the servlet context of the web application
+ * @param container The portal container on which we would like to execute the task
+ */
+ public void execute(ServletContext context, PortalContainer portalContainer);
+
+ /**
+ * @return the type of the task
+ */
+ public String getType();
+ }
+
+</programlisting>
+ </note>
+
+ <para>To add a task you can either call:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>PortalContainer.addInitTask(ServletContext context,
+ PortalContainerInitTask task)</emphasis> in order to execute the
+ task on all the portal containers that depend on the given
+ <emphasis>ServletContext</emphasis> according to the
+ <emphasis>PortalContainerDefinitions</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>PortalContainer.addInitTask(ServletContext context,
+ PortalContainerInitTask task, String portalContainerName)</emphasis>
+ in order to execute the task on a given portal container.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>RootContainer.addInitTask(ServletContext context,
+ PortalContainerInitTask task)</emphasis> in order to execute the
+ task on the portal container which name is the name of the given
+ <emphasis>ServletContext</emphasis>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>We will take for example the class
+ <emphasis>GadgetRegister</emphasis> that is used to register new google
+ gadgets on a given portal container.</para>
+
+ <para><emphasis role="underline">The old code was:</emphasis></para>
+
+ <note>
+ <title>Old GadgetRegister.java</title>
+
+ <programlisting>...
+public class GadgetRegister implements ServletContextListener
+{
+...
+ public void contextInitialized(ServletContextEvent event)
+ {
+ try
+ {
+ ExoContainer pcontainer = ExoContainerContext.getContainerByName("portal") ;
+ SourceStorage sourceStorage = (SourceStorage)pcontainer.getComponentInstanceOfType(SourceStorage.class);
+ ...
+ }
+ ...
+}
+
+</programlisting>
+ </note>
+
+ <para>The new code relies on a
+ <emphasis>org.exoplatform.container.RootContainer.PortalContainerPostInitTask</emphasis>,
+ as you can see below</para>
+
+ <note>
+ <title>New GadgetRegister.java</title>
+
+ <programlisting>...
+public class GadgetRegister implements ServletContextListener {
+...
+ public void contextInitialized(ServletContextEvent event)
+ {
+ // Create a new post init task
+ final PortalContainerPostInitTask task = new PortalContainerPostInitTask()
+ {
+
+ public void execute(ServletContext context, PortalContainer portalContainer)
+ {
+ contextInitialized(context, portalContainer);
+ }
+ };
+ // Add the init task to all the related portal containers
+ PortalContainer.addInitTask(event.getServletContext(), task);
+ }
+
+ private void contextInitialized(ServletContext context, PortalContainer pcontainer)
+ {
+ try
+ {
+ SourceStorage sourceStorage = (SourceStorage)pcontainer.getComponentInstanceOfType(SourceStorage.class);
+ ...
+ }
+ ...
+}
+
+</programlisting>
+ </note>
+ </section>
+
+ <section id="MakeyourLoginModulescompatible">
+ <title>Make your LoginModules compatible</title>
+
+ <para>Now all your LoginModules that need to get the current
+ <emphasis>ExoContainer</emphasis> must extends
+ <emphasis>org.exoplatform.services.security.jaas.AbstractLoginModule</emphasis>.
+ You just need to call the method <emphasis>getContainer()</emphasis> to
+ get the current <emphasis>ExoContainer</emphasis>.</para>
+
+ <important>
+ <title>Useful Information</title>
+
+ <para>The class
+ <emphasis>org.exoplatform.services.security.jaas.AbstractLoginModule</emphasis>
+ supports 2 login module options which are
+ <emphasis>portalContainerName</emphasis> and
+ <emphasis>realmName</emphasis>, to allow you to indicate the realm
+ name and the portal container name, if you want to change the default
+ value.</para>
+ </important>
+ </section>
+
+ <section id="Avoidstaticmodifieroncomponentdependency">
+ <title>Avoid <emphasis>static</emphasis> modifier on component
+ dependency</title>
+
+ <para>A local variable that stores a component dependency must not be
+ static. In other words, when you create a component A that depends on
+ component B, we don't store B in a static variable of A otherwise we
+ cannot have several different instances of A in the same JVM which is
+ not compatible with a multi-portal instance.</para>
+ </section>
+
+ <section id="Avoidcomponentinitializationbasedoncomponentdependencyintheconstructor">
+ <title>Avoid component initialization based on component dependency in
+ the constructor</title>
+
+ <para>We will have more and more extensible components (i.e. that can be
+ extended thanks to an external plugin) which means that those components
+ can only be initialized in the <emphasis>start</emphasis> method, thus
+ it is not a good practice to initialize a component in its constructor
+ if this initialization uses other components because those components
+ may not be initialized. For example, now the ResourceBundleService is
+ extensible, so if you create a component that depends on the
+ ResourceBundleService and you need the ResourceBundleService to
+ initialize your component, your component will need to be "Startable"
+ and you will have to initialize your component in a
+ <emphasis>start</emphasis> method.</para>
+ </section>
+ </chapter>
+
+ <chapter id="FAQ">
+ <title>FAQ</title>
+
+ <section id="Whathaschangedsincethepreviousversions">
+ <title>What has changed since the previous versions?</title>
+
+ <para>The main difference with previous versions is the way to package
+ your application, in previous versions you had to change the content of
+ the file <emphasis>portal.war</emphasis> in order to customize the
+ portal. Now we more consider your application as an add-on that you can
+ packaged in another ear/war file. You just need to follow some rules in
+ order to notify the platform that it must take into account your add-on
+ in order to customize the portal.</para>
+
+ <para>Among other things, you will have to:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Indicate the platform how to initialize and manage your
+ application by defining and registering the
+ <emphasis>PortalContainerDefinition</emphasis> related to your
+ portal instance.</para>
+ </listitem>
+
+ <listitem>
+ <para>Deploy the <emphasis>starter</emphasis> ear/war file that is
+ used to create and start all the portals (i.e. portal
+ containers).</para>
+ </listitem>
+ </itemizedlist>
+
+ <warning>
+ <title>Warning</title>
+
+ <para>Please take into account, that you need to ensure that the
+ <emphasis>starter</emphasis> is launched after all the other ear/war
+ files.</para>
+ </warning>
+
+ <important>
+ <title>Nota Bene</title>
+
+ <para>If you don't need to customize the portal, you don't have to
+ deploy the starter. The old way to deploy an application is still
+ compatible.</para>
+ </important>
+ </section>
+
+ <section id="Whatisthemainpurposeofaportalextension">
+ <title>What is the main purpose of a <emphasis>portal
+ extension</emphasis>?</title>
+
+ <para>An <emphasis>extension</emphasis> is just a set of files that we
+ use to customize or add new features to a given portal. An extension
+ must be the least intrusive as possible, as we could potentially have
+ several extensions for the same portal. In other words we are supposed
+ to only add what is missing in the portal and avoid to change or
+ duplicate files that are in the portal.war.</para>
+ </section>
+
+ <section id="Whatisthemainpurposeofthestarter">
+ <title>What is the main purpose of the
+ <emphasis>starter</emphasis>?</title>
+
+ <para>The <emphasis>sarter</emphasis> is a web application that has been
+ added to create and start all the portals (i.e. portal containers) at
+ the same time when all the other web applications have already been
+ started. In fact all other web applications can potentially defined
+ several things at startup such as skins, javascripts, google gadgets and
+ configuration files, thus the loading order is important as we can
+ redefine skins or configuration files or a javascript from a web
+ application 1 could depend on another javascript from a web application
+ 2 so if the web application 2 is loaded after the web application 1, we
+ will get errors in the merged javascript file.</para>
+
+ <para>If a <emphasis>PortalContainerDefinition</emphasis> has been
+ defined, the loading order will be the order that has been used to
+ define the list of dependency. And if you defined a
+ <emphasis>PortalContainerDefinition</emphasis> you need to deploy the
+ starter otherwise the loading order will be the default one (i.e. the
+ loading order of the Application Server)</para>
+
+ <para>So if you need to customize your portal by adding a new extension
+ and/or a new portal, you need to defined the related
+ <emphasis>PortalContainerDefinitions</emphasis> so you need to deploy
+ also the starter. Otherwise, you don't need to define any
+ <emphasis>PortalContainerDefinition</emphasis> and to deploy the
+ <emphasis>starter</emphasis>.</para>
+ </section>
+
+ <section id="Howaportalandaportalcontainerarerelated">
+ <title>How a portal and a portal container are related?</title>
+
+ <para>Each portal instance has its own portal container which allows the
+ portal to have its own set of components/services. It will ensure the
+ isolation between the different portal instances.</para>
+ </section>
+
+ <section id="HowtodefineandregisteraPortalContainerDefinition">
+ <title>How to define and register a
+ <emphasis>PortalContainerDefinition</emphasis>?</title>
+
+ <para>A <emphasis>PortalContainerDefinition</emphasis> allows you to
+ indicate the platform how it must initialize and manage your portal. In
+ a <emphasis>PortalContainerDefinition</emphasis>, you can define a set
+ of properties, such as:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The name of the portal container</para>
+ </listitem>
+
+ <listitem>
+ <para>The name of the context name of the rest web
+ application</para>
+ </listitem>
+
+ <listitem>
+ <para>The name of the realm</para>
+ </listitem>
+
+ <listitem>
+ <para>The list of all the dependencies of the portal container
+ ordered by priority</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>You can define and register a
+ <emphasis>PortalContainerDefinition</emphasis> thanks to an external
+ plugin that has to be treated at the <emphasis>RootContainer</emphasis>
+ level. In other words, your configuration file must be a file
+ <emphasis>conf/configuration.xml</emphasis> packaged into a jar file or
+ $AS_HOME/exo-conf/configuration.xml (for more details please have a look
+ to the wiki article <ulink
+ url="http://wiki.exoplatform.com/xwiki/bin/view/Kernel/Container+Configuration">http://wiki.exoplatform.com/xwiki/bin/view/Kernel/Container+Configuration</ulink>).</para>
+
+ <para><emphasis role="underline">See below an example of configuration
+ file that define and register a
+ PortalContainerDefinition:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the PortalContainerConfig -->
+ <target-component>org.exoplatform.container.definition.PortalContainerConfig</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>Add PortalContainer Definitions</name>
+ <!-- The name of the method to call on the PortalContainerConfig in order to register the PortalContainerDefinitions -->
+ <set-method>registerPlugin</set-method>
+ <!-- The full qualified name of the PortalContainerDefinitionPlugin -->
+ <type>org.exoplatform.container.definition.PortalContainerDefinitionPlugin</type>
+ <init-params>
+ <object-param>
+ <name>portal</name>
+ <object type="org.exoplatform.container.definition.PortalContainerDefinition">
+ <!-- The name of the portal container -->
+ <field name="name"><string>portal</string></field>
+ <!-- The name of the context name of the rest web application -->
+ <field name="restContextName"><string>rest</string></field>
+ <!-- The name of the realm -->
+ <field name="realmName"><string>exo-domain</string></field>
+ <!-- All the dependencies of the portal container ordered by loading priority -->
+ <field name="dependencies">
+ <collection type="java.util.ArrayList">
+ <value>
+ <string>eXoResources</string>
+ </value>
+ <value>
+ <string>portal</string>
+ </value>
+ <value>
+ <string>dashboard</string>
+ </value>
+ <value>
+ <string>exoadmin</string>
+ </value>
+ <value>
+ <string>eXoGadgets</string>
+ </value>
+ <value>
+ <string>eXoGadgetServer</string>
+ </value>
+ <value>
+ <string>rest</string>
+ </value>
+ <value>
+ <string>web</string>
+ </value>
+ <value>
+ <string>wsrp-producer</string>
+ </value>
+ <value>
+ <string>sample-ext</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+
+ <para>In the previous example, we define a portal container called
+ "portal", which rest context name is "rest", which realm name is
+ "exo-domain" and which dependencies are the web applications
+ "eXoResources", "portal"... The platform will load first "eXoResources",
+ then "portal" and so on.</para>
+ </section>
+
+ <section id="HowtheplatforminterpretsthedependencyorderdefinedintothePortalContainerDefinition">
+ <title>How the platform interprets the dependency order defined into the
+ PortalContainerDefinition?</title>
+
+ <para>The dependency order defined into the
+ <emphasis>PortalContainerDefinition</emphasis> is really crucial since
+ it will be interpreted the same way by several components of the
+ platform. All those components, will consider the 1st element in the
+ list is less important than the second element and so on.</para>
+
+ <para><emphasis role="underline">So it is currently used
+ to:</emphasis></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>know loading order of all the dependencies</para>
+ </listitem>
+
+ <listitem>
+ <para>If we have several
+ <emphasis>PortalContainerConfigOwner</emphasis> (see next section
+ for more details about a PortalContainerConfigOwner)</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The ServletContext of all the
+ <emphasis>PortalContainerConfigOwner</emphasis> will be unified,
+ if we use the unified ServletContext
+ (PortalContainer.getPortalContext()) to get a resource, it will
+ try to get the resource in the ServletContext of the most
+ important <emphasis>PortalContainerConfigOwner</emphasis> (i.e.
+ last in the dependency list) and if it cans find it, it will try
+ with the second most important
+ <emphasis>PortalContainerConfigOwner</emphasis> and so
+ on.</para>
+ </listitem>
+
+ <listitem>
+ <para>The ClassLoader of all the
+ <emphasis>PortalContainerConfigOwner</emphasis> will be unified,
+ if we use the unified ClassLoader
+ (PortalContainer.getPortalClassLoader()) to get a resource, it
+ will try to get the resource in the ClassLoader of the most
+ important <emphasis>PortalContainerConfigOwner</emphasis> (i.e.
+ last in the dependency list) and if it cans find it, it will try
+ with the second most important
+ <emphasis>PortalContainerConfigOwner</emphasis> and so
+ on.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="HowtochangetheServletContextnametherealmnameandortherestcontextnameofmyportalwithoutusingaPortalContainerDefinition">
+ <title>How to change the ServletContext name, the realm name and/or the
+ rest context name of my portal without using a
+ PortalContainerDefinition?</title>
+
+ <para>To do that you need first to change the default values used by a
+ PortalContainer that has not been defined thanks to a
+ <emphasis>PortalContainerDefinition</emphasis>. Those default values can
+ be modified thanks to a set of init parameters of the component
+ <emphasis>PortalContainerConfig</emphasis>.</para>
+
+ <para>The component <emphasis>PortalContainerConfig</emphasis> must be
+ registered at the <emphasis>RootContainer</emphasis> level. In other
+ words, your configuration file must be a file
+ <emphasis>conf/configuration.xml</emphasis> packaged into a jar file or
+ $AS_HOME/exo-conf/configuration.xml (for more details please have a look
+ to the wiki article <ulink
+ url="http://wiki.exoplatform.com/xwiki/bin/view/Kernel/Container+Configuration">http://wiki.exoplatform.com/xwiki/bin/view/Kernel/Container+Configuration</ulink>).</para>
+
+ <para><emphasis role="underline">In the example below we will
+ rename:</emphasis></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>the portal name "portal" to "myPortal".</para>
+ </listitem>
+
+ <listitem>
+ <para>the rest servlet context name "rest" to "myRest".</para>
+ </listitem>
+
+ <listitem>
+ <para>the realm name "exo-domain" to "my-exo-domain".</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><emphasis role="underline">See below an example</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <component>
+ <!-- The full qualified name of the PortalContainerConfig -->
+ <type>org.exoplatform.container.definition.PortalContainerConfig</type>
+ <init-params>
+ <!-- The name of the default portal container -->
+ <value-param>
+ <name>default.portal.container</name>
+ <value>myPortal</value>
+ </value-param>
+ <!-- The name of the default rest ServletContext -->
+ <value-param>
+ <name>default.rest.context</name>
+ <value>myRest</value>
+ </value-param>
+ <!-- The name of the default realm -->
+ <value-param>
+ <name>default.realm.name</name>
+ <value>my-exo-domain</value>
+ </value-param>
+ </init-params>
+ </component>
+</configuration>
+
+</programlisting>
+
+ <para>{+}Once your configuration is ready, you need to:+</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Update the file <emphasis>WEB-INF/web.xml</emphasis> of the
+ file "portal.war" by changing the "display-name" (the new value is
+ "myPortal") and the "realm-name" in the "login-config" (the new
+ value is "my-exo-domain").</para>
+ </listitem>
+
+ <listitem>
+ <para>If you use JBoss AS: Update the file
+ <emphasis>WEB-INF/jboss-web.xml</emphasis> of the file "portal.war"
+ by changing the "security-domain" (the new value is
+ "java:/jaas/my-exo-domain").</para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the "portal.war" to "myPortal.war" (or "02portal.war"
+ to "02myPortal.war")</para>
+ </listitem>
+
+ <listitem>
+ <para>Update the file <emphasis>WEB-INF/web.xml</emphasis> of the
+ file "rest.war" by changing the "display-name" (the new value is
+ "myRest") and the "realm-name" in the "login-config" (the new value
+ is "my-exo-domain").</para>
+ </listitem>
+
+ <listitem>
+ <para>If you use JBoss AS: Update the file
+ <emphasis>WEB-INF/jboss-web.xml</emphasis> of the file "rest.war" by
+ changing the "security-domain" (the new value is
+ "java:/jaas/my-exo-domain").</para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the "rest.war" to "myRest.war"</para>
+ </listitem>
+
+ <listitem>
+ <para>If "portal.war" and "rest.war" were embedded into an ear file:
+ Update the file <emphasis>META-INF/application.xml</emphasis> of the
+ file "exoplatform.ear" by remaming "02portal.war" to
+ "02myPortal.war", "portal" to "myPortal", "rest.war" to "myRest.war"
+ and "rest" to "myRest".</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The end of the process depends on your application server</para>
+
+ <section id="OnJBosstestedonJBoss5.1.0.GA">
+ <title>On JBoss (tested on JBoss 5.1.0.GA)</title>
+
+ <para>You need to change the name of the application policy in your
+ file <emphasis>conf/login-config.xml</emphasis> (the new name is
+ "my-exo-domain").</para>
+ </section>
+
+ <section id="OnTomcattestedonTomcat6.0.20">
+ <title>On Tomcat (tested on Tomcat 6.0.20)</title>
+
+ <para><emphasis role="underline">You need to:</emphasis></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Update the file
+ <emphasis>tomcat/conf/Catalina/localhost/portal.xml</emphasis> by
+ changing the "path" (the new value is "/myPortal"), the "docBase"
+ (the new value is "myPortal") and the "appName" in the "Realm"
+ definition (the new value is "my-exo-domain").</para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the file
+ <emphasis>tomcat/conf/Catalina/localhost/portal.xml</emphasis> to
+ <emphasis>myPortal.xml</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Update the file
+ <emphasis>tomcat/conf/Catalina/localhost/rest.xml</emphasis> by
+ changing the "path" (the new value is "/myRest"), the "docBase"
+ (the new value is "myRest") and the "appName" in the "Realm"
+ definition (the new value is "my-exo-domain").</para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the file
+ <emphasis>tomcat/conf/Catalina/localhost/rest.xml</emphasis> to
+ <emphasis>myRest.xml</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Change the realm name in the file
+ <emphasis>tomcat/conf/jaas.conf</emphasis> (the new name is
+ "my-exo-domain").</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+
+ <section id="Howtoaddnewconfigurationfiletoagivenportalfromawarfile">
+ <title>How to add new configuration file to a given portal from a war
+ file?</title>
+
+ <para>To indicate the platform that a given web application has
+ configuration file to provide, you need to:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>add the ServletContextListener
+ <emphasis>org.exoplatform.container.web.PortalContainerConfigOwner</emphasis>
+ in its web.xml.</para>
+ </listitem>
+
+ <listitem>
+ <para>add the servlet context name of this web application as a new
+ dependency in the <emphasis>PortalContainerDefinition</emphasis> of
+ all the portal containers for which you want to share the
+ configuration file embedded into the war file, located at
+ <emphasis>WEB-INF/conf/configuration.xml</emphasis>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The simple fact to add this Servlet Context Listener, will add the
+ Servlet Context of this web application to the Unified Servlet Context
+ of all the <emphasis>PortalContainers</emphasis> that depend on this web
+ application according to their
+ <emphasis>PortalContainerDefinition</emphasis>.</para>
+
+ <important>
+ <title>Useful Information #1</title>
+
+ <para>The position of the servlet context name of this web application
+ in the dependency list is important since the last configuration file
+ loaded has always right towards other configuration files. Each
+ configuration file loaded, could potentially redefine a configuration
+ file that has already been loaded. Moreover, as we now use a unified
+ Servlet Context to load the configuration files, if you want for
+ instance to import the file
+ <emphasis>war:/conf/database/database-configuration.xml</emphasis> and
+ this file exists in 2 different web applications, the file from the
+ last (according to the dependency order) web application will be
+ loaded.</para>
+ </important>
+
+ <important>
+ <title>Useful Information #2</title>
+
+ <para>A portal is implicitly considered as a
+ <emphasis>PortalContainerConfigOwner</emphasis> without having to
+ define the ServletContextListener
+ <emphasis>org.exoplatform.container.web.PortalContainerConfigOwner</emphasis>
+ in its web.xml.</para>
+ </important>
+
+ <para>{+}See an example of a web.xml below:+</para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+<web-app>
+ <display-name>sample-ext</display-name>
+
+ <context-param>
+ <param-name>org.exoplatform.frameworks.jcr.command.web.fckeditor.digitalAssetsWorkspace</param-name>
+ <param-value>collaboration</param-value>
+ <description>Binary assets workspace name</description>
+ </context-param>
+
+ <context-param>
+ <param-name>org.exoplatform.frameworks.jcr.command.web.fckeditor.digitalAssetsPath</param-name>
+ <param-value>/Digital Assets/</param-value>
+ <description>Binary assets path</description>
+ </context-param>
+
+ <context-param>
+ <param-name>CurrentFolder</param-name>
+ <param-value>/Digital Assets/</param-value>
+ <description>Binary assets workspace name</description>
+ </context-param>
+
+ <!-- ================================================================== -->
+ <!-- RESOURCE FILTER TO CACHE MERGED JAVASCRIPT AND CSS -->
+ <!-- ================================================================== -->
+ <filter>
+ <filter-name>ResourceRequestFilter</filter-name>
+ <filter-class>org.exoplatform.portal.application.ResourceRequestFilter</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>ResourceRequestFilter</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+
+ <!-- ================================================================== -->
+ <!-- LISTENER -->
+ <!-- ================================================================== -->
+ <listener>
+ <listener-class>org.exoplatform.container.web.PortalContainerConfigOwner</listener-class>
+ </listener>
+ <!-- ================================================================== -->
+ <!-- SERVLET -->
+ <!-- ================================================================== -->
+ <servlet>
+ <servlet-name>GateInServlet</servlet-name>
+ <servlet-class>org.gatein.wci.api.GateInServlet</servlet-class>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+ <!-- ================================================================= -->
+ <servlet-mapping>
+ <servlet-name>GateInServlet</servlet-name>
+ <url-pattern>/gateinservlet</url-pattern>
+ </servlet-mapping>
+</web-app>
+
+</programlisting>
+ </section>
+
+ <section id="Howtocreatedefineaportalextension">
+ <title>How to create/define a portal extension?</title>
+
+ <para>A portal extension is in fact a web application declared as a
+ <emphasis>PortalContainerConfigOwner</emphasis> (see previous section
+ for more details about a
+ <emphasis>PortalContainerConfigOwner</emphasis>) that has been added to
+ the dependency list of the
+ <emphasis>PortalContainerDefinition</emphasis> of a given portal.</para>
+
+ <para><emphasis role="underline">See below an example of configuration
+ file that add the portal extension "portal-ext" to the dependency list
+ of the portal "portal":</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the PortalContainerConfig -->
+ <target-component>org.exoplatform.container.definition.PortalContainerConfig</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>Add PortalContainer Definitions</name>
+ <!-- The name of the method to call on the PortalContainerConfig in order to register the PortalContainerDefinitions -->
+ <set-method>registerPlugin</set-method>
+ <!-- The full qualified name of the PortalContainerDefinitionPlugin -->
+ <type>org.exoplatform.container.definition.PortalContainerDefinitionPlugin</type>
+ <init-params>
+ <object-param>
+ <name>portal</name>
+ <object type="org.exoplatform.container.definition.PortalContainerDefinition">
+ <!-- The name of the portal container -->
+ <field name="name"><string>portal</string></field>
+ <!-- The name of the context name of the rest web application -->
+ <field name="restContextName"><string>rest</string></field>
+ <!-- The name of the realm -->
+ <field name="realmName"><string>exo-domain</string></field>
+ <!-- All the dependencies of the portal container ordered by loading priority -->
+ <field name="dependencies">
+ <collection type="java.util.ArrayList">
+ <value>
+ <string>eXoResources</string>
+ </value>
+ <value>
+ <string>portal</string>
+ </value>
+ <value>
+ <string>dashboard</string>
+ </value>
+ <value>
+ <string>exoadmin</string>
+ </value>
+ <value>
+ <string>eXoGadgets</string>
+ </value>
+ <value>
+ <string>eXoGadgetServer</string>
+ </value>
+ <value>
+ <string>rest</string>
+ </value>
+ <value>
+ <string>web</string>
+ </value>
+ <value>
+ <string>wsrp-producer</string>
+ </value>
+ <!-- The sample-ext has been added at the end of the dependency list in order to have the highest priority towards
+ the other web applications and particularly towards "portal" -->
+ <value>
+ <string>sample-ext</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+ </section>
+
+ <section id="Howtodeployaportalextension">
+ <title>How to deploy a portal extension?</title>
+
+ <para>Refer to <emphasis>How to deploy the sample
+ extension?</emphasis></para>
+ </section>
+
+ <section id="Howtocreatedefineanewportal">
+ <title>How to create/define a new portal?</title>
+
+ <para>You have no need anymore, to duplicate the entire "portal.war"
+ file to create a new portal, you just to duplicate the following files
+ from the original "portal.war":</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>login/jsp/login.jsp</para>
+ </listitem>
+
+ <listitem>
+ <para>login/skin: You can customize the css files and
+ pictures</para>
+ </listitem>
+
+ <listitem>
+ <para>bookmark.jsp</para>
+ </listitem>
+
+ <listitem>
+ <para>favicon.ico: You can replace it by your own logo</para>
+ </listitem>
+
+ <listitem>
+ <para>index.jsp</para>
+ </listitem>
+
+ <listitem>
+ <para>portal-unavailable.jsp</para>
+ </listitem>
+
+ <listitem>
+ <para>portal-warning.jsp</para>
+ </listitem>
+
+ <listitem>
+ <para>WEB-INF/web.xml: You just need to change the "display-name"
+ and set a different value for the "realm-name" in the
+ "login-config". Indeed, we must have one realm name per
+ portal.</para>
+ </listitem>
+
+ <listitem>
+ <para>WEB-INF/jboss-web.xml: If you use JBoss AS, you need to
+ duplicate also this file and set the new "security-domain" with the
+ new realm name.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>You need also to duplicate the "rest.war" file to create a
+ dedicated rest web application for your portal as we must have one rest
+ web application per portal, in fact you just need to duplicate the
+ following files from the original "rest.war":</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>WEB-INF/web.xml: You just need to change the "display-name"
+ and set a different value for the "realm-name" in the
+ "login-config". Indeed, we must have one realm name per
+ portal.</para>
+ </listitem>
+
+ <listitem>
+ <para>WEB-INF/jboss-web.xml: If you use JBoss AS, you need to
+ duplicate also this file and set the new "security-domain" with the
+ new realm name.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>Finally you need to register and define the corresponding
+ <emphasis>PortalContainerDefinition</emphasis>. The
+ <emphasis>PortalContainerDefinition</emphasis> of your portal will be
+ composed of:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The name of new portal</para>
+ </listitem>
+
+ <listitem>
+ <para>The name of the context name of the new rest web
+ application</para>
+ </listitem>
+
+ <listitem>
+ <para>The name of the new realm</para>
+ </listitem>
+
+ <listitem>
+ <para>The list of all the dependencies of the original portal, with
+ the new name of the rest web application instead of the old name
+ (i.e. "rest") and with a new dependency which is in fact the name of
+ your portal. As we leave the dependency of the original portal in
+ the list of dependencies, it will load the configuration files of
+ original "portal.war" file.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><emphasis role="underline">See an example below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the PortalContainerConfig -->
+ <target-component>org.exoplatform.container.definition.PortalContainerConfig</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>Add PortalContainer Definitions</name>
+ <!-- The name of the method to call on the PortalContainerConfig in order to register the PortalContainerDefinitions -->
+ <set-method>registerPlugin</set-method>
+ <!-- The full qualified name of the PortalContainerDefinitionPlugin -->
+ <type>org.exoplatform.container.definition.PortalContainerDefinitionPlugin</type>
+ <init-params>
+ <object-param>
+ <name>sample-portal</name>
+ <object type="org.exoplatform.container.definition.PortalContainerDefinition">
+ <!-- The name of the portal container -->
+ <field name="name"><string>sample-portal</string></field>
+ <!-- The name of the context name of the rest web application -->
+ <field name="restContextName"><string>rest-sample-portal</string></field>
+ <!-- The name of the realm -->
+ <field name="realmName"><string>exo-domain-sample-portal</string></field>
+ <!-- All the dependencies of the portal container ordered by loading priority -->
+ <field name="dependencies">
+ <collection type="java.util.ArrayList">
+ <value>
+ <string>eXoResources</string>
+ </value>
+ <value>
+ <string>portal</string>
+ </value>
+ <value>
+ <string>dashboard</string>
+ </value>
+ <value>
+ <string>exoadmin</string>
+ </value>
+ <value>
+ <string>eXoGadgets</string>
+ </value>
+ <value>
+ <string>eXoGadgetServer</string>
+ </value>
+ <value>
+ <string>rest-sample-portal</string>
+ </value>
+ <value>
+ <string>web</string>
+ </value>
+ <value>
+ <string>wsrp-producer</string>
+ </value>
+ <value>
+ <string>sample-portal</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+
+ <important>
+ <title>Useful Information #1</title>
+
+ <para>A portal is implicitly a
+ <emphasis>PortalContainerConfigOwner</emphasis> which means that it
+ shares the configuration file embedded into the war file, located at
+ <emphasis>WEB-INF/conf/configuration.xml</emphasis></para>
+ </important>
+
+ <important>
+ <title>Useful Information #2</title>
+
+ <para>The position of the servlet context name of this web application
+ in the dependency list is important since the last configuration file
+ loaded has always right towards other configuration files. Each
+ configuration file loaded, could potentially redefine a configuration
+ file that has already been loaded. Moreover, as we now use a unified
+ Servlet Context to load the configuration files, if you want for
+ instance to import the file
+ <emphasis>war:/conf/database/database-configuration.xml</emphasis> and
+ this file exists in 2 different web applications, the file from the
+ last (according to the dependency order) web application will be
+ loaded.</para>
+ </important>
+ </section>
+
+ <section id="Howtodeployanewportal">
+ <title>How to deploy a new portal?</title>
+
+ <para>Refer to <emphasis>How to deploy the sample
+ portal?</emphasis></para>
+ </section>
+
+ <section id="Howtoimportproperlyaconfigurationfileusingtheprefixwar">
+ <title>How to import properly a configuration file using the prefix
+ "war:"?</title>
+
+ <para>Now, the <emphasis>ConfigurationManager</emphasis> uses by default
+ the unified servlet context of the portal in order to get any resources
+ in particular the configuration files. The unified servlet context is
+ aware of the priorities that has been set in the
+ <emphasis>PortalContainerDefinition</emphasis> of the portal. In other
+ words, if you want for instance to import the file
+ <emphasis>war:/conf/database/database-configuration.xml</emphasis> and
+ this file exists in 2 different web applications, the file from the last
+ (according to the dependency order) web application will be
+ loaded.</para>
+
+ <para>So, in order to avoid issues when we would like to package several
+ products at the same time (i.e. WCM, DMS, CS, KS), we need to:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Avoid the best you can to redefine a configuration file from
+ the "portal.war" by using the exact same path (like the previous
+ example)</para>
+ </listitem>
+
+ <listitem>
+ <para>Add your configuration files in a dedicated folder which name
+ will be the name of the product, in oder to ensure that no other
+ products will use the same path</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>The example below, is an the example of a file
+ <emphasis>WEB-INF/conf/configuration.xml</emphasis> of the product
+ "sample-ext".</para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <import>war:/conf/sample-ext/common/common-configuration.xml</import>
+ <import>war:/conf/sample-ext/jcr/jcr-configuration.xml</import>
+ <import>war:/conf/sample-ext/portal/portal-configuration.xml</import>
+ <import>war:/conf/sample-ext/web/web-inf-extension-configuration.xml</import>
+</configuration>
+
+</programlisting>
+ </section>
+
+ <section id="Howtoavoidduplicatingconfigurationfilesjusttorenameasimplevalue">
+ <title>How to avoid duplicating configuration files just to rename a
+ simple value?</title>
+
+ <para>In your configuration file, you can use a special variable called
+ <emphasis>container.name.suffix</emphasis> in order to add a suffix to
+ values that could change between portal containers. The value of this
+ variable will be an empty sting if no
+ <emphasis>PortalContainerDefinition</emphasis> has been defined
+ otherwise the value will be
+ <emphasis>\-$portal.container.name</emphasis>. <emphasis
+ role="underline">See an example below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <component>
+ <key>org.exoplatform.services.database.HibernateService</key>
+ <jmx-name>database:type=HibernateService</jmx-name>
+ <type>org.exoplatform.services.database.impl.HibernateServiceImpl</type>
+ <init-params>
+ <properties-param>
+ <name>hibernate.properties</name>
+ <description>Default Hibernate Service</description>
+ <property name="hibernate.show_sql" value="false"/>
+ <property name="hibernate.cglib.use_reflection_optimizer" value="true"/>
+ <property name="hibernate.connection.url" value="jdbc:hsqldb:file:../temp/data/exodb${container.name.suffix}"/>
+ <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
+ <property name="hibernate.connection.autocommit" value="true"/>
+ <property name="hibernate.connection.username" value="sa"/>
+ <property name="hibernate.connection.password" value=""/>
+ <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
+ <property name="hibernate.c3p0.min_size" value="5"/>
+ <property name="hibernate.c3p0.max_size" value="20"/>
+ <property name="hibernate.c3p0.timeout" value="1800"/>
+ <property name="hibernate.c3p0.max_statements" value="50"/>
+ </properties-param>
+ </init-params>
+ </component>
+</configuration>
+
+</programlisting>
+ </section>
+
+ <section id="HowtoaddorchangeaRepositoryandoraWorkspace">
+ <title>How to add or change a Repository and/or a Workspace?</title>
+
+ <para>Now you can add new JCR repositories or workspaces thanks to an
+ external plugin, the configuration of your JCR Repositories will be
+ merged knowing that the merge algorithm will:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>add missing Repository Definitions and/or Workspace
+ Definitions.</para>
+ </listitem>
+
+ <listitem>
+ <para>change the properties of a Repository Definition if it has
+ already been defined</para>
+ </listitem>
+
+ <listitem>
+ <para>replace the Workspace Definition if it has already been
+ defined.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><emphasis role="underline">See an example of jcr-configuration.xml
+ below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the RepositoryServiceConfiguration -->
+ <target-component>org.exoplatform.services.jcr.config.RepositoryServiceConfiguration</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>Sample RepositoryServiceConfiguration Plugin</name>
+ <!-- The name of the method to call on the RepositoryServiceConfiguration in order to add the RepositoryServiceConfigurations -->
+ <set-method>addConfig</set-method>
+ <!-- The full qualified name of the RepositoryServiceConfigurationPlugin -->
+ <type>org.exoplatform.services.jcr.impl.config.RepositoryServiceConfigurationPlugin</type>
+ <init-params>
+ <value-param>
+ <name>conf-path</name>
+ <description>JCR configuration file</description>
+ <value>war:/conf/sample-ext/jcr/repository-configuration.xml</value>
+ </value-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+
+ <para>{+}See an example of repository-configuration.xml below:+</para>
+
+ <programlisting><repository-service default-repository="repository">
+ <repositories>
+ <repository name="repository" system-workspace="system" default-workspace="portal-system">
+ <security-domain>exo-domain</security-domain>
+ <access-control>optional</access-control>
+ <authentication-policy>org.exoplatform.services.jcr.impl.core.access.JAASAuthenticator</authentication-policy>
+ <workspaces>
+ <workspace name="sample-ws">
+ <container class="org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer">
+ <properties>
+ <property name="source-name" value="jdbcexo${container.name.suffix}" />
+ <property name="dialect" value="hsqldb" />
+ <property name="multi-db" value="false" />
+ <property name="update-storage" value="true" />
+ <property name="max-buffer-size" value="204800" />
+ <property name="swap-directory" value="../temp/swap/sample-ws${container.name.suffix}" />
+ </properties>
+ <value-storages>
+ <value-storage id="sample-ws" class="org.exoplatform.services.jcr.impl.storage.value.fs.TreeFileValueStorage">
+ <properties>
+ <property name="path" value="../temp/values/sample-ws${container.name.suffix}" />
+ </properties>
+ <filters>
+ <filter property-type="Binary" />
+ </filters>
+ </value-storage>
+ </value-storages>
+ </container>
+ <initializer class="org.exoplatform.services.jcr.impl.core.ScratchWorkspaceInitializer">
+ <properties>
+ <property name="root-nodetype" value="nt:unstructured" />
+ <property name="root-permissions"
+ value="any read;*:/platform/administrators read;*:/platform/administrators add_node;*:/platform/administrators set_property;*:/platform/administrators remove" />
+ </properties>
+ </initializer>
+ <cache enabled="true">
+ <properties>
+ <property name="max-size" value="20000" />
+ <property name="live-time" value="30000" />
+ </properties>
+ </cache>
+ <query-handler class="org.exoplatform.services.jcr.impl.core.query.lucene.SearchIndex">
+ <properties>
+ <property name="index-dir" value="../temp/jcrlucenedb/sample-ws${container.name.suffix}" />
+ </properties>
+ </query-handler>
+ <lock-manager>
+ <time-out>15m</time-out><!-- 15min -->
+ <persister class="org.exoplatform.services.jcr.impl.core.lock.FileSystemLockPersister">
+ <properties>
+ <property name="path" value="../temp/lock/sample-ws${container.name.suffix}" />
+ </properties>
+ </persister>
+ </lock-manager>
+ </workspace>
+ </workspaces>
+ </repository>
+ </repositories>
+</repository-service>
+
+</programlisting>
+
+ <warning>
+ <title>Warning</title>
+
+ <para>If you have to change the default repository or the default
+ workspace, please be careful since it could cause side effects as you
+ could be incompatible with some portal configuration files that refer
+ explicitly to <emphasis>portal-system</emphasis> and/or to
+ <emphasis>repository</emphasis>. To solve this problem you can either
+ redefine the configuration file in a portal extension to change the
+ workspace name and/or the repository name or you could also add your
+ own repository instead of your own workspace.</para>
+ </warning>
+ </section>
+
+ <section id="HowtoaddnewResourceBundlestomyportal">
+ <title>How to add new ResourceBundles to my portal?</title>
+
+ <para>Now you can add new Resource Bundles, thanks to an external
+ plugin.</para>
+
+ <para><emphasis role="underline">See an example below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the ResourceBundleService -->
+ <target-component>org.exoplatform.services.resources.ResourceBundleService</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>Sample ResourceBundle Plugin</name>
+ <!-- The name of the method to call on the ResourceBundleService in order to register the ResourceBundles -->
+ <set-method>addResourceBundle</set-method>
+ <!-- The full qualified name of the BaseResourceBundlePlugin -->
+ <type>org.exoplatform.services.resources.impl.BaseResourceBundlePlugin</type>
+ <init-params>
+ <!--values-param>
+ <name>classpath.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>init.resources</name>
+ <description>Store the following resources into the db for the first launch </description>
+ <value>locale.portal.sample</value>
+ </values-param>
+ <values-param>
+ <name>portal.resource.names</name>
+ <description>The properties files of the portal , those file will be merged
+ into one ResoruceBundle properties </description>
+ <value>locale.portal.sample</value>
+ </values-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+ </section>
+
+ <section id="HowtooverwriteexistingResourceBundlesinmyportal">
+ <title>How to overwrite existing ResourceBundles in my portal?</title>
+
+ <para>Now each portal container has its own
+ <emphasis>ClassLoader</emphasis> which is automatically set for you at
+ runtime (FYI: it could be retrieved thanks to
+ <emphasis>portalContainer.getPortalClassLoader()</emphasis>). This
+ <emphasis>ClassLoader</emphasis> is an unified
+ <emphasis>ClassLoader</emphasis> that is also aware of the dependency
+ order defined into the <emphasis>PortalContainerDefinition</emphasis>,
+ so to add new keys or update key values, you just need to:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Add the corresponding resource bundle with the same name, with
+ <emphasis role="underline">the same extension</emphasis> (xml or
+ properties) at the same location into the
+ <emphasis>classpath</emphasis> of your Web application (i.e.
+ directly into the <emphasis>WEB-INF/classes</emphasis> directory or
+ into a jar file in the <emphasis>WEB-INF/lib</emphasis>
+ directory)</para>
+ </listitem>
+
+ <listitem>
+ <para>Ensure that your web application is defined after the web
+ application of the portal in the dependency list of the related
+ <emphasis>PortalContainerDefinition</emphasis>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>In the example below, we want to change the values of the keys
+ <emphasis>UIHomePagePortlet.Label.Username</emphasis> and
+ <emphasis>UIHomePagePortlet.Label.Password</emphasis>, and add the new
+ key <emphasis>UIHomePagePortlet.Label.SampleKey</emphasis> into the
+ Resource Bundle <emphasis>locale.portal.webui</emphasis>.</para>
+
+ <note>
+ <title>WEB-INF/classes/local/portal/webui_en.properties</title>
+
+ <programlisting>#############################################################################
+#org.exoplatform.portal.webui.component.UIHomePagePortlet #
+#############################################################################
+
+UIHomePagePortlet.Label.Username=Usr:
+UIHomePagePortlet.Label.Password=Pwd:
+UIHomePagePortlet.Label.SampleKey=This is a new key that has been added to the Resource Bundle "locale.portal.webui" of "sample-ext"
+
+</programlisting>
+ </note>
+ </section>
+
+ <section id="Howtoreplaceagroovytemplateofmyportal">
+ <title>How to replace a groovy template of my portal?</title>
+
+ <para>Now each portal container has its own
+ <emphasis>ServletContext</emphasis> which is automatically set for you
+ at runtime (FYI: it could be retrieved thanks to
+ <emphasis>portalContainer.getPortalContext()</emphasis>). This
+ <emphasis>ServletContext</emphasis> is an unified
+ <emphasis>ServletContext</emphasis> that is also aware of the dependency
+ order defined into the <emphasis>PortalContainerDefinition</emphasis> so
+ to replace a groovy template of the portal, you just need to:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Add the corresponding groovy template with the same name at
+ the same location into your Web application</para>
+ </listitem>
+
+ <listitem>
+ <para>Ensure that your web application is defined after the web
+ application of the portal in the dependency list of the related
+ <emphasis>PortalContainerDefinition</emphasis>.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section id="HowtoaddnewPortalConfigurationsNavigationsPagesorPortletPreferencestomyportal">
+ <title>How to add new Portal Configurations, Navigations, Pages or
+ Portlet Preferences to my portal?</title>
+
+ <para>Now you can add new Portal Configurations, Navigations, Pages or
+ Portlet Preferences thanks to an external plugin.</para>
+
+ <para><emphasis role="underline">See an example below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="ISO-8859-1"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the UserPortalConfigService -->
+ <target-component>org.exoplatform.portal.config.UserPortalConfigService</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>new.portal.config.user.listener</name>
+ <!-- The name of the method to call on the UserPortalConfigService in order to register the NewPortalConfigs -->
+ <set-method>initListener</set-method>
+ <!-- The full qualified name of the NewPortalConfigListener -->
+ <type>org.exoplatform.portal.config.NewPortalConfigListener</type>
+ <description>this listener init the portal configuration</description>
+ <init-params>
+ <object-param>
+ <name>portal.configuration</name>
+ <description>description</description>
+ <object type="org.exoplatform.portal.config.NewPortalConfig">
+ <field name="predefinedOwner">
+ <collection type="java.util.HashSet">
+ <value>
+ <string>classic</string>
+ </value>
+ </collection>
+ </field>
+ <field name="ownerType">
+ <string>portal</string>
+ </field>
+ <field name="templateLocation">
+ <string>war:/conf/sample-ext/portal</string>
+ </field>
+ </object>
+ </object-param>
+ <object-param>
+ <name>group.configuration</name>
+ <description>description</description>
+ <object type="org.exoplatform.portal.config.NewPortalConfig">
+ <field name="predefinedOwner">
+ <collection type="java.util.HashSet">
+ <value>
+ <string>platform/users</string>
+ </value>
+ </collection>
+ </field>
+ <field name="ownerType">
+ <string>group</string>
+ </field>
+ <field name="templateLocation">
+ <string>war:/conf/sample-ext/portal</string>
+ </field>
+ </object>
+ </object-param>
+ <object-param>
+ <name>user.configuration</name>
+ <description>description</description>
+ <object type="org.exoplatform.portal.config.NewPortalConfig">
+ <field name="predefinedOwner">
+ <collection type="java.util.HashSet">
+ <value>
+ <string>root</string>
+ </value>
+ </collection>
+ </field>
+ <field name="ownerType">
+ <string>user</string>
+ </field>
+ <field name="templateLocation">
+ <string>war:/conf/sample-ext/portal</string>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+ </section>
+
+ <section id="HowtoaddnewHttpFilterstomyportalwithoutmodifyingtheportalbinary">
+ <title>How to add new Http Filters to my portal without modifying the
+ portal binary?</title>
+
+ <para>We added a <emphasis>GenericFilter</emphasis> that allows you to
+ define new Http Filters thanks to an external plugin. Your filter will
+ need to implement the interface
+ <emphasis>org.exoplatform.web.filter.Filter</emphasis>.</para>
+
+ <para><emphasis role="underline">See an example of configuration
+ below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the ExtensibleFilter -->
+ <target-component>org.exoplatform.web.filter.ExtensibleFilter</target-component>
+ <component-plugin>
+ <!-- The name of the plugin -->
+ <name>Sample Filter Definition Plugin</name>
+ <!-- The name of the method to call on the ExtensibleFilter in order to register the FilterDefinitions -->
+ <set-method>addFilterDefinitions</set-method>
+ <!-- The full qualified name of the FilterDefinitionPlugin -->
+ <type>org.exoplatform.web.filter.FilterDefinitionPlugin</type>
+ <init-params>
+ <object-param>
+ <name>Sample Filter Definition</name>
+ <object type="org.exoplatform.web.filter.FilterDefinition">
+ <!-- The filter instance -->
+ <field name="filter"><object type="org.exoplatform.sample.ext.web.SampleFilter"/></field>
+ <!-- The mapping to use -->
+ <!-- WARNING: the mapping is expressed with regular expressions -->
+ <field name="patterns">
+ <collection type="java.util.ArrayList" item-type="java.lang.String">
+ <value>
+ <string>/.*</string>
+ </value>
+ </collection>
+ </field>
+ </object>
+ </object-param>
+ </init-params>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+
+ <para>{+}See an example of Filter below:+</para>
+
+ <note>
+ <title>SampleFilter.java</title>
+
+ <programlisting>...
+import org.exoplatform.web.filter.Filter;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public class SampleFilter implements Filter
+{
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+ ServletException
+ {
+ System.out.println("SampleFilter start");
+ try
+ {
+ chain.doFilter(request, response);
+ }
+ finally
+ {
+ System.out.println("SampleFilter end");
+ }
+ }
+}
+
+</programlisting>
+ </note>
+ </section>
+
+ <section id="HowtoaddnewHttpSessionListenersandorServletContextListenerstomyportalwithoutmodifyingtheportalbinary">
+ <title>How to add new <emphasis>HttpSessionListeners</emphasis> and/or
+ <emphasis>ServletContextListeners</emphasis> to my portal without
+ modifying the portal binary?</title>
+
+ <para>We added a <emphasis>GenericHttpListener</emphasis> that allows
+ you to define new <emphasis>HttpSessionListeners</emphasis> and/or
+ <emphasis>ServletContextListeners</emphasis> thanks to an external
+ plugin. Actually, the <emphasis>GenericHttpListener</emphasis> will
+ broadcast events thanks to the <emphasis>ListenerService</emphasis> that
+ you can easily capture. The events that it broadcasts are:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para><emphasis>org.exoplatform.web.GenericHttpListener.sessionCreated</emphasis>:
+ When a new session is created in the portal.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>org.exoplatform.web.GenericHttpListener.sessionDestroyed</emphasis>:
+ When a session is destroyed in the portal.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>org.exoplatform.web.GenericHttpListener.contextInitialized</emphasis>:
+ When the servlet context of the portal is initialized.</para>
+ </listitem>
+
+ <listitem>
+ <para><emphasis>org.exoplatform.web.GenericHttpListener.contextDestroyed</emphasis>:
+ When the servlet context of the portal is destroyed.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para>If you want to listen to
+ <emphasis>org.exoplatform.web.GenericHttpListener.sessionCreated</emphasis>,
+ you will need to create a Listener that extends
+ _Listener<PortalContainer, HttpSessionEvent>_If you want to listen
+ to \_org.exoplatform.web.GenericHttpListener.sessionDestroyed_, you will
+ need to create a Listener that extends _Listener<PortalContainer,
+ HttpSessionEvent>_If you want to listen to
+ \_org.exoplatform.web.GenericHttpListener.contextInitialized_, you will
+ need to create a Listener that extends _Listener<PortalContainer,
+ ServletContextEvent>_If you want to listen to
+ \_org.exoplatform.web.GenericHttpListener.contextDestroyed_, you will
+ need to create a Listener that extends
+ <emphasis>Listener<PortalContainer,
+ ServletContextEvent></emphasis></para>
+
+ <para><emphasis role="underline">See an example of configuration
+ below:</emphasis></para>
+
+ <programlisting><?xml version="1.0" encoding="UTF-8"?>
+<configuration
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd http://www.exoplaform.org/xml/ns/kernel_1_0.xsd"
+ xmlns="http://www.exoplaform.org/xml/ns/kernel_1_0.xsd">
+ <external-component-plugins>
+ <!-- The full qualified name of the ListenerService -->
+ <target-component>org.exoplatform.services.listener.ListenerService</target-component>
+ <component-plugin>
+ <!-- The name of the listener that is also the name of the target event -->
+ <name>org.exoplatform.web.GenericHttpListener.sessionCreated</name>
+ <!-- The name of the method to call on the ListenerService in order to register the Listener -->
+ <set-method>addListener</set-method>
+ <!-- The full qualified name of the Listener -->
+ <type>org.exoplatform.sample.ext.web.SampleHttpSessionCreatedListener</type>
+ </component-plugin>
+ <component-plugin>
+ <!-- The name of the listener that is also the name of the target event -->
+ <name>org.exoplatform.web.GenericHttpListener.sessionDestroyed</name>
+ <!-- The name of the method to call on the ListenerService in order to register the Listener -->
+ <set-method>addListener</set-method>
+ <!-- The full qualified name of the Listener -->
+ <type>org.exoplatform.sample.ext.web.SampleHttpSessionDestroyedListener</type>
+ </component-plugin>
+ <component-plugin>
+ <!-- The name of the listener that is also the name of the target event -->
+ <name>org.exoplatform.web.GenericHttpListener.contextInitialized</name>
+ <!-- The name of the method to call on the ListenerService in order to register the Listener -->
+ <set-method>addListener</set-method>
+ <!-- The full qualified name of the Listener -->
+ <type>org.exoplatform.sample.ext.web.SampleContextInitializedListener</type>
+ </component-plugin>
+ <component-plugin>
+ <!-- The name of the listener that is also the name of the target event -->
+ <name>org.exoplatform.web.GenericHttpListener.contextDestroyed</name>
+ <!-- The name of the method to call on the ListenerService in order to register the Listener -->
+ <set-method>addListener</set-method>
+ <!-- The full qualified name of the Listener -->
+ <type>org.exoplatform.sample.ext.web.SampleContextDestroyedListener</type>
+ </component-plugin>
+ </external-component-plugins>
+</configuration>
+
+</programlisting>
+
+ <para>{+}See an example of Session Listener below:+</para>
+
+ <note>
+ <title>SampleHttpSessionCreatedListener.java</title>
+
+ <programlisting>..
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.services.listener.Event;
+import org.exoplatform.services.listener.Listener;
+
+import javax.servlet.http.HttpSessionEvent;
+
+public class SampleHttpSessionCreatedListener extends Listener<PortalContainer, HttpSessionEvent>
+{
+
+ @Override
+ public void onEvent(Event<PortalContainer, HttpSessionEvent> event) throws Exception
+ {
+ System.out.println("Creating a new session");
+ }
+}
+
+</programlisting>
+ </note>
+
+ <para>{+}See an example of Context Listener below:+</para>
+
+ <note>
+ <title>SampleContextInitializedListener.java</title>
+
+ <programlisting>..
+import org.exoplatform.container.PortalContainer;
+import org.exoplatform.services.listener.Event;
+import org.exoplatform.services.listener.Listener;
+
+import javax.servlet.ServletContextEvent;
+
+public class SampleContextInitializedListener extends Listener<PortalContainer, ServletContextEvent>
+{
+
+ @Override
+ public void onEvent(Event<PortalContainer, ServletContextEvent> event) throws Exception
+ {
+ System.out.println("Initializing the context");
+ }
+}
+
+</programlisting>
+ </note>
+ </section>
+
+ <section id="HowtoaddnewHttpServlettomyportalwithoutmodifyingtheportalbinary">
+ <title>How to add new <emphasis>HttpServlet</emphasis> to my portal
+ without modifying the portal binary?</title>
+
+ <para>Actually, it is not possible but you can create a rest component
+ instead. For more details about rest, please refer to the following wiki
+ article <ulink
+ url="http://wiki.exoplatform.com/xwiki/bin/view/WS">http://wiki.exoplatform.com/xwiki/bin/view/WS</ulink>.</para>
+ </section>
+
+ <section id="HowtooverrideoraddaContextParametertomyportalwithoutmodifyingtheportalbinary">
+ <title>How to override or add a Context Parameter to my portal without
+ modifying the portal binary?</title>
+
+ <para>Actually, you have nothing to do, you just need to ensure that you
+ get the context parameter value from the unified servlet context of the
+ portal, that should be set for you but you can still get it from
+ <emphasis>portalContainer.getPortalContext()</emphasis>.</para>
+ </section>
+
+ <section id="WherecanIfoundanexampleofhowtoextendmyportal">
+ <title>Where can I found an example of how to extend my portal?</title>
+
+ <para>We added an example of portal extension (i.e. ability to customize
+ a portal without changing anything in the portal.ear) that you can find
+ in the svn of gatein at gatein/sample/extension.</para>
+ </section>
+
+ <section id="Howtodeploythesampleextension">
+ <title>How to deploy the sample extension?</title>
+
+ <section id="OnJBosstestedonJBoss5.1.0.GA2">
+ <title>On JBoss (tested on JBoss 5.1.0.GA)</title>
+
+ <para>We assume that you have a clean JBoss version of GateIn, in
+ other words, we assume that you have already the file
+ <emphasis>exoplatform.ear</emphasis> in the
+ <emphasis>deploy</emphasis> directory of JBoss and you have the
+ related application policy in your
+ <emphasis>conf/login-config.xml</emphasis>.</para>
+
+ <para><emphasis role="underline">You need to:</emphasis></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Add the file <emphasis>sample-ext.ear</emphasis> from
+ sample/extension/ear/target/ to the deploy directory of JBoss,
+ this file contains:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The file <emphasis>sample-ext.war</emphasis> which is
+ the web application that contains (potentially) configuration
+ files, groovy templates, resource bundles, skins and
+ javascript files, that will extend the portal.</para>
+ </listitem>
+
+ <listitem>
+ <para>The file
+ <emphasis>exo.portal.sample.extension.config-X.Y.Z.jar</emphasis>
+ which is the file in which we defined the
+ <emphasis>PortalContainerDefinition</emphasis> of the original
+ portal in which we added <emphasis>sample-ext</emphasis> at
+ the end of dependency list.</para>
+ </listitem>
+
+ <listitem>
+ <para>The file
+ <emphasis>exo.portal.sample.extension.jar-X.Y.Z.jar</emphasis>
+ which is the file in which we have internal classes that are
+ actualy a set of sample classes <emphasis>(SampleFilter,
+ SampleContextInitializedListener,
+ SampleContextDestroyedListener,
+ SampleHttpSessionCreatedListener and
+ SampleHttpSessionDestroyedListener)</emphasis></para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>Add the file <emphasis>starter.ear</emphasis> from
+ starter/ear/target/ to the deploy directory of JBoss, this file
+ contains:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The file <emphasis>starter.war</emphasis> which is the
+ web application that will create and start all the portal
+ containers, that is why it must be launched after all the
+ other web applications.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+
+ <warning>
+ <title>Warning #1</title>
+
+ <para>This can only work if a Unified ClassLoader has been
+ configured on your JBoss (default behavior) and the load order is
+ first the <emphasis>exoplatform.ear</emphasis> then the
+ <emphasis>sample-ext.ear</emphasis> and finally the
+ <emphasis>starter.ear</emphasis>.</para>
+ </warning>
+
+ <warning>
+ <title>Warning #2</title>
+
+ <para>The file <emphasis>starter.ear</emphasis> must always been
+ started last.</para>
+ </warning>
+ </section>
+
+ <section id="OnTomcattestedonTomcat6.0.202">
+ <title>On Tomcat (tested on Tomcat 6.0.20)</title>
+
+ <para>We assume that you have a clean Tomcat version of GateIn, in
+ other words, we assume that you have already all the jar files of
+ GateIn and their dependencies into <emphasis>tomcat/lib</emphasis>,
+ you have all the war files of GateIn into
+ <emphasis>tomcat/webapps</emphasis> and you have the realm name
+ "exo-domain" defined into the file
+ <emphasis>tomcat/conf/jaas.conf</emphasis>.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Add the file <emphasis>sample-ext.war</emphasis> from
+ sample/extension/war/target/ to the
+ <emphasis>tomcat/webapps</emphasis> directory. <emphasis>(See the
+ purpose of this file in the JBoss section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the folder <emphasis>starter</emphasis> from
+ starter/war/target/ to the <emphasis>tomcat/webapps</emphasis>
+ directory. <emphasis>(See the purpose of this file in the JBoss
+ section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the directory (unzipped folder)
+ <emphasis>starter</emphasis> to <emphasis>starter.war</emphasis>
+ (for more details see the warning below)</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the jar file
+ <emphasis>exo.portal.sample.extension.config-X.Y.Z.jar</emphasis>
+ from sample/extension/config/target/ to the
+ <emphasis>tomcat/lib</emphasis> directory. <emphasis>(See the
+ purpose of this file in the JBoss section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the jar file
+ <emphasis>exo.portal.sample.extension.jar-X.Y.Z.jar</emphasis>
+ from sample/extension/jar/target/ to the
+ <emphasis>tomcat/lib</emphasis> directory. <emphasis>(See the
+ purpose of this file in the JBoss section)</emphasis>.</para>
+ </listitem>
+ </itemizedlist>
+
+ <warning>
+ <title>Warning</title>
+
+ <para>This can only work if the <emphasis>starter.war</emphasis> is
+ the last war file to be loaded, so don't hesitate to rename it if
+ your war files are loaded following to the alphabetic order.</para>
+ </warning>
+ </section>
+ </section>
+
+ <section id="WherecanIfoundanexampleofhowtocreateanewportal">
+ <title>Where can I found an example of how to create a new
+ portal?</title>
+
+ <para>We added an example of new portal (i.e. ability to create a new
+ portal from another portal without changing anything in the portal.ear)
+ that you can find in the svn of gatein at gatein/sample/portal.</para>
+ </section>
+
+ <section id="Howtodeploythesampleportal">
+ <title>How to deploy the sample portal?</title>
+
+ <section id="OnJBosstestedonJBoss5.1.0.GA3">
+ <title>On JBoss (tested on JBoss 5.1.0.GA)</title>
+
+ <para>We assume that you have a clean JBoss version of GateIn, in
+ other words, we assume that you have already the file
+ <emphasis>exoplatform.ear</emphasis> in the
+ <emphasis>deploy</emphasis> directory of JBoss and you have the
+ related application policy in your
+ <emphasis>conf/login-config.xml</emphasis>.</para>
+
+ <para><emphasis role="underline">You need to:</emphasis></para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Add the file <emphasis>sample-portal.ear</emphasis> from
+ <emphasis>sample/portal/ear/target/</emphasis> to the deploy
+ directory of JBoss, this file contains:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The file <emphasis>sample-portal.war</emphasis> which is
+ the entry point of the new portal</para>
+ </listitem>
+
+ <listitem>
+ <para>The file <emphasis>rest-sample-portal.war</emphasis>
+ which is the entry point for <emphasis>rest</emphasis> outside
+ the portal (in the portal you can access to
+ <emphasis>rest</emphasis> thanks to path prefix
+ <emphasis>/sample-portal/rest</emphasis>)</para>
+ </listitem>
+
+ <listitem>
+ <para>The file
+ <emphasis>exo.portal.sample.portal.config-X.Y.Z.jar</emphasis>
+ which is the file in which we defined the
+ <emphasis>PortalContainerDefinition</emphasis> of this
+ portal</para>
+ </listitem>
+
+ <listitem>
+ <para>The file
+ <emphasis>exo.portal.sample.portal.jar-X.Y.Z.jar</emphasis>
+ which is the file in which we have internal classes that are
+ actualy a set of sample classes <emphasis>(SampleFilter,
+ SampleContextInitializedListener,
+ SampleContextDestroyedListener,
+ SampleHttpSessionCreatedListener and
+ SampleHttpSessionDestroyedListener)</emphasis></para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>Add the file <emphasis>starter.ear</emphasis> from
+ starter/ear/target/ to the deploy directory of JBoss, this file
+ contains:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>The file <emphasis>starter.war</emphasis> which is the
+ web application that will create and start all the portal
+ containers, that is why it must be launched after all the
+ other web applications.</para>
+ </listitem>
+ </itemizedlist>
+ </listitem>
+
+ <listitem>
+ <para>Define the related application policy in your file
+ <emphasis>conf/login-config.xml</emphasis>, as below:</para>
+ </listitem>
+ </itemizedlist>
+
+ <programlisting> <application-policy name="exo-domain-sample-portal">
+ <authentication>
+ <login-module code="org.exoplatform.web.security.PortalLoginModule" flag="required">
+ <module-option name="portalContainerName">sample-portal</module-option>
+ <module-option name="realmName">exo-domain-sample-portal</module-option>
+ </login-module>
+ <login-module code="org.exoplatform.services.security.jaas.SharedStateLoginModule" flag="required">
+ <module-option name="portalContainerName">sample-portal</module-option>
+ <module-option name="realmName">exo-domain-sample-portal</module-option>
+ </login-module>
+ <login-module code="org.exoplatform.services.security.j2ee.JbossLoginModule" flag="required">
+ <module-option name="portalContainerName">sample-portal</module-option>
+ <module-option name="realmName">exo-domain-sample-portal</module-option>
+ </login-module>
+ </authentication>
+ </application-policy>
+
+</programlisting>
+
+ <warning>
+ <title>Warning #1</title>
+
+ <para>This can only work if a Unified ClassLoader has been
+ configured on your JBoss (default behavior) and the load order is
+ first the <emphasis>exoplatform.ear</emphasis> then the
+ <emphasis>sample-portal.ear</emphasis> and finally the
+ <emphasis>starter.ear</emphasis>.</para>
+ </warning>
+
+ <warning>
+ <title>Warning #2</title>
+
+ <para>The file <emphasis>starter.ear</emphasis> must always been
+ started last.</para>
+ </warning>
+ </section>
+
+ <section id="OnTomcattestedonTomcat6.0.203">
+ <title>On Tomcat (tested on Tomcat 6.0.20)</title>
+
+ <para>We assume that you have a clean Tomcat version of GateIn, in
+ other words, we assume that you have already all the jar files of
+ GateIn and their dependencies into <emphasis>tomcat/lib</emphasis>,
+ you have all the war files of GateIn into
+ <emphasis>tomcat/webapps</emphasis> and you have the realm name
+ "exo-domain" defined into the file
+ <emphasis>tomcat/conf/jaas.conf</emphasis>.</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Add the file <emphasis>sample-portal.war</emphasis> from
+ sample/portal/war/target/ to the
+ <emphasis>tomcat/webapps</emphasis> directory. <emphasis>(See the
+ purpose of this file in the JBoss section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the file <emphasis>rest-sample-portal.war</emphasis>
+ from sample/portal/rest-war/target/ to the
+ <emphasis>tomcat/webapps</emphasis> directory. <emphasis>(See the
+ purpose of this file in the JBoss section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the folder <emphasis>starter</emphasis> from
+ starter/war/target/ to the <emphasis>tomcat/webapps</emphasis>
+ directory. <emphasis>(See the purpose of this file in the JBoss
+ section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the directory (unzipped folder)
+ <emphasis>starter</emphasis> to <emphasis>starter.war</emphasis>
+ <emphasis>(for more details see the warning
+ below)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the jar file
+ <emphasis>exo.portal.sample.portal.config-X.Y.Z.jar</emphasis>
+ from sample/portal/config/target/ to the
+ <emphasis>tomcat/lib</emphasis> directory. <emphasis>(See the
+ purpose of this file in the JBoss section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Add the jar file
+ <emphasis>exo.portal.sample.portal.jar-X.Y.Z.jar</emphasis> from
+ sample/portal/jar/target/ to the <emphasis>tomcat/lib</emphasis>
+ directory. <emphasis>(See the purpose of this file in the JBoss
+ section)</emphasis>.</para>
+ </listitem>
+
+ <listitem>
+ <para>Define the related realm in your file
+ <emphasis>tomcat/conf/jaas.conf</emphasis>, as below:</para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <title>tomcat/conf/jaas.conf</title>
+
+ <programlisting>...
+exo-domain-sample-portal {
+ org.exoplatform.web.security.PortalLoginModule required
+ portalContainerName="sample-portal"
+ realmName="exo-domain-sample-portal";
+ org.exoplatform.services.security.jaas.SharedStateLoginModule required
+ portalContainerName="sample-portal"
+ realmName="exo-domain-sample-portal";
+ org.exoplatform.services.security.j2ee.TomcatLoginModule required
+ portalContainerName="sample-portal"
+ realmName="exo-domain-sample-portal";
+};
+
+</programlisting>
+ </note>
+
+ <itemizedlist>
+ <listitem>
+ <para>Define the context of <emphasis>sample-portal</emphasis> by
+ creating a file called <emphasis>sample-portal.xml</emphasis> into
+ <emphasis>tomcat/conf/Catalina/localhost/</emphasis> with the
+ following content:</para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <title>tomcat/conf/Catalina/localhost/sample-portal.xml</title>
+
+ <programlisting><Context path='/sample-portal' docBase='sample-portal' debug='0' reloadable='true' crossContext='true' privileged='true'>
+ <Logger className='org.apache.catalina.logger.SystemOutLogger'
+ prefix='localhost_portal_log.' suffix='.txt' timestamp='true'/>
+ <Manager className='org.apache.catalina.session.PersistentManager' saveOnRestart='false'/>
+ <Realm className='org.apache.catalina.realm.JAASRealm'
+ appName='exo-domain-sample-portal'
+ userClassNames='org.exoplatform.services.security.jaas.UserPrincipal'
+ roleClassNames='org.exoplatform.services.security.jaas.RolePrincipal'
+ debug='0' cache='false'/>
+ <Valve className='org.apache.catalina.authenticator.FormAuthenticator' characterEncoding='UTF-8'/></Context>
+
+</programlisting>
+ </note>
+
+ <itemizedlist>
+ <listitem>
+ <para>Define the context of
+ <emphasis>rest-sample-portal</emphasis> by creating a file called
+ <emphasis>rest-sample-portal.xml</emphasis> into
+ <emphasis>tomcat/conf/Catalina/localhost/</emphasis> with the
+ following content:</para>
+ </listitem>
+ </itemizedlist>
+
+ <note>
+ <title>tomcat/conf/Catalina/localhost/rest-sample-portal.xml</title>
+
+ <programlisting><Context path="/rest-sample-portal" docBase="rest-sample-portal" reloadable="true" crossContext="false">
+
+ <Logger className='org.apache.catalina.logger.SystemOutLogger'
+ prefix='localhost_portal_log.' suffix='.txt' timestamp='true'/>
+ <Manager className='org.apache.catalina.session.PersistentManager' saveOnRestart='false'/>
+ <Realm className='org.apache.catalina.realm.JAASRealm'
+ appName='exo-domain-sample-portal'
+ userClassNames="org.exoplatform.services.security.jaas.UserPrincipal"
+ roleClassNames="org.exoplatform.services.security.jaas.RolePrincipal"
+ debug='0' cache='false'/>
+</Context>
+
+
+</programlisting>
+ </note>
+
+ <warning>
+ <title>Warning</title>
+
+ <para>This can only work if the <emphasis>starter.war</emphasis> is
+ the last war file to be loaded, so don't hesitate to rename it if
+ your war files are loaded following to the alphabetic order.</para>
+ </warning>
+ </section>
+ </section>
+
+ <section id="Igetjava.lang.IllegalStateExceptionNopreinittaskscanbeaddedtotheportalcontainerportalbecauseithasalreadybeeninitialized.whatcanIdotofixit">
+ <title>I get "java.lang.IllegalStateException: No pre init tasks can be
+ added to the portal container 'portal', because it has already been
+ initialized." what can I do to fix it?</title>
+
+ <para>To fix this issue you need to check if:</para>
+
+ <orderedlist>
+ <listitem>
+ <para>The file <emphasis>starter-gatein.ear</emphasis> (which will
+ be <emphasis>starter.war</emphasis> for Tomcat) has been
+ deployed</para>
+ </listitem>
+
+ <listitem>
+ <para>The file <emphasis>starter-gatein.ear</emphasis> (which will
+ be <emphasis>starter.war</emphasis> for Tomcat) is the last ear file
+ to be launched</para>
+ </listitem>
+ </orderedlist>
+
+ <note>
+ <title>Note</title>
+
+ <para>With Tomcat to prevent any alphabetic issue, the good way to
+ solve this problem is to:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>Unzip the archive <emphasis>starter.war</emphasis> into a
+ directory called <emphasis>starter</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>Remove the archive <emphasis>starter.war</emphasis></para>
+ </listitem>
+
+ <listitem>
+ <para>Rename the folder <emphasis>starter</emphasis> to
+ <emphasis>starter.war</emphasis></para>
+ </listitem>
+ </itemizedlist>
+
+ <para>This tip works because folders corresponding to unzipped wars
+ are launched after war files.</para>
+ </note>
+ </section>
+
+ <section id="WhathasbeendonetoallowGateInextensions">
+ <title>What has been done to allow GateIn extensions?</title>
+
+ <para>Refer to the dedicated wiki article <ulink
+ url="What has been done to allow GateIn extensions?">What has been done
+ to allow GateIn extensions?</ulink></para>
+ </section>
+ </chapter>
+
+ <chapter id="Recommendations">
+ <title>Recommendations</title>
+
+ <section id="Dontshipyourconfigurationfileswithyourjarfiles">
+ <title>Don't ship your configuration files with your jar files?</title>
+
+ <para>Remove all the configuration files from the jar files (
+ <emphasis>conf/configuration.xml</emphasis> and
+ <emphasis>conf/portal/configuration.xml</emphasis>) and move them to the
+ war file of your extension, otherwise your configuration files will be
+ loaded for all the portal containers which could cause incompatibility
+ issues with other portals.</para>
+
+ <para>Each extension should manage independently, its css files, js
+ files, google gadgets and configuration files. If you add configuration
+ files into the jar files of your extension, you brake this law.</para>
+ </section>
+
+ <section id="Useadedicatedworkspacerepositoryforyourextension">
+ <title>Use a dedicated workspace/repository for your extension?</title>
+
+ <para>In order to avoid conflicts with other extensions and to manage
+ each extension independently, it is highly recommended to use a
+ dedicated workspace or repository per extension.</para>
+ </section>
+ </chapter>
+</part>
More information about the exo-jcr-commits
mailing list