Author: sergiykarpenko
Date: 2010-08-23 08:17:50 -0400 (Mon, 23 Aug 2010)
New Revision: 2970
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gatein.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/how-to-extend-my-gatein-instance.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/managed-datasources-under-jboss-as.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/resources/images/perf_EC2_results.jpg
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/resources/images/perf_EC2_results_2.jpg
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/master.xml
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr.xml
Log:
EXOJCR-905: userguide chapters merged into reference
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/master.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/master.xml 2010-08-23
12:02:15 UTC (rev 2969)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/master.xml 2010-08-23
12:17:50 UTC (rev 2970)
@@ -66,9 +66,14 @@
xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="modules/ws.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
-
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
<xi:include href="modules/faq.xml"
-
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="modules/jcr-with-gatein.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+
+
</book>
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml
(rev 0)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr/performance-tuning-guide.xml 2010-08-23
12:17:50 UTC (rev 2970)
@@ -0,0 +1,323 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<chapter id="JCR.PerformanceTuningGuide">
+ <?dbhtml filename="ch-jcr-performance-tuning.html"?>
+
+ <title>JCR Performance Tuning Guide</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <para>This guide will show you possible ways of improving JCR
+ performance.</para>
+
+ <para>It is intended to GateIn Administrators and those who wants to use
+ JCR features.</para>
+ </section>
+
+ <section>
+ <title>JCR Performance and Scalability</title>
+
+ <section>
+ <title>Cluster configuration</title>
+
+ <para><citetitle>EC2 network</citetitle>: 1Gbit</para>
+
+ <para><citetitle>Servers hardware</citetitle>:<simplelist>
+ <member>7.5 GB memory</member>
+
+ <member>4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute
+ Units each)</member>
+
+ <member>850 GB instance storage (2×420 GB plus 10 GB root
+ partition)</member>
+
+ <member>64-bit platform</member>
+
+ <member>I/O Performance: High</member>
+
+ <member>API name: m1.large</member>
+ </simplelist></para>
+
+ <note>
+ <para>NFS and statistics (cacti snmp) server were located on one
+ physical server.</para>
+ </note>
+
+ <para><citetitle>JBoss AS configuration</citetitle></para>
+
+ <para><code>JAVA_OPTS: -Dprogram.name=run.sh -server -Xms4g -Xmx4g
+ -XX:MaxPermSize=512m -Dorg.jboss.resolver.warning=true
+ -Dsun.rmi.dgc.client.gcInterval=3600000
+ -Dsun.rmi.dgc.server.gcInterval=3600000 -XX:+UseParallelGC
+ -Djava.net.preferIPv4Stack=true</code></para>
+ </section>
+
+ <section>
+ <title>JCR Clustered Performance</title>
+
+ <para>Benchmark test using webdav (Complex read/write load test
+ (benchmark)) with 20K same file. To obtain per-operation results we have
+ used custom output from the testscase threads to CSV file.</para>
+
+ <para><citetitle>Read operation</citetitle>:<simplelist>
+ <member>Warm-up iterations: 100</member>
+
+ <member>Run iterations: 2000</member>
+
+ <member>Background writing threads: 25</member>
+
+ <member>Reading threads: 225</member>
+ </simplelist></para>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/perf_EC2_results.jpg" />
+ </imageobject>
+ </mediaobject>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Nodes count</entry>
+
+ <entry>tps</entry>
+
+ <entry> Responses >2s</entry>
+
+ <entry>Responses >4s</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>1</entry>
+
+ <entry>523</entry>
+
+ <entry>6.87%</entry>
+
+ <entry>1.27% </entry>
+ </row>
+
+ <row>
+ <entry>2</entry>
+
+ <entry>1754</entry>
+
+ <entry>0.64% </entry>
+
+ <entry>0.08% </entry>
+ </row>
+
+ <row>
+ <entry>3</entry>
+
+ <entry>2388</entry>
+
+ <entry>0.49% </entry>
+
+ <entry>0.09% </entry>
+ </row>
+
+ <row>
+ <entry>4</entry>
+
+ <entry>2706</entry>
+
+ <entry>0.46% </entry>
+
+ <entry> 0.1% </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
+ <para><citetitle>Read operaion with more
threads</citetitle>:</para>
+
+ <simplelist>
+ <member>Warm-up iterations: 100</member>
+
+ <member>Run iterations: 2000</member>
+
+ <member>Background writing threads: 50</member>
+
+ <member>Reading threads: 450</member>
+ </simplelist>
+
+ <mediaobject>
+ <imageobject>
+ <imagedata fileref="images/perf_EC2_results_2.jpg" />
+ </imageobject>
+ </mediaobject>
+
+ <table>
+ <title></title>
+
+ <tgroup cols="4">
+ <thead>
+ <row>
+ <entry>Nodes count</entry>
+
+ <entry>tps</entry>
+
+ <entry>Responses >2s</entry>
+
+ <entry>Responses >4s</entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry>1</entry>
+
+ <entry>116</entry>
+
+ <entry>?</entry>
+
+ <entry>?</entry>
+ </row>
+
+ <row>
+ <entry>2</entry>
+
+ <entry>1558</entry>
+
+ <entry>6.1%</entry>
+
+ <entry>0.6%</entry>
+ </row>
+
+ <row>
+ <entry>3</entry>
+
+ <entry>2242</entry>
+
+ <entry>3.1%</entry>
+
+ <entry>0.38%</entry>
+ </row>
+
+ <row>
+ <entry>4</entry>
+
+ <entry>2756 </entry>
+
+ <entry>2.2%</entry>
+
+ <entry>0.41%</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </section>
+ </section>
+
+ <section>
+ <title>Performance Tuning Guide</title>
+
+ <section>
+ <title>JBoss AS Tuning</title>
+
+ <para>You can use <parameter>maxThreads</parameter> parameter to
+ increase maximum amount of threads that can be launched in AS instance.
+ This can improve performance if you need a high level of concurrency.
+ also you can use <code>-XX:+UseParallelGC</code> java directory to use
+ paralel garbage collector.</para>
+
+ <tip>
+ <para>Beware of setting <parameter>maxThreads</parameter> too
big,
+ this can cause <exceptionname>OutOfMemoryError</exceptionname>.
We've
+ got it with <code>maxThreads=1250</code> on such
machine:</para>
+
+ <simplelist>
+ <member>7.5 GB memory</member>
+
+ <member>4 EC2 Compute Units (2 virtual cores with 2 EC2 Compute
+ Units each)</member>
+
+ <member>850 GB instance storage (2×420 GB plus 10 GB root
+ partition)</member>
+
+ <member>64-bit platform</member>
+
+ <member>I/O Performance: High</member>
+
+ <member>API name: m1.large</member>
+
+ <member>java -Xmx 4g</member>
+ </simplelist>
+ </tip>
+ </section>
+
+ <section>
+ <title>JCR Cache Tuning</title>
+
+ <para><citetitle>Cache size</citetitle></para>
+
+ <para>JCR-cluster implementation is built using JBoss Cache as
+ distributed, replicated cache. But there is one particularity related to
+ remove action in it. Speed of this operation depends on the actual size
+ of cache. As many nodes are currently in cache as much time is needed to
+ remove one particular node (subtree) from it.</para>
+
+ <para><citetitle>Eviction</citetitle></para>
+
+ <para>Manipulations with eviction
<parameter>wakeUpInterval</parameter>
+ value doestn't affect on performance. Performance results with values
+ from 500 up to 3000 are approximately equal.</para>
+
+ <para><citetitle>Transaction Timeout</citetitle></para>
+
+ <para>Using short timeout for long transactions such as Export/Import,
+ removing huge subtree defined timeout may cause
+ <exceptionname>TransactionTimeoutException</exceptionname>. [TODO] put
+ recomended timeout value</para>
+ </section>
+
+ <section>
+ <title>Clustering</title>
+
+ <para>For performance it is better to have loadbalacer, DB server and
+ shared NFS on different computers. If in some reasons you see that one
+ node gets more load than others you can decrease this load using load
+ value in load balancer.</para>
+
+ <para><citetitle>JGroups configuration</citetitle></para>
+
+ <para>It's recommended to use "multiplexer stack" feature
present in
+ JGroups. It is set by default in eXo JCR and offers higher performance
+ in cluster, using less network connections also. If there are two or
+ more clusters in your network, please check that they use different
+ ports and different cluster names.</para>
+
+ <para><citetitle>Write performance in
cluster</citetitle></para>
+
+ <para>Exo JCR implementation uses Lucene indexing engine to provide
+ search capabilities. But Lucene brings some limitations for write
+ operations: it can perform indexing only in one thread. Thats why write
+ performance in cluster is not higher than in singleton environment. Data
+ is indexed on coordinator node, so increasing write-load on cluster may
+ lead to ReplicationTimeout exception. It occurs because writing threads
+ queue in the indexer and under high load timeout for replication to
+ coordinator will be exceeded.</para>
+
+ <para>Taking in consideration this fact, it is recommended to exceed
+ <parameter>replTimeout</parameter> value in cache configurations in
case
+ of high write-load.</para>
+
+ <para><citetitle>Replication timeout</citetitle></para>
+
+ <para>Some operations may take too much time. So if you get
+ <exceptionname>ReplicationTimeoutException</exceptionname> try
+ increasing replication timeout:<programlisting> <clustering
mode="replication" clusterName="${jbosscache-cluster-name}">
+ ...
+ <sync replTimeout="60000" />
+ </clustering></programlisting>value is set in
miliseconds.</para>
+ </section>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gatein.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gatein.xml
(rev 0)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gatein.xml 2010-08-23
12:17:50 UTC (rev 2970)
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<part>
+ <?dbhtml filename="part-jcr-with-gatein.html"?>
+
+ <title>eXo JCR with GateIn</title>
+
+ <xi:include href="jcr-with-gtn/how-to-extend-my-gatein-instance.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+
+ <xi:include href="jcr-with-gtn/managed-datasources-under-jboss-as.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
+</part>
+
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/how-to-extend-my-gatein-instance.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/how-to-extend-my-gatein-instance.xml
(rev 0)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/how-to-extend-my-gatein-instance.xml 2010-08-23
12:17:50 UTC (rev 2970)
@@ -0,0 +1,2460 @@
+<?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">
+<chapter id="JCRWithGateIn.HowToExtendMyGateInInstance">
+ <?dbhtml filename="ch-how-to-extend-my-gatein-instance.html"?>
+
+ <title>How to extend my GateIn instance?</title>
+
+ <section>
+ <title>Introduction</title>
+
+ <section>
+ <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>
+ <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>
+ </section>
+
+ <section>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ </section>
+
+ <section>
+ <title>FAQ</title>
+
+ <section>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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 article <link
linkend="Kernel.ContainerConfiguration">Container
+ Configuration</link>).</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>
+ <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>
+ <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 article <link
linkend="Kernel.ContainerConfiguration">Container
+ Configuration</link>).</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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <title>How to deploy a portal extension?</title>
+
+ <para>Refer to <emphasis>How to deploy the sample
+ extension?</emphasis></para>
+ </section>
+
+ <section>
+ <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>
+ <title>How to deploy a new portal?</title>
+
+ <para>Refer to <emphasis>How to deploy the sample
+ portal?</emphasis></para>
+ </section>
+
+ <section>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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>
+ <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
+ article <link linkend="WS">WS</link>.</para>
+ </section>
+
+ <section>
+ <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>
+ <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>
+ <title>How to deploy the sample extension?</title>
+
+ <section>
+ <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>
+ <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>
+ <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>
+ <title>How to deploy the sample portal?</title>
+
+ <section>
+ <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>
+ <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>
+ <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>
+
+ <section>
+ <title>Recommendations</title>
+
+ <section>
+ <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>
+ <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>
+ </section>
+</chapter>
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/managed-datasources-under-jboss-as.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/managed-datasources-under-jboss-as.xml
(rev 0)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr-with-gtn/managed-datasources-under-jboss-as.xml 2010-08-23
12:17:50 UTC (rev 2970)
@@ -0,0 +1,102 @@
+<?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">
+<chapter id="JCRWithGateIn.HowToUseDataSourceUnderJBoss">
+ <title>How to use AS Managed DataSource under JBoss AS</title>
+
+ <?dbhtml
filename="ch-how-to-use-managed-datasource-under-jboss.html"?>
+
+ <section>
+ <title>Configurations Steps</title>
+
+ <important>
+ <para>Checked under Gatein 3.1.0-GA Final</para>
+ </important>
+
+ <important>
+ <para>only no-tx-datasource is supported in JCR 1.12</para>
+ </important>
+
+ <section>
+ <title>Declaring the datasources in the AS</title>
+
+ <para>Under JBoss, just put a file XXX-ds.xml in the deploy server
+ (example: \server\default\deploy). In this file we will configure all
+ datasources which eXo will need. (there should be 4 named:
+ jdbcjcr_portal, jdbcjcr_portal-sample, jdbcidm_portal &
+ jdbcidm_sample-portal).</para>
+
+ <para>Example:<programlisting><?xml version="1.0"
encoding="UTF-8"?>
+<datasources>
+ <no-tx-datasource>
+ <jndi-name>jdbcjcr_portal</jndi-name>
+
<connection-url>jdbc:hsqldb:${jboss.server.data.dir}/data/jdbcjcr_portal</connection-url>
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ </no-tx-datasource>
+
+ <no-tx-datasource>
+ <jndi-name>jdbcjcr_sample-portal</jndi-name>
+
<connection-url>jdbc:hsqldb:${jboss.server.data.dir}/data/jdbcjcr_sample-portal</connection-url>
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ </no-tx-datasource>
+
+ <no-tx-datasource>
+ <jndi-name>jdbcidm_portal</jndi-name>
+
<connection-url>jdbc:hsqldb:${jboss.server.data.dir}/data/jdbcidm_portal</connection-url>
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ </no-tx-datasource>
+
+ <no-tx-datasource>
+ <jndi-name>jdbcidm_sample-portal</jndi-name>
+
<connection-url>jdbc:hsqldb:${jboss.server.data.dir}/data/jdbcidm_sample-portal</connection-url>
+ <driver-class>org.hsqldb.jdbcDriver</driver-class>
+ <user-name>sa</user-name>
+ <password></password>
+ </no-tx-datasource>
+</datasources></programlisting></para>
+
+ <para>Which properties can be set for datasource can be found here:
+ <ulink
+
url="http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4...
+ JDBC DataSources - The non transactional DataSource configuration
+ schema</ulink></para>
+ </section>
+
+ <section>
+ <title>Do not let eXo bind datasources explicitly</title>
+
+ <para>Edit server/default/conf/gatein/configuration.properties and
+ comment out next rows in JCR section:</para>
+
+ <programlisting>#gatein.jcr.datasource.driver=org.hsqldb.jdbcDriver
+#gatein.jcr.datasource.url=jdbc:hsqldb:file:${gatein.db.data.dir}/data/jdbcjcr_${name}
+#gatein.jcr.datasource.username=sa
+#gatein.jcr.datasource.password=</programlisting>
+
+ <para>and in IDM section:</para>
+
+ <programlisting>#gatein.idm.datasource.driver=org.hsqldb.jdbcDriver
+#gatein.idm.datasource.url=jdbc:hsqldb:file:${gatein.db.data.dir}/data/jdbcidm_${name}
+#gatein.idm.datasource.username=sa
+#gatein.idm.datasource.password=</programlisting>
+
+ <para>In jcr-configuration.xml and idm-configuration.xml comment out the
+ plugin InitialContextInitializer.</para>
+
+ <programlisting><!-- Commented because, Datasources are declared and
bound by AS, not in eXo -->
+<!--
+<external-component-plugins>
+ [...]
+</external-component-plugins>
+--></programlisting>
+
+ <para>Running eXo after these configurations goes well.</para>
+ </section>
+ </section>
+</chapter>
Modified:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr.xml
===================================================================
---
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr.xml 2010-08-23
12:02:15 UTC (rev 2969)
+++
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/docbook/en-US/modules/jcr.xml 2010-08-23
12:17:50 UTC (rev 2970)
@@ -148,4 +148,7 @@
<xi:include href="jcr/data-container-howto.xml"
xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <!-- tuning guide -->
+ <xi:include href="jcr/performance-tuning-guide.xml"
+
xmlns:xi="http://www.w3.org/2001/XInclude" />
</part>
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/resources/images/perf_EC2_results.jpg
===================================================================
(Binary files differ)
Property changes on:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/resources/images/perf_EC2_results.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/resources/images/perf_EC2_results_2.jpg
===================================================================
(Binary files differ)
Property changes on:
jcr/branches/1.12.x/exo.jcr.docs/exo.jcr.docs.developer/reference/en/src/main/resources/images/perf_EC2_results_2.jpg
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream