Appendix A. The eXo Kernel
A.1. The eXo Kernel
public ServiceA(ServiceB serviceB)
public void setServiceB(ServiceB serviceB)
public ServiceA(){ this.serviceB =Container.getSInstance().getService(ServiceB.class); }
PortalContainer.. If the service cannot be found, then the class loader looks in the parent container. This means the reusable business logic components can be loaded in the same container (here the RootContainer) and differentiates the service implementation from one portal instance to the other by loading different service implementations in two sibling PortalContainers.
configuration.xml files: one for each container type. This file defines the list of services and their init parameters that are loaded in the corresponding container.
RootContainer, which is a base container and contains services that exist independently of any portal. TheRootContainercan be accessed by all portals. This container plays an important role during startup, but must not be used directly.PortalContainer, in which each portal exists. This scope contains services that are common for a set of portals, and services which must remain unique to each portal instance. This service component is created when a portal web application (in the init() method of the PortalController servlet) starts.
portal.war.
PortalContainer, and the service is not available, the lookup is delegated further up to the RootContainer.
RootContainer, and portal specific instances in some or all PortalContainers, that override the default instance.
PortalContainer.
Important
A.2. Kernel Configuration Namespace
http://www.exoplatform.org/xml/ns/kernel_1_2.xsd must be the target namespace of the XML configuration file.
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> ... </configuration>
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplatform.org/xml/ns/kernel_1_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <import>${db.configuration.path}/db.xml</import> <import>${java.io.tmpdir}/bindfile.xml</import> <import>simple.xml</import> </configuration>
A.3. Configuration Retrieval
- Services default
RootContainerconfigurations from JAR files/conf/configuration.xml. - Services default
PortalContainerconfigurations from JAR files/conf/portal/configuration.xml. - Web applications configurations from WAR files
/WEB-INF/conf/configuration.xml - Configuration URL for
PortalContainer, based on the following caveats:- If the configuration URL was initialized to be added to services defaults using
PortalContainer.addConfigurationURL(containerConf);the configuration from the containerConf overrides services configured in the file only. - The
$JPP_HOME/gatein/gatein.ear/portal.war/WEB-INF/conf/configuration.xmlis the only path that states the correct location for the configuration.
Warning
/conf/portal/configuration.xml and /conf/configuration.xml are loaded because there is no way of determining the JAR loading order prior to start.
/conf/portal/configuration.xml in the portal itself).
Important
org.exoplatform.container.configuration.debug can be used to identify this information.
java -Dorg.exoplatform.container.configuration.debug ...
getConfigurationXML() method that is exposed through JMX at the container level. This method exposes the effective configuration, in XML format, that the kernel interpreted. This information could be helpful when analyzing how a given component or plug-in has been initialized.
A.4. PortalContainer Advanced Concepts
A.4.1. Add new configuration files from a WAR file
ServletContextListener called org.exoplatform.container.web.PortalContainerConfigOwner notifies the application that a web application provides some configuration to the portal container, and this configuration file is the file WEB-INF/conf/configuration.xml available in the web application itself.
PortalContainer add the following lines to the web.xml file.
<?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> ... <!-- ================================================================== --> <!-- LISTENER --> <!-- ================================================================== --> <listener> <listener-class>org.exoplatform.container.web.PortalContainerConfigOwner</listener-class> </listener> ... </web-app>
A.4.2. Creating PortalContainers from a WAR File
Important
starter.war/ear.
org.exoplatform.container.web.PortalContainerCreator creates the current portal containers that have been registered. It is assumed that the web applications have already been loaded before calling PortalContainerCreator.contextInitialized.
A.4.3. Defining a PortalContainer with its dependencies and its settings
PortalContainerDefinition contains the name of the portal container, the name of the rest context, the name of the realm, the web application dependencies ordered by loading priority, and the settings.
Example A.1. Defining a PortalContainerDefinition
PortalContainerConfig at the RootContainer level to define a PortalContainerDefinition.
<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> <!-- Indicates whether the unregistered webapps have to be ignored --> <value-param> <name>ignore.unregistered.webapp</name> <value>true</value> </value-param> <!-- The default portal container definition --> <!-- It cans be used to avoid duplicating configuration --> <object-param> <name>default.portal.definition</name> <object type="org.exoplatform.container.definition.PortalContainerDefinition"> <!-- All the dependencies of the portal container ordered by loading priority --> <field name="dependencies"> <collection type="java.util.ArrayList"> <value> <string>foo</string> </value> <value> <string>foo2</string> </value> <value> <string>foo3</string> </value> </collection> </field> <!-- A map of settings tied to the default portal container --> <field name="settings"> <map type="java.util.HashMap"> <entry> <key> <string>foo5</string> </key> <value> <string>value</string> </value> </entry> <entry> <key> <string>string</string> </key> <value> <string>value0</string> </value> </entry> <entry> <key> <string>int</string> </key> <value> <int>100</int> </value> </entry> </map> </field> <!-- The path to the external properties file --> <field name="externalSettingsPath"> <string>classpath:/org/exoplatform/container/definition/default-settings.properties</string> </field> </object> </object-param> </init-params> </component>
PortalContainerConfig Parameters
Note
- default.portal.container (*)
- The name of the default portal container. This field is optional.
- default.rest.context (*)
- The name of the default rest
ServletContext. This field is optional. - default.realm.name (*)
- The name of the default realm. This field is optional.
- ignore.unregistered.webapp (*)
- Indicates whether the unregistered webapps have to be ignored.This field is optional and is set to false by default.If a webapp has not been registered as a dependency of any portal container, the application will use the value of this parameter to determine how to classify the webapp:
- If set to false, the webapp will be considered by default as a dependency of all the portal containers.
- If set to true, the webapp will not be considered by default as a dependency of any portal container, and is ignored.
- default.portal.definition
- The definition of the default portal container. This field is optional. The expected type is
org.exoplatform.container.definition.PortalContainerDefinitionthat is described below. Allow the parameters defined in this defaultPortalContainerDefinitionwill be the default values.
Example A.2. Defining a PortalContainerDefinition at the RootContainer Level Using a Plug-in
PortalContainerDefinition can be defined at the RootContainer level using an external plug-in:
<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>myPortal</string> </field> <!-- The name of the context name of the rest web application --> <field name="restContextName"> <string>myRest</string> </field> <!-- The name of the realm --> <field name="realmName"> <string>my-domain</string> </field> <!-- All the dependencies of the portal container ordered by loading priority --> <field name="dependencies"> <collection type="java.util.ArrayList"> <value> <string>foo</string> </value> <value> <string>foo2</string> </value> <value> <string>foo3</string> </value> </collection> </field> <!-- A map of settings tied to the portal container --> <field name="settings"> <map type="java.util.HashMap"> <entry> <key> <string>foo</string> </key> <value> <string>value</string> </value> </entry> <entry> <key> <string>int</string> </key> <value> <int>10</int> </value> </entry> <entry> <key> <string>long</string> </key> <value> <long>10</long> </value> </entry> <entry> <key> <string>double</string> </key> <value> <double>10</double> </value> </entry> <entry> <key> <string>boolean</string> </key> <value> <boolean>true</boolean> </value> </entry> </map> </field> <!-- The path to the external properties file --> <field name="externalSettingsPath"> <string>classpath:/org/exoplatform/container/definition/settings.properties</string> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
PortalContainerDefinition Parameter Values
- name (*)
- The name of the portal container. This field is mandatory .
- restContextName (*)
- The name of the context name of the rest web application. This field is optional. The default value will be defined at the
PortalContainerConfiglevel. - realmName (*)
- The name of the realm. This field is optional. The default value will be defined at the
PortalContainerConfiglevel. - dependencies
- All the dependencies of the portal container ordered by loading priority. This field is optional. The default value will be defined at the
PortalContainerConfiglevel.The dependencies are in fact the list of the context names of the web applications from which the portal container depends on. The dependency order is crucial because it will be interpreted the same way by several components of the platform. All components will consider the first element in the list less important than the second element and so on.Dependency order is used to define the following:- Know the loading order of all the dependencies.
- If several
PortalContainerConfigOwnerdependencies exist, the unifiedServletContext(PortalContainer.getPortalContext()) is called to get a resource. It will attempt to get the resource in theServletContextof the most importantPortalContainerConfigOwner(the last in the dependency list). If it is able to find the resource, it will try again with the second most importantPortalContainerConfigOwnerand so on.
- settings
- A
java.util.Mapof internal parameters to apply to the portal container. Parameters could have any type of value. This field is optional. If some internal settings are defined at thePortalContainerConfiglevel, the two settings maps are merged. If a setting with the same name is defined in both maps, it will keep the value defined at thePortalContainerDefinitionlevel. - externalSettingsPath
- The path of the external properties file to load as default settings to the portal container. This field is optional. If some external settings are defined at the
PortalContainerConfiglevel, the two settings maps are merged. If a setting with the same name is defined in both maps, it will keep the value defined at thePortalContainerDefinitionlevel. The external properties files can be either of type "properties" or of type "xml". The path will be interpreted as follows:- If the path doesn't contain any prefix of type "classpath:", "jar:" or "file:", it is assumed the file could be externalized. The following rules are applied:
- If a file exists at ${exo-conf-dir}/portal/${portalContainerName}/${externalSettingsPath} this file is loaded.
- If no file exists, it is assumed that the path can be interpreted by the
ConfigurationManager.
- If the path contains a prefix, it is assumed that the path can be interpreted by the
ConfigurationManager.
PortalContianerDefinition Parameter Descriptions When Used for The Default Portal Container
Note
- name (*)
- The name of the portal container. This field is optional. The default portal name is determined by the following logic:
- If this field is not empty, the default value is the value of this field.
- If this field is empty and the value of the parameter default.portal.container is not empty, the default value will be the value of the parameter.
- If this field and the parameter default.portal.container are both empty, the default value is "portal".
- restContextName (*)
- The name of the context name of the rest web application. This field is optional. The default value is determined by the following logic:
- If this field is not empty, then the default value will be the value of this field.
- If this field is empty and the value of the parameter default.rest.context is not empty, then the default value will be the value of the parameter.
- If this field and the parameter default.rest.context are both empty, the default value will be "rest".
- realmName (*)
- The name of the realm. This field is optional. The default value is determined by the following logic:
- If this field is not empty, then the default value is the value of this field.
- If this field is empty and the value of the parameter default.realm.name is not empty, then the default value is the value of the parameter.
- If this field and the parameter default.realm.name are both empty, the default value is "exo-domain".
- dependencies
- All dependencies of the portal container ordered by loading priority. This field is optional. If this field has a non empty value, it is interpreted as the default list of dependencies.
- settings
- A
java.util.Mapof internal parameters to associate with the default portal container. Parameters can be of any data type. This field is optional. - externalSettingsPath
- The path of the external properties file to load as default settings to the default portal container. This field is optional. The external properties files can be either of type "properties" or of type "xml". The path is interpreted as follows:
- If the path does not contain any prefix of type "classpath:", "jar:" or "file:", it is assumed that the file could be externalized. The following rule subset is applied:
- If a file exists at ${exo-conf-dir}/portal/${externalSettingsPath}, the file is loaded.
- If no file exists at the previous path, it is assumed that the path can be interpreted by the
ConfigurationManager.
- If the path contains a prefix, it is assumed that the path can be interpreted by the
ConfigurationManager.
- If the value of the external setting is null, the value is ignored.
- If the value of the external setting is not null, and the value of the internal setting is null, the final value is the external setting value that is of type
String. - If both values are not
null, the external setting value is converted into the target type (the internal setting value) through the static method valueOf(String). The following rule subset is applied:- If the method cannot be found, the final value is the external setting value that is of type
String. - If the method can be found and the external setting value is an empty
String, the external setting value is ignored. - If the method can be found and the external setting value is not an empty
Stringbut the method call fails, the external setting value is ignored. - If the method can be found, the external setting value is not an empty
String, and the method call succeeds, the final value is the external setting value that is the same type as the internal setting value.
A.4.4. PortalContainer Settings
portal.container.* variable permits value injection into portal container configuration files. For example, to get the value of a setting called "name", use ${portal.container.name}. The following internal variables are also valid:
PortalContainer Internal Variables
- portal.container.name
- Gives the name of the current portal container.
- portal.container.rest
- Gives the context name of the rest web application of the current portal container.
- portal.container.realm
- Gives the realm name of the current portal container.
Example A.3. portal.container.* Usage Example
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <component> <type>org.exoplatform.container.TestPortalContainer$MyComponent</type> <init-params> <!-- The name of the portal container --> <value-param> <name>portal</name> <value>${portal.container.name}</value> </value-param> <!-- The name of the rest ServletContext --> <value-param> <name>rest</name> <value>${portal.container.rest}</value> </value-param> <!-- The name of the realm --> <value-param> <name>realm</name> <value>${portal.container.realm}</value> </value-param> <value-param> <name>foo</name> <value>${portal.container.foo}</value> </value-param> <value-param> <name>before foo after</name> <value>before ${portal.container.foo} after</value> </value-param> </init-params> </component> </configuration>
Example A.4. Create a New Variable from Existing Variables
portal.container. is not needed.
my-var1=value 1
my-var2=value 2
complex-value=${my-var1}-${my-var2}Example A.5. Settings Created Using System Parameters
PropertyConfigurator.
temp-dir=${java.io.tmpdir}${file.separator}my-tempNote
java.lang.String can only be used when generating new internal setting variables.
Example A.6. Specify a Dynamically-changing Variable
my-generic-var=value of the portal container "${name}""sales" is value of the portal container "sales".
A.4.5. Dynamically Changing a PortalContainerDefinition
component-plugin elements to dynamically change a PortalContainerDefinition.
Example A.7.
sales is added to the default portal container, and to the portal containers named shop1 and shop2:
<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>Change PortalContainer Definitions</name> <!-- The name of the method to call on the PortalContainerConfig in order to register the changes on the PortalContainerDefinitions --> <set-method>registerChangePlugin</set-method> <!-- The full qualified name of the PortalContainerDefinitionChangePlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionChangePlugin</type> <init-params> <value-param> <name>apply.default</name> <value>true</value> </value-param> <values-param> <name>apply.specific</name> <value>shop1</value> <value>shop2</value> </values-param> <object-param> <name>change</name> <object type="org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependencies"> <!-- The list of name of the dependencies to add --> <field name="dependencies"> <collection type="java.util.ArrayList"> <value> <string>foo</string> </value> </collection> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
PortalContainerDefinitionChangePlugin Parameters
Note
configuration.properties by default.
- apply.all (*)
- Indicates whether the changes have to be applied to all the portal containers or not. The default value of this field is
false. This field is aValueParamand is not mandatory. - apply.default (*)
- Indicates whether the changes have to be applied to the default portal container or not. The default value of this field is
false. This field is aValueParamand is not mandatory. - apply.specific (*)
- A set of specific portal container names to apply the changes to. This field is a
ValuesParamand is not mandatory.
Other Expected Parameters
ObjectParam of type PortalContainerDefinitionChange. Those parameters are in fact the list of changes to apply to one or several portal containers. If the list of changes is empty, the component plug-in is ignored. The supported implementations of PortalContainerDefinitionChange are described later in this section.
- If the parameter
apply.allis set totruethe corresponding changes are applied to all the portal containers and other parameters will be ignored. - If the parameter
apply.defaultis set totrueand the parameterapply.specificisnull,the corresponding changes are applied to the default portal container only.Ifapply.specificis notnull, the corresponding changes are applied to the default portal container, and the list of specific portal containers. - If the parameter
apply.defaultis set tofalseor has not been set, and the parameterapply.specificisnull, the corresponding changes are applied to the default portal container only.Ifapply.specificis notnull, the corresponding changes are applied to the list of specific portal containers.
A.4.5.1. PortalContainerDefinitionChange Implementations
PortalContainerDefinition must be a class of type PortalContainerDefinitionChange. The product ships implementations described in the following sections.
A.4.5.1.1. AddDependencies
PortalContainerDefinition. The full qualified name is org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependencies.
AddDependencies Parameters
- dependencies
- A String list, corresponding to the list of dependency names to add. If the field is unpopulated, the change is ignored.
Example A.8. Appending a Dependency
foo at the end of the dependency list of the default portal container.
<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>Change PortalContainer Definitions</name> <!-- The name of the method to call on the PortalContainerConfig in order to register the changes on the PortalContainerDefinitions --> <set-method>registerChangePlugin</set-method> <!-- The full qualified name of the PortalContainerDefinitionChangePlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionChangePlugin</type> <init-params> <value-param> <name>apply.default</name> <value>true</value> </value-param> <object-param> <name>change</name> <object type="org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependencies"> <!-- The list of name of the dependencies to add --> <field name="dependencies"> <collection type="java.util.ArrayList"> <value> <string>foo</string> </value> </collection> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
A.4.5.1.2. AddDependenciesBefore
PortalContainerDefinition. The fullly qualified name is org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependenciesBefore.
AddDependenciesBefore Parameters
- dependencies
- A String list, corresponding to the list of dependency names to add. If the field is unpopulated, the change is ignored.
- target
- The name of the dependency that the new dependencies are added before. New dependencies are added in first position to the list if this field is
null, or the target dependency cannot be found in the list of dependencies defined into thePortalContainerDefinition.
Example A.9. Adding Multiple Dependencies
dependency1 before dependency2 in the dependency list of the default portal container.
<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>Change PortalContainer Definitions</name> <!-- The name of the method to call on the PortalContainerConfig in order to register the changes on the PortalContainerDefinitions --> <set-method>registerChangePlugin</set-method> <!-- The full qualified name of the PortalContainerDefinitionChangePlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionChangePlugin</type> <init-params> <value-param> <name>apply.default</name> <value>true</value> </value-param> <object-param> <name>change</name> <object type="org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependenciesBefore"> <!-- The list of name of the dependencies to add --> <field name="dependencies"> <collection type="java.util.ArrayList"> <value> <string>dependency1</string> </value> </collection> </field> <!-- The name of the target dependency --> <field name="target"> <string>dependency2</string> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
A.4.5.1.3. AddDependenciesAfter
PortalContainerDefinition. The full qualified name is org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependenciesAfter.
AddDependenciesAfter Parameters
- dependencies
- A list of String corresponding to the list of dependency names to add. If the field is unpopulated, the change is ignored.
- target
- The name of the dependency that the new dependencies are added before. New dependencies are added in first position to the list if this field is
null, or the target dependency cannot be found in the list of dependencies defined into thePortalContainerDefinition.
Example A.10. Adding Dependencies After
dependency1 after dependency2 in the dependency list of the default portal container.
<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>Change PortalContainer Definitions</name> <!-- The name of the method to call on the PortalContainerConfig in order to register the changes on the PortalContainerDefinitions --> <set-method>registerChangePlugin</set-method> <!-- The full qualified name of the PortalContainerDefinitionChangePlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionChangePlugin</type> <init-params> <value-param> <name>apply.default</name> <value>true</value> </value-param> <object-param> <name>change</name> <object type="org.exoplatform.container.definition.PortalContainerDefinitionChange$AddDependenciesAfter"> <!-- The list of name of the dependencies to add --> <field name="dependencies"> <collection type="java.util.ArrayList"> <value> <string>dependency1</string> </value> </collection> </field> <!-- The name of the target dependency --> <field name="target"> <string>dependency2</string> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
A.4.5.1.4. AddSettings
PortalContainerDefinition. The full qualified name is org.exoplatform.container.definition.PortalContainerDefinitionChange$AddSettings.
AddSettings Parameters
- settings
- A map of <String, Object> corresponding to the settings to add. The change is ignored if the value of this field is empty.
Example A.11. Add Settings
string and stringX to the settings of the default portal container.
<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>Change PortalContainer Definitions</name> <!-- The name of the method to call on the PortalContainerConfig in order to register the changes on the PortalContainerDefinitions --> <set-method>registerChangePlugin</set-method> <!-- The full qualified name of the PortalContainerDefinitionChangePlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionChangePlugin</type> <init-params> <value-param> <name>apply.default</name> <value>true</value> </value-param> <object-param> <name>change</name> <object type="org.exoplatform.container.definition.PortalContainerDefinitionChange$AddSettings"> <!-- The settings to add to the to the portal containers --> <field name="settings"> <map type="java.util.HashMap"> <entry> <key> <string>string</string> </key> <value> <string>value1</string> </value> </entry> <entry> <key> <string>stringX</string> </key> <value> <string>value1</string> </value> </entry> </map> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins>
A.4.6. Dynamically Disable a Portal Container
component-plugin elements to dynamically disable one or more portal containers.
Example A.12. Disabling a Portal Container
sales.
<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>Disable a PortalContainer</name> <!-- The name of the method to call on the PortalContainerConfig in order to register the changes on the PortalContainerDefinitions --> <set-method>registerDisablePlugin</set-method> <!-- The full qualified name of the PortalContainerDefinitionDisablePlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionDisablePlugin</type> <init-params> <!-- The list of the name of the portal containers to disable --> <values-param> <name>names</name> <value>sales</value> </values-param> </init-params> </component-plugin> </external-component-plugins>
PortalContainerDefinitionDisablePlugin Parameters
- names (*)
- Specifies a list of portal container names to disable.
Note
PortalContainer, ensure the following HTTP Filter (or a sub class of it) has been added to the web.xml file, at the beginning of the file.
<filter> <filter-name>PortalContainerFilter</filter-name> <filter-class>org.exoplatform.container.web.PortalContainerFilter</filter-class> </filter> <filter-mapping> <filter-name>PortalContainerFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Note
A.5. Runtime Configuration Profiles
# runs the portal with the profiles jboss, foo and bar sh run.sh -Dexo.profiles=foo,bar
- Any kernel element with the no profiles attribute will create a configuration object.
- Any kernel element having a profiles attribute containing at least one of the active profiles will create a configuration object.
- Any kernel element having a profiles attribute matching none of the active profiles will not create a configuration object
- Resolution of duplicates (such as two components of the same type) is left up to the kernel.
Profiles-capable Configuration Directives
- <component>
- The <component> element declares a component when activated. It will shadow any element with the same key declared before in the same configuration file:
<component> <key>Component</key> <type>Component</type> </component> <component profiles="foo"> <key>Component</key> <type>FooComponent</type> </component>
- <component-plugin>
- The <component-plugin> element is used to dynamically extend the configuration of a given component. Thanks to the profiles the <component-plugin> elements can be enabled or disabled:
<external-component-plugins> <target-component>Component</target-component> <component-plugin profiles="foo"> <name>foo</name> <set-method>addPlugin</set-method> <type>type</type> <init-params> <value-param> <name>param</name> <value>empty</value> </value-param> </init-params> </component-plugin> </external-component-plugins>
- <import>
- The <import> element imports a referenced configuration file when activated:
<import>empty</import> <import profiles="foo">foo</import> <import profiles="bar">bar</import>
- <init-params>
- The <init-params> element configures the parameter argument of the construction of a component service:
<component> <key>Component</key> <type>ComponentImpl</type> <init-params> <value-param> <name>param</name> <value>empty</value> </value-param> <value-param profiles="foo"> <name>param</name> <value>foo</value> </value-param> <value-param profiles="bar"> <name>param</name> <value>bar</value> </value-param> </init-params> </component>
- <value-collection>
- The <value-collection> element configures one of the value of collection data:
<object type="org.exoplatform.container.configuration.ConfigParam"> <field name="role"> <collection type="java.util.ArrayList"> <value><string>manager</string></value> <value profiles="foo"><string>foo_manager</string></value> <value profiles="foo,bar"><string>foo_bar_manager</string></value> </collection> </field> </object>
- <field-configuration>
- The <field-configuration> element configures the field of an object:
<object-param> <name>test.configuration</name> <object type="org.exoplatform.container.configuration.ConfigParam"> <field name="role"> <collection type="java.util.ArrayList"> <value><string>manager</string></value> </collection> </field> <field name="role" profiles="foo,bar"> <collection type="java.util.ArrayList"> <value><string>foo_bar_manager</string></value> </collection> </field> <field name="role" profiles="foo"> <collection type="java.util.ArrayList"> <value><string>foo_manager</string></value> </collection> </field> </object> </object-param>
A.6. Component request life cycle
A.6.1. Component request life cycle contract
public interface ComponentRequestLifecycle { /** * Start a request. * @param container the related container */ void startRequest(ExoContainer container); /** * Ends a request. * @param container the related container */ void endRequest(ExoContainer container); }
A.6.2. Request life cycle
RequestLifeCycle class has several statics methods that are used to schedule the component request life cycle of components. Its main responsibility is to perform scheduling while respecting the constraint to execute the request life cycle of a component only once even if it can be scheduled several times.
A.6.2.1. Scheduling a component request life cycle
RequestLifeCycle.begin(component); try { // Do something } finally { RequestLifeCycle.end(); }
A.6.2.2. Scheduling a container request life cycle
ComponentRequestLifeCycle. If one of the components has already been scheduled before, the component is not scheduled again.
true, the looked components are those of the container. When the value is false, the scheduler looks at the components in the ancestor containers.
RequestLifeCycle.begin(container, local); try { // Do something } finally { RequestLifeCycle.end(); }
A.6.2.3. When request life cycle is triggered
A.6.2.3.1. Portal request life cycle
A.6.2.3.2. JMX request Life Cycle
A.7. Configuring Services
configuration.xml configuration files. The location of the configuration files determines if services are placed into the RootContainer scope, or into the PortalContainer scope.
/conf/configuration.xml configuration file in the service's base folder. The container looks for a /conf/configuration.xml file in each jar-file.
/conf/configuration.xml in the classpath (any directory, or any jar in the classpath) will have services configured in the RootContainer scope.
configuration.xml files located in /conf/portal/configuration.xml of the classpath will have services configured at the PortalContainer scope.
$JPP_HOME/gatein/gatein.ear/portal.war/WEB-INF/conf/configuration.xml, and will also have their services configured in the PortalContainer scope.
Note
A.7.1. Configuration syntax
A.7.1.1. Components
configuration.xml by using a <component> element.
<?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_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <component> <key>org.exoplatform.services.database.HibernateService</key> <type>org.exoplatform.services.database.impl.HibernateServiceImpl</type> ... </component> </configuration>
/webapps/portal/WEB-INF/conf/configuration.xml file. Use <component> elements to contain the configuration information. The <key> element defines the interface, and the <type> tag defines the implementation. While the <key> tag is not mandatory, specifying it can result in a small performance improvement.
Example A.13. <component> Custom Configuration Block
<!-- Portlet container hooks --> <component> <key>org.exoplatform.services.portletcontainer.persistence.PortletPreferencesPersister</key> <type>org.exoplatform.services.portal.impl.PortletPreferencesPersisterImpl</type> </component>
Example A.14. Define Services That Can Receive Plug-ins Without a Framework Interface
<external-component-plugins> <target-component>org.exoplatform.services.database.HibernateService</target-component> <component-plugin> <name>add.hibernate.mapping</name> <set-method>addPlugin</set-method> <type>org.exoplatform.services.database.impl.AddHibernateMappingPlugin</type> <init-params> <values-param> <name>hibernate.mapping</name> <value>org/exoplatform/services/portal/impl/PortalConfigData.hbm.xml</value> <value>org/exoplatform/services/portal/impl/PageData.hbm.xml</value> <value>org/exoplatform/services/portal/impl/NodeNavigationData.hbm.xml</value> </values-param> </init-params> </component-plugin> </external-component-plugins>
Example A.15. Add Listener to the OrganizationService
addListenerPlugin with an object of type PortalUserEventListenerImpl. Each time a user is created (apart the predefined ones in the list ) PortalUserEventListenerImpl methods are called by the service.
<external-component-plugins> <target-component>org.exoplatform.services.organization.OrganizationService</target-component> <component-plugin> <name>portal.new.user.event.listener</name> <set-method>addListenerPlugin</set-method> <type>org.exoplatform.services.portal.impl.PortalUserEventListenerImpl</type> <description>this listener create the portal configuration for the new user</description> <init-params> <object-param> <name>configuration</name> <description>description</description> <object type="org.exoplatform.services.portal.impl.NewPortalConfig"> <field name="predefinedUser"> <collection type="java.util.HashSet"> <value><string>admin</string></value> <value><string>exo</string></value> <value><string>company</string></value> <value><string>community</string></value> <value><string>portal</string></value> <value><string>exotest</string></value> </collection> </field> <field name="templateUser"><string>template</string></field> <field name="templateLocation"><string>war:/conf/users</string></field> </object> </object-param> </init-params> </component-plugin> ...
A.7.1.1.1. RootContainer
- Services default
RootContainerconfigurations from JAR files/conf/configuration.xml - External
RootContainerconfiguration, to be found at$JPP_HOME/gatein/gatein.ear/portal.war/WEB-INF/conf/configuration.xml
RootContainer creates a Java HashTable which contains key-value pairs for the services. The qualified interface name of each service is used as key for the hash table. The <key> element of the configuration file contains the interface name. The value of each hash table pair is an object that contains the service configuration, which is the whole structure between the <component> tags of the configuration.xml file.
RootContainer runs over all JAR files present in $JPP_HOME/modules/system/layers/gatein/org/gatein/lib and checks if there is a configuration file located in /conf/configuration.xml. If the file is present, the services configured in this file are added to the hash table. At the end of the boot process, the default configurations for all services are stored in the hash table.
Note
$JPP_HOME/gatein/gatein.ear/portal.war/WEB-INF/conf/configuration.xml. The same configuration rules that apply to JARs apply to this configuration file.
A.7.1.1.2. PortalContainer
- Inherit the configuration of the RootContainer.
- Default PortalContainer configuration from all JAR files (/conf/portal/configuration.xml)
- Web application configurations from the
portal.warfile, or the portal web app configuration file (/WEB-INF/conf/configuration.xml). - External configuration for services of a named portal, located in
exo-tomcat/exo-conf/portal/$portal_name/configuration.xml.
/conf/portal/configuration.xml file of each JAR are loaded as they are discovered, the last configuration file loaded being the one used for all JARs. The next file the container loads is from within the portal.war archive (or the portal webapp folder). The /WEB-INF/conf/configuration.xml contains many import statements that point to other configuration files in the same portal.war (or portal webapp).
configuration.xml file in the PortalContainer. From Red Hat JBoss Portal 6.1, configuration can be provided from outside the JARs and WARs or webapps. Place a configuration file in exo-tomcat/exo-conf/portal/$portal_name/configuration.xml where $portal_name is the name of the portal to configure. In most cases, installations have one primary portal, named by default as "portal". In this scenario, the exo-tomcat/exo-conf/portal/portal/configuration.xml is used.
Note
exo-conf is looked up in directory specified by the Red Hat JBoss System property jboss.server.config.url. If the property is not found or empty, exo-jboss/exo-conf is loaded by default.
Note
exo.conf.dir can be used to override the external configuration location. If the property is defined, its value is used as path to the eXo configuration directory. This is an alternative method of loading configuration in the exo-tomcat/exo-conf folder.
java -Dexo.conf.dir=/path/to/exo/conf, or use eXo.bat or eXo.sh.
exo-tomcat/exo-conf/portal/PORTAL_NAME/configuration.xml and the target configuration file located in exo-tomcat/exo-conf/portal/PORTAL_NAME/mySubConfDir/myConfig.xml must be loaded, add <import>mySubConfDir/myConfig.xml</import> to the configuration file.
A.7.1.1.3. External Plug-ins
org.exoplatform.container.component.ComponentPlugin interface.
PortalContainerDefinitionPlugin implements the ComponentPlugin:
<?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_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <external-component-plugins> <target-component>org.exoplatform.container.definition.PortalContainerConfig</target-component> <component-plugin> <!-- The name of the plug-in --> <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 fully qualified name of the PortalContainerDefinitionPlugin --> <type>org.exoplatform.container.definition.PortalContainerDefinitionPlugin</type> ... </component-plugin> </external-component-plugins> </configuration>
org.exoplatform.services.cms.categories.impl.TaxonomyPlugin:
addTaxonomyPlugin(org.exoplatform.services.cms.categories.impl.TaxonomyPlugin plugin)
Note
A.7.1.1.4. Service instantiation
Example A.16. Service Instantiation
OrganizationServiceImpl.java [1] file has one constructor only.
ListenerService and a DatabaseService. These services must be instantiated before BaseOrganizationService, because BaseOrganizationService depends on them.
public OrganizationServiceImpl(ListenerService listenerService, DatabaseService dbService);
java.lang.Exception is thrown.
Note
A.7.1.1.5. Service Access
ExoContainer myContainer = ExoContainerContext.getCurrentContainer(); command.
myContainer.getComponentInstance(class) method.
Example A.17. Service Access Command and Method Usage
ArticleStatsService statsService = (ArticleStatsService) myContainer.getComponentInstance(ArticleStatsService.class);
Example A.18.
package com.laverdad.common; import org.exoplatform.container.ExoContainer; import org.exoplatform.container.ExoContainerContext; import com.laverdad.services.*; public class Statistics { public int makeStatistics(String articleText) { ExoContainer myContainer = ExoContainerContext.getCurrentContainer(); ArticleStatsService statsService = (ArticleStatsService) myContainer.getComponentInstance(ArticleStatsService.class); int numberOfSentences = statsService.calcSentences(articleText); return numberOfSentences; } public static void main( String args[]) { Statistics stats = new Statistics(); String newText = "This is a normal text. The method only counts the number of periods. " + "You can implement your own implementation with a more exact counting. " + "Let`s make a last sentence."; System.out.println("Number of sentences: " + stats.makeStatistics(newText)); } }
A.7.1.1.6. Includes, and special URLs
configuration.xml file into many smaller files, which are then included into the main configuration file.
Example A.19. Outsourcing Configuration to External Files
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <!-- Comment #1 --> <import>war:/conf/sample-ext/jcr/jcr-configuration.xml</import> <import>war:/conf/sample-ext/portal/portal-configuration.xml</import> </configuration>
war: URL schema indicates the path is resolved relative to the current PortalContainer's servlet context resource path, starting with /WEB-INF as the root.
Note
PortalContainer is a newly created PortalContainer, because war: URLs are used for PortalContainer scoped configuration only.
'jar:' URL schema.
A.7.1.1.7. Special variables
${container.name.suffix} special variable reference. This variable resolves to the name of the current portal container, prefixed by underscore (_).
PortalContainer available, and is only available for PortalContainer scoped services.
Example A.20. ${container.name.suffix} Usage
<?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_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.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.cache.region.jbc2.query.localonly" value="true" /> <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.jbc2.MultiplexedJBossCacheRegionFactory" /> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" /> <property name="hibernate.show_sql" value="false"/> <property name="hibernate.current_session_context_class" value="thread"/> <property name="hibernate.cache.use_second_level_cache" value="true"/> <property name="hibernate.cache.use_query_cache" value="true"/> <property name="hibernate.connection.datasource" value="${gatein.idm.datasource.name}${container.name.suffix}"/> <property name="hibernate.connection.autocommit" value="true"/> <!-- Should be automatically detected. Force otherwise <property name="hibernate.dialect" value="org.hibernate.dialect.XXXDialect"/> --> </properties-param> </init-params> </component> ... </configuration>
A.7.1.2. <init-params> configuration element
String, and the value can be any type that can be described using the kernel XML configuration.
Example A.21. <init-params> XML Configuration and Parameter Descriptions
<component> <key>org.exoplatform.services.naming.InitialContextInitializer</key> <type>org.exoplatform.commons.InitialContextInitializer2</type> <init-params> <properties-param> <name>default-properties</name> <description>Default initial context properties</description> </properties-param> </init-params> </component>
- <value-param>
- <values-param>
- <properties-param>
- <object-param>
value specification.
java.util.Properties instance.
Example A.22. <value-param> Example
<component> <key>org.exoplatform.portal.config.UserACL</key> <type>org.exoplatform.portal.config.UserACL</type> <init-params> ... <value-param> <name>access.control.workspace</name> <description>groups with memberships that have the right to access the User Control Workspace</description> <value>*:/platform/administrators,*:/organization/management/executive-board</value> </value-param> ... </component>
package org.exoplatform.portal.config; public class UserACL { public UserACL(InitParams params) { UserACLMetaData md = new UserACLMetaData(); ValueParam accessControlWorkspaceParam = params.getValueParam("access.control.workspace"); if(accessControlWorkspaceParam != null) md.setAccessControlWorkspace(accessControlWorkspaceParam.getValue()); ...
Example A.23. <values-param> XML Configuration and Parameter Descriptions
String instance.
<component> <key>org.exoplatform.services.resources.ResourceBundleService</key> <type>org.exoplatform.services.resources.impl.SimpleResourceBundleService</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.test.resources.test</value> </values-param> <values-param> <name>portal.resource.names</name> <description>The properties files of the portal , those file will be merged into one ResourceBundle properties </description> <value>local.portal.portal</value> <value>local.portal.custom</value> </values-param> </init-params> </component>
String instance. All String values are then collected into a java.util.List instance.
Example A.24. <properties-param> Hibernate Example
<component> <key>org.exoplatform.services.database.HibernateService</key> <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"/> <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/> ... </properties-param> </init-params> </component>
org.exoplatform.services.database.impl.HibernateServiceImpl, the name hibernate.properties of the <properties-param> is used to access the properties.
package org.exoplatform.services.database.impl; public class HibernateServiceImpl implements HibernateService, ComponentRequestLifecycle { public HibernateServiceImpl(InitParams initParams, CacheService cacheService) { PropertiesParam param = initParams.getPropertiesParam("hibernate.properties"); ... }
Example A.25. <object-param> XML Configuration and Parameter Descriptions
<component> <key>org.exoplatform.services.cache.CacheService</key> <jmx-name>cache:type=CacheService</jmx-name> <type>org.exoplatform.services.cache.impl.CacheServiceImpl</type> <init-params> <object-param> <name>cache.config.default</name> <description>The default cache configuration</description> <object type="org.exoplatform.services.cache.ExoCacheConfig"> <field name="name"> <string>default</string> </field> <field name="maxSize"> <int>300</int> </field> <field name="liveTime"> <long>300</long> </field> <field name="distributed"> <boolean>false</boolean> </field> <field name="implementation"> <string>org.exoplatform.services.cache.concurrent.ConcurrentFIFOExoCache</string> </field> </object> </object-param> </init-params> </component>
Example A.26. <object-param> and LDAP Example
<component> <key>org.exoplatform.services.LDAP.LDAPService</key> <type>org.exoplatform.services.LDAP.impl.LDAPServiceImpl</type> <init-params> <object-param> <name>LDAP.config</name> <description>Default LDAP config</description> <object type="org.exoplatform.services.LDAP.impl.LDAPConnectionConfig"> <field name="providerURL"> <string>LDAPs://10.0.0.3:636</string> </field> <field name="rootdn"> <string>CN=Administrator,CN=Users,DC=exoplatform,DC=org</string> </field> <field name="password"> <string>exo</string> </field> <field name="version"> <string>3</string> </field> <field name="minConnection"> <int>5</int> </field> <field name="maxConnection"> <int>10</int> </field> <field name="referralMode"> <string>ignore</string> </field> <field name="serverName"> <string>active.directory</string> </field> </object> </object-param> </init-params> </component>
- <name>
- <description>
- <object>, which defines the type and a number of <field> elements.
package org.exoplatform.services.LDAP.impl; public class LDAPServiceImpl implements LDAPService { ... public LDAPServiceImpl(InitParams params) { LDAPConnectionConfig config = (LDAPConnectionConfig) params.getObjectParam("LDAP.config") .getObject(); ...
package org.exoplatform.services.LDAP.impl; public class LDAPConnectionConfig { private String providerURL = "LDAP://127.0.0.1:389"; private String rootdn; private String password; private String version; private String authenticationType = "simple"; private String serverName = "default"; private int minConnection; private int maxConnection; private String referralMode = "follow"; ...
- string, int, long, boolean, date, double
<object type="package.name"> <field name="string"><string>This is a string</string></field> <field name="int"><int>1234</int></field> <field name="long"><long>123456</long></field> <field name="double"><double>1.1234</double></field> <field name="boolean"><boolean>true</boolean></field> <field name="name"> <object version="1.0" type="package.name"> <field name="nested 1"><string>value</string></field> <field name="nested 2"><int>1234</int></field> </object> </field> <field name="map"> <map type="java.util.HashMap"> <entry> <key><string>akey</string></key> <value><string>a value</string></value> </entry> <entry> <key><int>1234</int></key> <value><string>a value</string></value> </entry> </map> </field> <field name="list"> <collection type="java.util.ArrayList"> <value><string>a value</string></value> </collection> </field> </object>
A.7.1.2.1. Collection
database-organization-configuration.xml file as an example configuration. This file defines a default user organization (users, groups, memberships/roles) of the portal. The configuration uses <component-plugins> elements, and the <object-param> element is also used.
ArrayList, which contains one value: the object which defines the field of the NewUserConfig$JoinGroup bean.
HashSet that is a set of strings.
<component-plugin> <name>new.user.event.listener</name> <set-method>addListenerPlugin</set-method> <type>org.exoplatform.services.organization.impl.NewUserEventListener</type> <description>this listener assign group and membership to a new created user</description> <init-params> <object-param> <name>configuration</name> <description>description</description> <object type="org.exoplatform.services.organization.impl.NewUserConfig"> <field name="group"> <collection type="java.util.ArrayList"> <value> <object type="org.exoplatform.services.organization.impl.NewUserConfig$JoinGroup"> <field name="groupId"><string>/platform/users</string></field> <field name="membership"><string>member</string></field> </object> </value> </collection> </field> <field name="ignoredUser"> <collection type="java.util.HashSet"> <value><string>root</string></value> <value><string>john</string></value> <value><string>marry</string></value> <value><string>demo</string></value> <value><string>james</string></value> </collection> </field> </object> </object-param> </init-params> </component-plugin>
public class NewUserConfig { private List role; private List group; private HashSet ignoredUser; ... public void setIgnoredUser(String user) { ignoredUser.add(user); ... static public class JoinGroup { public String groupId; public String membership; ... }
A.7.1.3. Component Plug-in Priority
configuration.xml.
Example A.27. <priority> Element
... <component> <type>org.exoplatform.services.Component1</type> </component> <external-component-plugins> <target-component>org.exoplatform.services.Component1</target-component> <component-plugin> <name>Plugin1</name> <set-method>addPlugin</set-method> <type>org.exoplatform.services.plugins.Plugin1</type> <description>description</description> <priority>1</priority> </component-plugin> <component-plugin> <name>Plugin2</name> <set-method>addPlugin</set-method> <type>org.exoplatform.services.plugins.Plugin2</type> <description>description</description> <priority>2</priority> </component-plugin> </external-component-plugins> <external-component-plugins> <target-component>org.exoplatform.services.Component1</target-component> <component-plugin> <name>Plugin3</name> <set-method>addPlugin</set-method> <type>org.exoplatform.services.plugins.Plugin3</type> <description>description</description> </component-plugin> </external-component-plugins> ...
A.7.1.4. Configuration Logging
org.exoplatform.container.configuration.debug can assist with identifying problems with service configuration, by identifying the JAR/WAR that is causing issues. Add the system property to the eXo.bat or eXo.sh file in the exo-tomcat/bin/ directory.
set EXO_CONFIG_OPTS="-Dorg.exoplatform.container.configuration.debug"
...... Add configuration jar:file:/D:/Projects/eXo/dev/exo-working/exo-tomcat/lib/exo.kernel.container-trunk.jar!/conf/portal/configuration.xml Add configuration jar:file:/D:/Projects/eXo/dev/exo-working/exo-tomcat/lib/exo.kernel.component.cache-trunk.jar!/conf/portal/configuration.xml Add configuration jndi:/localhost/portal/WEB-INF/conf/configuration.xml import jndi:/localhost/portal/WEB-INF/conf/common/common-configuration.xml import jndi:/localhost/portal/WEB-INF/conf/database/database-configuration.xml import jndi:/localhost/portal/WEB-INF/conf/ecm/jcr-component-plugins-configuration.xml import jndi:/localhost/portal/WEB-INF/conf/jcr/jcr-configuration.xml ......
A.7.1.5. Import
import tag to reference other configuration files from within the configuration.xml file. The imported files can be placed anywhere on the system, providing the files can be accessed by the user configured on the host machine.
Important
war: Imports fromportal.war/WEB-INFjarorclasspath: Uses the classloader. Use this prefix in the default configuration for importing another configuration file accessible by the classloader.file: Uses an absolute path. A URL is also a valid value for this parameter.- without any prefix:
/gatein/gatein.ear/portal.war/WEB-INF/conf/configuration.xml file contains import statements primarily:
<import>war:/conf/common/common-configuration.xml</import> <import>war:/conf/common/logs-configuration.xml</import> <import>war:/conf/database/database-configuration.xml</import> <import>war:/conf/jcr/jcr-configuration.xml</import> <import>war:/conf/common/portlet-container-configuration.xml</import> ...
A.7.1.6. System properties
Example A.28. System Property
/web/portal/src/main/webapp/WEB-INF/conf/database/database-configuration.tmpl.xml shows how system properties are used in configuration.
<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.connection.url" value="${connectionUrl}"/> <property name="hibernate.connection.driver_class" value="${driverClass}"/> <property name="hibernate.connection.username" value="${username}"/> <property name="hibernate.connection.password" value="${password}"/> <property name="hibernate.dialect" value="${dialect}"/> ... </properties-param> </init-params> </component>
Note
java -DconnectionUrl=jdbc:hsqldb:file:../temp/data/exodb -DdriverClass=org.hsqldb.jdbcDriver.
.bat or .sh portal start script, which will load the configuration each time the portal is started: set EXO_OPTS="-DconnectionUrl=jdbc:hsqldb:file:../temp/data/exodb -DdriverClass=org.hsqldb.jdbcDriver"
A.8. Specific Services
A.8.1. ListenerService
org.exoplatform.services.listener.Listener registered by the ListenerService.
A.8.1.1. Configuring a Listener
ComponentPlugin. The following configuration is required:
<?xml version="1.0" encoding="ISO-8859-1"?> <configuration> ... <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>${name-of-the-target-event}</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>${the-FQN-of-the-listener}</type> </component-plugin> </external-component-plugins> </configuration>
A.8.1.2. Registering a Listener
addListener() method.
/** * This method is used to register a listener with the service. The method * will: 1. Check to see if there is a list of listener with the listener * name, create one if the listener list doesn't exit 2. Add the new listener * to the listener list * * @param listener */ public void addListener(Listener listener) { ... }
A.8.1.3. Triggering an Event
broadcast() methods of ListenerService.
/** * This method is used to broadcast an event. This method will: 1. Check if * there is a list of listener that listen to the event name. 2. If there is a * list of listener, create the event object with the given name , source and * data 3. For each listener in the listener list, invoke the method * onEvent(Event) * * @param <S> The type of the source that broadcast the event * @param <D> The type of the data that the source object is working on * @param name The name of the event * @param source The source object instance * @param data The data object instance * @throws Exception */ public <S, D> void broadcast(String name, S source, D data) throws Exception { ... } /** * This method is used when a developer neeeds to implement his own event object * and broadcast the event. The method will: 1. Check if there is a list of * listener that listen to the event name. 2. If there is a list of the * listener, For each listener in the listener list, invoke the method * onEvent(Event) * * @param <T> The type of the event object, the type of the event object has * to be extended from the Event type * @param event The event instance * @throws Exception */ public <T extends Event> void broadcast(T event) throws Exception { ... }
broadcast() methods retrieve the name of the event, finds the registered listeners with the same name, and calls the onEvent() method on each listener found.
org.exoplatform.services.listener.Listener, as described below:
public abstract class Listener<S, D> extends BaseComponentPlugin { /** * This method should be invoked when an event with the same name is * broadcasted */ public abstract void onEvent(Event<S, D> event) throws Exception; }
Warning
onEvent() method with the corresponding types.
public interface ComponentPlugin { public String getName(); public void setName(String name); public String getDescription(); public void setDescription(String description); }
A.8.1.4. Asynchronous Event Broadcast
@Asynchronous.
@Asynchronous class AsynchListenerWithException<S,D> extends Listener<S,D> { @Override public void onEvent(Event<S,D> event) throws Exception { // some expensive operation } }
ExecutorService.
ExecutorService is configured with thread pool size 1, which can be changed in the configuration file.
<component> <key>org.exoplatform.services.listener.ListenerService</key> <type>org.exoplatform.services.listener.ListenerService</type> <init-params> <value-param> <name>asynchPoolSize</name> <value>5</value> </value-param> </init-params> </component>
A.8.1.5. ListenerService Example
org.exoplatform.services.security.ConversationRegistry uses the ListenerService to notify that a user has signed in or left the application. When a user signs in, the following code is called:
listenerService.broadcast("exo.core.security.ConversationRegistry.register", this, state);
exo.core.security.ConversationRegistry.register, the source of which is the current instance of ConversationRegistry, and the data is that of the given state. The ListenerService calls the method onEvent(Event<ConversationRegistry, ConversationState> event) on all listeners with the name exo.core.security.ConversationRegistry.register.
Example A.29. Define a ConversationRegistry.register Listener
exo.core.security.ConversationRegistry.register.
<?xml version="1.0" encoding="ISO-8859-1"?> <configuration> ... <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>exo.core.security.ConversationRegistry.register</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.forum.service.AuthenticationLoginListener</type> </component-plugin> </external-component-plugins> </configuration> ...
A.8.2. Job Scheduler
- at a certain time of day (to the millisecond)
- on certain days of the week
- on certain days of the month
- on certain days of the year
- not on certain days listed within a registered Calendar (such as business holidays)
- repeated a specific number of times
- repeated until a specific time/date
- repeated indefinitely
- repeated with a delay interval
A.8.2.1. Using the Job Scheduler Service in the Kernel
org.quartz.Scheduler in org.exoplatform.services.scheduler.impl.QuartzSheduler for easier service wiring and configuration. To work with Quartz in Kernel, the org.exoplatform.services.scheduler.JobSchedulerService class (implemented by org.exoplatform.services.scheduler.impl.JobSchedulerServiceImpl is primarily used.
JobSchedulerService, configure it as a component in the configuration.xml file. Because JobSchedulerService requires QuartzSheduler and QueueTasks, these two components must also be configured.
<?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_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <component> <type>org.exoplatform.services.scheduler.impl.QuartzSheduler</type> </component> <component> <type>org.exoplatform.services.scheduler.QueueTasks</type> </component> <component> <key>org.exoplatform.services.scheduler.JobSchedulerService</key> <type>org.exoplatform.services.scheduler.impl.JobSchedulerServiceImpl</type> </component> </configuration>
A.8.2.2. Samples
JobSchedulerService by creating a sample project, and use the portal for testing.
org.quartz.Job interface and add the job class to perform.
Procedure A.1. Prepare Job Scheduler Project
- Download the project code from https://github.com/hoatle/job-scheduler-service-tutorial
- Create a project by using the maven archetype plug-in. Run the
mvn archetype:generatecommand to create a sample project.- For project type: select maven-archetype-quickstart.
- For groupId: select org.exoplatform.samples.
- For artifactId: select exo.samples.scheduler.
- For version: select 1.0.0-SNAPSHOT.
- For package: select org.exoplatform.samples.scheduler.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>exo.portal.parent</artifactId> <groupId>org.exoplatform.portal</groupId> <version>3.1.0-GA</version> </parent> <groupId>org.exoplatform.samples</groupId> <artifactId>exo.samples.scheduler</artifactId> <version>1.0.0-SNAPSHOT</version> <name>eXo Samples For Scheduler</name> <description>eXo Samples Code For Scheduler</description> </project>
- Generate an eclipse project by using maven eclipse plug-in and then import into eclipse:
mvn eclipse:eclipse
A.8.2.2.1. Define a Job
package org.exoplatform.samples.scheduler.jobs; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * SampleJob for executing a defined sample job. */ public class SampleJob implements Job { /** * The logger */ private static final Log LOG = ExoLogger.getLogger(SampleJob.class); /** * The job of the SampleJob will be done by executing this method. * * @param context * @throws JobExecutionException */ public void execute(JobExecutionContext context) throws JobExecutionException { LOG.info("SampleJob is executing..."); } }
execute method from org.quartz.Job interface. This method is called whenever a job is performed. With SampleJob, logging is used to verify the job is working. By looking at the terminal, the log message "SampleJob is executing..." is displayed.
A.8.2.2.2. Configuring a Job
org.exoplatform.services.scheduler.JobSchedulerService. Use the following methods for setting the component plug-in:
public void addPeriodJob(ComponentPlugin plug-in) throws Exception;
org.exoplatform.services.scheduler.PeriodJob. This type of job is used to perform actions that are executed over a period of time, by defining when the job is performed, when it ends, when it performs the first action, how many times it is executed and the period of time to perform the action.
Example A.30. PeriodJob <component-plugin>
<external-component-plugins> <target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component> <component-plugin> <name>PeriodJob Plugin</name> <set-method>addPeriodJob</set-method> <type>org.exoplatform.services.scheduler.PeriodJob</type> <description>period job configuration</description> <init-params> <properties-param> <name>job.info</name> <description>dumb job executed periodically</description> <property name="jobName" value="DumbJob"/> <property name="groupName" value="DumbJobGroup"/> <property name="job" value="org.exoplatform.samples.scheduler.jobs.DumbJob"/> <property name="repeatCount" value="0"/> <property name="period" value="60000"/> <property name="startTime" value="+45"/> <property name="endTime" value=""/> </properties-param> </init-params> </component-plugin> </external-component-plugins>
Example A.31. addCronJob
org.exoplatform.services.scheduler.CronJob. This type of job is used to perform actions at a specified time, using Unix 'cron-like' definitions. The plug-in uses the expression parameter to specify the 'cron-like' definitions to execute the job.
cron-line Examples
- At 12pm every day
- "0 0 12 * * ?"
- 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday
- "0 15 10 ? * MON-FRI"
Note
public void addCronJob(ComponentPlugin plugin) throws Exception;
<external-component-plugins> <target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component> <component-plugin> <name>CronJob Plugin</name> <set-method>addCronJob</set-method> <type>org.exoplatform.services.scheduler.CronJob</type> <description>cron job configuration</description> <init-params> <properties-param> <name>job.info</name> <description>dumb job executed by cron expression</description> <property name="jobName" value="DumbJob"/> <property name="groupName" value="DumbJobGroup"/> <property name="job" value="org.exoplatform.samples.scheduler.jobs.DumbJob"/> <!-- The job will be performed at 10:15am every day --> <property name="expression" value="0 15 10 * * ?"/> </properties-param> </init-params> </component-plugin> </external-component-plugins>
Example A.32. addGlobalJobListener and addJobListener
org.quartz.JobListener. This job listener is informed when org.quartz.JobDetail executes.
public void addGlobalJobListener(ComponentPlugin plugin) throws Exception;
public void addJobListener(ComponentPlugin plugin) throws Exception;
Example A.33. addGlobalTriggerListener and addTriggerListener
org.quartz.TriggerListener. This trigger listener is informed when a org.quartz.Trigger executes.
public void addGlobalTriggerListener(ComponentPlugin plugin) throws Exception;
public void addTriggerListener(ComponentPlugin plugin) throws Exception;
A.8.2.2.3. Run the Project
conf.portal package in the sample project. Add the configuration.xml file with the content as follows:
<?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_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"> <component> <type>org.exoplatform.services.scheduler.impl.QuartzSheduler</type> </component> <component> <type>org.exoplatform.services.scheduler.QueueTasks</type> </component> <component> <key>org.exoplatform.services.scheduler.JobSchedulerService</key> <type>org.exoplatform.services.scheduler.impl.JobSchedulerServiceImpl</type> </component> <external-component-plugins> <target-component>org.exoplatform.services.scheduler.JobSchedulerService</target-component> <component-plugin> <name>PeriodJob Plugin</name> <set-method>addPeriodJob</set-method> <type>org.exoplatform.services.scheduler.PeriodJob</type> <description>period job configuration</description> <init-params> <properties-param> <name>job.info</name> <description>sample job executed periodically</description> <property name="jobName" value="SampleJob"/> <property name="groupName" value="SampleJobGroup"/> <property name="job" value="org.exoplatform.samples.scheduler.jobs.SampleJob"/> <property name="repeatCount" value="0"/> <property name="period" value="60000"/> <property name="startTime" value="+45"/> <property name="endTime" value=""/> </properties-param> </init-params> </component-plugin> </external-component-plugins> </configuration>
mvn clean install the project, and copy the .jar file to the /lib directory in the portal directory. Run bin/run.sh to see the SampleJob to be executed on the terminal when portal containers are initialized. Review the terminal to see the log message of SampleJob.
A.8.3. The data source provider
A.8.3.1. DataSourceProvider
Parameters
- getDataSource(String dataSourceName)
- Queries the data source from a JNDI lookup. If the datasource is found and the data source is defined as managed, the service wraps the original DataSource instance in a new DataSource instance that is aware of its managed state. Otherwise it will return the original DataSource instance.
- isManaged(String dataSourceName)
- Indicates whether or not the given data source is managed.
A.8.3.2. Configuring DataSourceProvider
<configuration>
....
<component>
<key>org.exoplatform.services.jdbc.DataSourceProvider</key>
<type>org.exoplatform.services.jdbc.impl.DataSourceProviderImpl</type>
<init-params>
<!-- Indicates that the data source needs to check if a tx is active
to decide if the provided connection needs to be managed or not.
If it is set to false, the data source will provide only
managed connections if the data source itself is managed. -->
<!--value-param>
<name>check-tx-active</name>
<value>true</value>
</value-param-->
<!-- Indicates that all the data sources are managed
If set to true the parameter never-managed and
managed-data-sources will be ignored -->
<!--value-param>
<name>always-managed</name>
<value>true</value>
</value-param-->
<!-- Indicates the list of all the data sources that are
managed, each value tag can contain a list of
data source names separated by a comma, in the
example below we will register ds-foo1, ds-foo2
and ds-foo3 as managed data source. If always-managed
and/or never-managed is set true this parameter is ignored -->
<!--values-param>
<name>managed-data-sources</name>
<value>ds-foo1, ds-foo2</value>
<value>ds-foo3</value>
</values-param-->
</init-params>
</component>
...
</configuration>Field Descriptions
- <check-tx-active>
- Specifies the data source must check whether a transaction is active to determine if the provided connection must be managed or not. If it is set to
false, the data source provides only managed connections if the data source itself is managed.By default, this parameter is set totrue. If set totrue, theTransactionServiceis required in the configuration. - <always-managed>
- Specifies all data sources are managed. If set to
true, the parameters <never-managed> and <managed-data-sources> are ignored (marking all the data sources as managed). This parameter is set to false by default. - <managed-data-sources>
- Specifies the list of all data sources that are managed. Each <value> element can contain a list of data source names separated by a comma. This parameter is ignored if <always-managed> and/or <never-managed> is set to
true.
A.9. Configuring a portal container
- Portal Container Name
- The URL context to which the current portal is bound.
- REST Context Name
- The REST name used for access to portal application. Every portal has one unique REST context name.
- Realm Name
- The name of the security realm used for authentication when users log into the portal.
- Dependencies
- List of other web applications, whose resources are visible to the current portal (through the extension mechanism described later), and are searched for in the specified order.
<?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_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd" xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.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 --> <value> <string>sample-ext</string> </value> </collection> </field> </object> </object-param> </init-params> </component-plugin> </external-component-plugins> </configuration>
PortalContainer is represented by a PortalContainer instance, which contains the following configuration directives.
Portal Container Directives
- eXoContainerContext
- Contains information about the portal.
- Unified Servlet Context
- Controls web-archive-relative resource loading.
- Unified Classloader
- Classpath based resource loading.
- Various methods for retrieving services
ServletContext, and ClassLoader) with specific resource loading behavior, such as visibility into associated web application archives, configured with the dependencies property of PortalContainerDefinition.
A.10. System property configuration
System Property Definitions
- properties
- The properties init param takes a property declared to configure various properties.
<component> <key>PropertyManagerConfigurator</key> <type>org.exoplatform.container.PropertyConfigurator</type> <init-params> <properties-param> <name>properties</name> <property name="foo" value="bar"/> </properties-param> </init-params> </component>
- properties.url
- The properties.url init param specifies an external file to load by URL reference. Both property and XML formats are supported (see the javadoc of the
java.util.Propertiesclass for more information).When a property file is loaded the various property declarations are loaded in the order in which the properties are declared sequentially in the file.<component> <key>PropertyManagerConfigurator</key> <type>org.exoplatform.container.PropertyConfigurator</type> <init-params> <value-param> <name>properties.url</name> <value>classpath:configuration.properties</value> </value-param> </init-params> </component>
In the properties file corresponding to the external properties, existing variables can be reused to create a new variable. Using this feature, the prefix "portal.container." is not needed. For example:my-var1=value 1 my-var2=value 2 complex-value=${my-var1}-${my-var2}It is possible to replace the properties URL init param by a system property that overwrites it. The name of that property is exo.properties.url.
${variable-name}, which does not define a default value. If the variable has not be set, the value is ${variable-name} to indicate that it could not be resolved.${variable-name:default-value}, which allows the default value to be defined after the semicolon. If the variable has not be set, the value will be the given default value.
A.10.1. Properties <init-param>
<component> <key>PropertyManagerConfigurator</key> <type>org.exoplatform.container.PropertyConfigurator</type> <init-params> <properties-param> <name>properties</name> <property name="foo" value="bar"/> </properties-param> </init-params> </component>
A.10.2. Properties URL <init-param>
java.util.Properties class for more information. When a property file is loaded the various property declarations are loaded in the order in which the properties are declared sequentially in the file.
<component> <key>PropertyManagerConfigurator</key> <type>org.exoplatform.container.PropertyConfigurator</type> <init-params> <value-param> <name>properties.url</name> <value>classpath:configuration.properties</value> </value-param> </init-params> </component>
my-var1=value 1
my-var2=value 2
complex-value=${my-var1}-${my-var2}
A.10.3. System Property configuration of the properties URL
A.10.4. Variable Syntaxes
A.11. The Extension Mechanism and Portal Extensions
.war archives by adding a .war archive to the resources and configuring its position in the portal's classpath. Custom .war archives can be created with new resources that override the resources in the original archive.
Procedure A.2. Creating a Portal Extension
- Declare the PortalConfigOwner servlet context listener in the
web.xmlof the web application.This example shows a portal extension calledsample-ext.<?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> <listener> <listener-class>org.exoplatform.container.web.PortalContainerConfigOwner</listener-class> </listener> ... </web-app>
- Add the application's servlet context name to the
PortalContainerDefinition's list of dependencies. This must be done for each portal container that requires access to the new application.The application's position in these lists dictates its priority when the portal loads resources. The later the application appears in the list, the higher its resource priority will be. - The new web archive is present on both the portal's unified classpath and unified servlet context resource path.
A.11.1. Running Multiple Portals
org.exoplatform.container.eXoContainerContext.
PortalContainer is associated with the current eXoContainerContext call.
org.exoplatform.container.web.AbstractHttpServlet class so as to properly initialize the current PortalContainer.
org.exoplatform.container.web.AbstractFilter.
AbstractHttpServlet, and AbstractFilter have a getContainer() method, which returns the current PortalContainer.
service() method, that method must be renamed to match the following signature:
/** * Use this method instead of Servlet.service() */ protected void onService(ExoContainer container, HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException;
Note
AbstractHttpServlet's service() interception is not overwritten.
HttpSessionListener. Ensure the abstract class org.exoplatform.container.web.AbstractHttpSessionListener is extended.
/** * Use this method instead of HttpSessionListener.sessionCreated() */ protected void onSessionCreated(ExoContainer container, HttpSessionEvent event); /** * Use this method instead of HttpSessionListener.sessionDestroyed() */ protected void onSessionDestroyed(ExoContainer container, HttpSessionEvent event);
/** * Method should return true if unified servlet context, * and unified classloader should be made available */ protected boolean requirePortalEnvironment();
AbstractHttpServlet and AbstractFilter. This is a default implementation that automatically returns true when it detects there is a current PortalContainer present and false otherwise.
.war and .ear files); it is the application server that performs the deployment.
PortalContainer to properly initialize themselves. This gives rise to a recursive dependency problem.
PortalContainer to initialize must avoid performing their initialization directly on a ServletContextListener executed during their deployment (before any PortalContainer was initialized).
init task of an appropriate type and only use ServletContextListener to insert the init task instance into the proper init tasks queue.
PortalContainer. This example uses PortalContainerPostInitTask which is executed after the portal container has been initialized.
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) { try { SourceStorage sourceStorage = (SourceStorage) portalContainer.getComponentInstanceOfType(SourceStorage.class); ... } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException("Initialization failed: ", e); } } }; // Add post-init task for execution on all the portal containers // that depend on the given ServletContext according to // PortalContainerDefinitions (via Dependencies configuration) PortalContainer.addInitTask(event.getServletContext(), task); } }
PortalContainerPreInitTask can be used in that case.
PortalContainerPostCreateTask if initialization is required after all the post-init tasks have been executed.
LoginModules require the current eXoContainer for initialization ensure they extend org.exoplatform.services.security.jaas.AbstractLoginModule.
AbstractLoginModule enforces some basic configuration. It recognizes two initialization options; portalContainerName and realmName.
A.12. Manageability
A.12.1. Introduction
A.12.2. Managed framework API
A.12.2.1. Annotations
Annotations List
- @org.exoplatform.management.annotations.Managed annotation
- The @Managed annotates elements that wants to expose a management view to a management layer.
- The @Managed annotation on objects exports a management view for the objects annotated.
- The @Managed annotation on getters and setters defines a managed property. An annotated getter defines a read property, an annotated setter defines a write property. If a matching getter or setter is annotated, the annotation defines a read-write property.
- The @Managed annotation on methods defines a managed operation.
- @org.exoplatform.management.annotations.ManagedDescription
- The @ManagedDescription annotation provides a description of a managed element. It is valid to annotated object or methods. It takes as sole argument a string that is the description value.
- @org.exoplatform.management.annotations.ManagedName
- The @ManagedName annotation provides an alternative name for managed properties. It is used to accomodate legacy methods of an object that can be renamed for compatibility reasons. It takes as sole argument a string that is the name value.
- @org.exoplatform.management.annotations.ManagedBy
- The @ManagedBy annotation defines a delegate class for exposing a management view. The sole argument of the annotation are class literals. The delegate class must provide a constructor with the managed object as argument.
A.12.2.1.1. @org.exoplatform.management.annotations.Managed annotation
A.12.2.1.2. @org.exoplatform.management.annotations.ManagedDescription
A.12.2.1.3. @org.exoplatform.management.annotations.ManagedName
A.12.2.1.4. @org.exoplatform.management.annotations.ManagedBy
A.12.3. JMX Management View
A.12.3.1. JMX Annotations
JMX Annotations
- @org.exoplatform.management.jmx.annotations.Property
- The @Property annotation is used to within other annotations such as @NameTemplate or @NamingContext. It should be seen as a structural way for a list of properties. A property is made of a key and a value. The value can either be a string literal or it can be surrounded by curly braces (
{}) to a dynamic property. A dynamic property is resolved against the instance of the object at runtime. - @org.exoplatform.management.jmx.annotations.NameTemplate
- The @NameTemplate defines a template used at registration time of a managed object to create the JMX object name. The template is populated with properties.
@NameTemplate({ @Property(key="container", value="workspace"), @Property(key="name", value="{Name}")})
- @org.exoplatform.management.jmx.annotations.NamingContext
- The @NamingContext annotation defines a set of properties which are used within a management context. It allows to propagate properties down to managed objects which are defined by an object implementing the ManagementAware interface. The goal is to scope different instances of the same class that would have the same object name otherwise.
@NamingContext(@Property(key="workspace", value="{Name}"))
A.12.3.1.1. @org.exoplatform.management.jmx.annotations.Property annotation
A.12.3.1.2. @org.exoplatform.management.jmx.annotations.NameTemplate annotation
@NameTemplate({ @Property(key="container", value="workspace"), @Property(key="name", value="{Name}")})
A.12.3.1.3. @org.exoplatform.management.jmx.annotations.NamingContext annotation
@NamingContext(@Property(key="workspace", value="{Name}"))
A.12.4. Example
A.12.4.1. CacheService example
@ManagedBy(CacheServiceManaged.class) public class CacheServiceImpl implements CacheService { CacheServiceManaged managed; ... synchronized private ExoCache createCacheInstance(String region) throws Exception { ... if (managed != null) { managed.registerCache(simple); } ... } }
@Managed @NameTemplate({@Property(key="service", value="cache"), @Property(key="name", value="{Name}")}) @ManagedDescription("Exo Cache") public interface ExoCache { @Managed @ManagedName("Name") @ManagedDescription("The cache name") public String getName(); @Managed @ManagedName("Capacity") @ManagedDescription("The maximum capacity") public int getMaxSize(); @Managed @ManagedDescription("Evict all entries of the cache") public void clearCache() throws Exception; ... }
@Managed public class CacheServiceManaged implements ManagementAware { /** . */ private ManagementContext context; /** . */ private CacheServiceImpl cacheService; public CacheServiceManaged(CacheServiceImpl cacheService) { this.cacheService = cacheService; // cacheService.managed = this; } public void setContext(ManagementContext context) { this.context = context; } void registerCache(ExoCache cache) { if (context != null) { context.register(cache); } } }

