Chapter 53. Packaging Nuxeo EAR

Table of Contents

53.1. Introduction
53.2. Basic project structure
53.3. The EAR module
53.3.1. Assembly descriptor
53.3.2. Add some resources
53.4. Improve usability
53.4.1. Thanks to Maven
53.4.2. Thanks to Ant
53.5. Recommended multi-machine packagings
53.5.1. Bi-machine: stateful/stateless

53.1. Introduction

Goal of this chapter is to help creating projects over Nuxeo. How to create a project structure including a packaging module that builds one or more Enterprise ARchive (EAR), ready for deployment. Ant scripts, Maven profiles and Nuxeo assemblies allow defining simple commands to build packages that will fit each target environments.

53.2. Basic project structure

Good practice is to define a parent pom at project root and set a module-ear. Beside that, you may have as many modules and sub-modules as you want. We recommend to split your code according to some development and deployment criteria: API, web or core contributions, stateful or stateless services, ... Following this main rule, you have to create multiple modules where to dispatch your code and resources. Maven will manage the dependencies between modules and our assembly files will package EAR with all required libraries.

Following multi-module project template is available here

|-- README.txt
|-- build.properties.sample                                                              (1)
|-- build.xml                                                                            (2)
|-- fixeclipse                                                                           (3)
|-- pom.xml                                                                              (4)
|-- .project.ok                                                                          (5)
|-- template-api                                                                         (6)
|-- template-core                                                                        (7)
|-- template-web                                                                         (8)
|-- template-ear                                                                         (9)
|   |-- pom.xml
|   `-- src
|       `-- main
|           |-- assemble                                                                 (10)
|           |   |-- template-dev.xml
|           |   |-- template-ldap-pg.xml
|           |   |-- template-stateful.xml
|           |   `-- template-stateless.xml
|           |-- resources_template_common                                                (11)
|           |   `-- README.txt
|           |-- resources_template_dev
|           |   `-- README.txt
|           |-- resources_template_ldap_pg
|           |   |-- config
|           |   |   |-- default-repository-config.xml
|           |   |   |-- jdbc-compass-connection-config.xml
|           |   |   `-- sql.properties
|           |   |-- datasources
|           |   |   `-- unified-nuxeo-ds.xml
|           |   `-- system
|           |       `-- nuxeo-platform-search-compass-plugin-5.1.7-SNAPSHOT.jar
|           |           `-- compass.cfg.xml
|           |-- resources_template_stateful
|           `-- resources_template_stateless
|-- template-stateful-services                                                           (12)
|-- template-stateless-services                                                          (13)
`-- template-test                                                                        (14)
    
1

Ant sample properties. Copy this file to build.properties and personalize it to fit your installation.

2

Ant script. It's aimed to ease the use of maven, giving targets to automatize common tasks on project (test, compile, deploy, package, ...).

3

OS dependent, will only work on Linux/Unix and Mac OS X. Copy it from Nuxeo EP root. It's a shell utility script that calls maven-eclipse-plugin to create or update Eclipse's .project and .classpath files, taking care of setting different build directories for Maven and Eclipse. The script gives precedence to any present .project.ok or .classpath.ok.

4

Maven project parent file.

5

Required to import this project into eclipse as a whole resources project (each module will also be individually imported as a java project).

6

This module contains common code usable in all other modules, such as interfaces, adaptors, constants, data transfer objects, ...

7

This module contains all contributions to Nuxeo Core.

8

This module contains all JSF, Seam, WebEngine contributions, components and templates.

9

This module provides packaging of Nuxeo EP following assembly descriptors.

10

Assembly descriptors. Here are some samples.

11

Resources directory sample.

12

This module gathers all Message Resolved Beans that modify some data and all services that define their own persistence source.

13

This module contains all services that are not going into template-stateful-services.

14

This module is for use in unit tests from other modules.

53.3. The EAR module

Describe packaging with assembly descriptors

53.3.1. Assembly descriptor

              <!-- This is a template assembly file that generates a mono Nuxeo-EP server.
  Configuration is designed for development usage -->

<assembly>
  <!-- RESOURCES -->
  <assemble>
    <set>resources</set>
    <outputFile>/</outputFile>
  </assemble>
  <zipEntrySet id="resources">
    <artifact>
      org.nuxeo.ecm.platform:nuxeo-platform-ear:${nuxeo.platform.version}:zip:resources-mono
    </artifact>
  </zipEntrySet>

  <!-- ARTIFACTS -->
  <assemble>
    <outputFile>/</outputFile>
    <set>root-artifacts</set>
  </assemble>
  <artifactSet id="root-artifacts">
    <import>**</import>
    <includeDependencies>false</includeDependencies>
    <includes>
      <artifact name="nuxeo-platform-webapp" />
      <artifact name="nuxeo-platform-webapp-core" />
    </includes>
  </artifactSet>

  <assemble>
    <outputFile>system</outputFile>
    <set>system</set>
  </assemble>
  <artifactSet id="system">
    <import>**</import>
    <includeDependencies>true</includeDependencies>
    <includes>
      <artifact group="org.nuxeo.*" category="runtime,jboss4"
        includeDependsOnCategory="false" />
      <artifact group="org.nuxeo.*" category="core,search,web" />
      <!-- add here nuxeo-addons -->
    </includes>
    <excludes>
      <artifact group="!org.nuxeo*" />
      <artifact group="org.nuxeo.common" />
      <artifact name="nuxeo-runtime-jboss-extensions" />

      <artifact name="nuxeo-platform-webapp" />
      <artifact name="nuxeo-platform-webapp-core" />

      <artifact name="nuxeo-platform-audit-facade" />
      <artifact name="nuxeo-platform-placeful-facade" />
      <artifact name="nuxeo-platform-search-compass-plugin" />
      <artifact name="nuxeo-platform-ear" />
      <artifact name="nuxeo-apt-extensions" />
      <artifact group="org.nuxeo.projects.template" />
    </excludes>
  </artifactSet>

  <assemble>
    <outputFile>system</outputFile>
    <unpack>true</unpack>
    <unpackInNewDirectory>true</unpackInNewDirectory>
    <set>nuxeo-platform-unpacked</set>
  </assemble>
  <artifactSet id="nuxeo-platform-unpacked">
    <import>**</import>
    <includes>
      <artifact name="nuxeo-platform-audit-facade" />
      <artifact name="nuxeo-platform-placeful-facade" />
      <artifact name="nuxeo-platform-search-compass-plugin" />
    </includes>
  </artifactSet>

  <!-- third party libraries embedded in the ear -->
  <assemble>
    <outputFile>lib</outputFile>
    <set>nuxeo-fixed-libs</set>
  </assemble>
  <artifactSet id="nuxeo-fixed-libs">
    <artifacts>
      <artifact group="org.freemarker" name="freemarker" version="2.3.11" />
      <artifact group="org.osgi" name="osgi-core" version="4.1" />
      <artifact group="commons-collections" name="commons-collections"
        version="3.1" />
      <artifact group="commons-io" name="commons-io" version="1.2" />
      <artifact group="commons-lang" name="commons-lang" version="2.2" />
      <artifact group="commons-fileupload" name="commons-fileupload"
        version="1.1.1" />
      <artifact group="cssparser" name="cssparser" version="0.9.4-fix" />
      <artifact group="net.sf.ehcache" name="ehcache" version="1.2.3" />
      <artifact group="net.sf.ezmorph" name="ezmorph" version="0.9" />
      <artifact group="org.hibernate" name="hibernate" version="3.2.0.ga" />
      <artifact group="org.hibernate" name="hibernate-annotations"
        version="3.2.0.ga" />
      <artifact group="org.hibernate" name="hibernate-entitymanager"
        version="3.2.0.ga" />
      <artifact group="jboss" name="jboss-cache-jdk50" version="1.4.0.SP1" />
      <artifact group="org.jboss.seam" name="jboss-seam" version="1.1.5.NX3" />
      <artifact group="jboss" name="jbpm" version="3.1.2" />
      <artifact group="jboss" name="jgroups" version="2.2.9" />
      <artifact group="net.sf.json-lib" name="json-lib" version="0.9" />
      <artifact group="org.apache.lucene" name="lucene-core" version="2.0.0" />
      <artifact group="net.sf.opencsv" name="opencsv" version="1.7" />
      <artifact group="org.slf4j" name="slf4j-api" version="1.3.0" />
      <artifact group="org.slf4j" name="slf4j-log4j12" version="1.3.0" />
      <artifact group="org.apache.myfaces.tomahawk" name="tomahawk"
        version="1.1.5" />
      <artifact group="org.apache.myfaces.tomahawk" name="tomahawk-sandbox"
        version="1.1.5" />
      <artifact group="org.apache.myfaces.trinidad" name="trinidad-api"
        version="1.0.1-incubating-NXEP51M2" />
      <artifact group="org.apache.myfaces.trinidad" name="trinidad-impl"
        version="1.0.1-incubating-NXEP51M2" />
      <artifact group="org.apache.directory.server"
        name="apacheds-protocol-shared" version="1.5.1" />
      <artifact group="org.apache.directory.shared" name="shared-ldap"
        version="0.9.7" />
      <artifact group="com.sun.facelets" name="jsf-facelets" version="1.1.11" />
      <artifact group="org.nuxeo.ecm.platform" name="nuxeo-jbossws-wrapper"
        version="4.0.5.GA" />
    </artifacts>
  </artifactSet>

  <!-- template project's artifacts -->
  <assemble>
    <outputFile>plugins</outputFile>
    <set>template-plugins</set>
  </assemble>
  <artifactSet id="template-plugins">
    <import>**</import>
    <includeDependencies>false</includeDependencies>
    <includes>
      <artifact group="org.nuxeo.projects.template" />
    </includes>
  </artifactSet>

  <!-- template project's resources -->
  <assemble>
    <outputFile>/</outputFile>
    <set>template-resources</set>
  </assemble>
  <fileSet id="template-resources">
    <directory>src/main/resources_template_common</directory>
    <excludes>
      <exclude>README.txt</exclude>
    </excludes>
  </fileSet>
  <assemble>
    <outputFile>/</outputFile>
    <set>template-resources-dev</set>
  </assemble>
  <fileSet id="template-resources-dev">
    <directory>src/main/resources_template_dev</directory>
    <excludes>
      <exclude>README.txt</exclude>
    </excludes>
  </fileSet>

</assembly>

          

Example 53.1. Sample of customized assembly for a standard EAR, configured for development


Create an XML file in template-ear/src/main/assemble/ that will describe the EAR to build. Here's the file content:

  • assembly: the main tag. For now, you can only define one assembly per file (meaning one packaging definition by assembly descriptor file).

  • assemble: part of an assembly. An assemble must be associated with a set (different sets are available: zipEntrySet, fileSet, artifactSet).

    • set: string. Id of associated set.

    • outputFile: output directory string. "/" represents the building EAR root.

    • unpack: true or false. Whether the set content should be unpack.

    • unpackInNewDirectory: true or false. if unpack is true, whether to create new directories or not in the output directory.

  • zipEntrySet

    This set allow to retrieve artifacts from outside the project dependencies and unzip them.

    • id: required set id.

    • artifact: group:name:version:type:classifier of an artifact to retrieve from maven resolution, even if not present in the project's dependency tree. Will be unzipped if necessary.

    • profile: if specified, will only be treated if the given maven profile is active.

  • artifactSet

    This set retrieves all artifacts from the project's dependencies tree, depending on conditions

    • id: required set id.

    • import: "**" is required for inheriting project's dependencies.

    • includeDependencies: true or false. If true, all dependencies of selected artifacts by this set will be added to the set.

    • excludeDependencies: true or false. If true, all dependencies of selected artifacts by this set will be removed from the set.

    • extends: deprecated. Was aimed to allow assemblies inheritance and sets overriding.

    • includes (or excludes): artifacts list to include (resp. exclude). Each artifact accept these parameters:

      • group: artifact's group id. Accept wildcards '*' and negative '!' to match multiple artifacts.

      • name: artifact's id. Accept wildcards '*' and negative '!' to match multiple artifacts.

      • type: artifact's type (pom, jar, ejb, ...).

      • version: artifact's version.

      • scope: artifact's scope (test, compile, provided, ...).

      • classifier: artifact's classifier.

      • file: artifact's filename. Accept wildcards '*' and negative '!' to match multiple artifacts.

      • category: artifact's category. Concept introduced by Nuxeo to "tag" an artifact with a "category". This is done in the artifact's Manifest as "Bundle-Category". Multiple categories, comma separated, is interpreted as an union of matching artifacts.

      • includeDependsOnCategory: true or false. In case of category specified, whether to include or not any artifact which has at least one dependency matching the specified category.

      • profile: if specified, the artifact will only be treated (included or excluded) if the given maven profile is active.

  • fileSet

    This set is for manipulating local resources.

    • id: required set id.

    • directory: root directory of resources to copy. For now, only one directory per set is allowed

    • includes: files and directories list to include.

      • include: string. File, directory or pattern file/directory to include. "**" means multiple directories.

    • excludes: files and directories list to exclude. By default, these patterns are already excluded: "**/.svn" and "**/.hg".

      • exclude: string. File, directory or pattern file/directory to exclude. "**" means multiple directories.

53.3.2. Add some resources

With this assembly descriptor file, you can configure your local resources to be copied into the packaged EAR. The above template gives some usual resources folders.

  • resources_template_common where you put your resources that should always be added or overwrite the default ones.

  • resources_template_dev where you put your resources configured for development purpose (filesystem backend, ...).

  • resources_template_ldap_pg is an example where you can put resources parameterized to configure Nuxeo with LDAP users and/or groups and a PostgreSQL backend.

  • resources_template_stateful and resources_template_stateless are to be used for a bi-machine packaging, explained later in this chapter.

53.4. Improve usability

It is important to give simple and stable ways to use these assembly descriptors. Maven will allow to configure profiles and parameters. Ant will then give possibility to call multiple maven and shell commands, OS independent.

53.4.1. Thanks to Maven

The module-ear pom.xml file must have in its dependencies all wanted artifacts that will then be filtered by the assembly descriptor. Including nuxeo-platform-ear bring all its dependencies, there's no need to copy Nuxeo's artifacts list.

In order to call the assembly descriptor, it must contain the following plugin declaration. "template.ear.assembly" is used to parameterize the assembly descriptor name. Set a default value with a property.

  <properties>
    <!-- default assembly descriptor to use -->
    <template.ear.assembly>template-dev</template.ear.assembly>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-nuxeo-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <runPreprocessor>false</runPreprocessor>
          <format>directory</format>
          <outputDirectory>../target</outputDirectory>
          <targetFile>${template.ear.assembly}</targetFile>
          <descriptor>
            ${basedir}/src/main/assemble/${template.ear.assembly}.xml
          </descriptor>
        </configuration>
        <executions>
          <execution>
            <id>assemble-ear</id>
            <phase>package</phase>
            <goals>
              <goal>assembly</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>    

Maven parameters may be set in command-line. For example, in the above template, "mvn clean package" will package a Nuxeo EAR for developers and "mvn clean package -Dtemplate.ear.assembly=template-ldap-pg" will call template-ldap-pg.xml instead of template-dev.xml and so package a Nuxeo EAR configured for LDAP and PostgreSQL.

You can also use Maven profiles with "-P" argument.

53.4.2. Thanks to Ant

Using Ant, we will automatize lot of common tasks. Here's the output of command "ant -projecthelp" on template-project:

$ ant -projecthelp
Buildfile: build.xml

Main targets:

 copy             Replace ear and copy libs to jboss
 copy-2parts      Copy Nuxeo-EP in two parts
 copy-3parts      DEPRECATED: Copy Nuxeo-EP in three parts
 copy-ldap-pg     Copy template on LDAP and Postgres
 deploy           Build and copy to JBoss
 deploy-2parts    Build 2parts and copy to two patched JBoss
 deploy-ldap-pg   Build for LDAP and Postgres and copy to JBoss
 install          Run mvn install
 package          Package Nuxeo-EP
 package-2parts   Package Nuxeo-EP in two parts
 package-3parts   DEPRECATED: Package Nuxeo-EP in three parts
 package-ldap-pg  Package for LDAP and Postgres
 web              Copy web files to a live JBoss
Default target: usage
              <?xml version="1.0"?>
<project name="template" default="usage" basedir=".">

  <!-- Create a build.properties file from build.properties.sample
       if you wish to override the JBoss paths -->
  <property file="build.properties" />
  <property name="jboss.dir" value="/opt/jboss" />
  <property name="jboss.config" value="default" />
  <property name="mvn.opts" value="" />

  <property name="javac.debug" value="true" />
  <property name="javac.deprecation" value="false" />

  <!-- Boilerplate configuration -->
  <property name="build.dir" value="${basedir}/target" />
  <property name="deploy.dir" value="${jboss.dir}/server/${jboss.config}/deploy" />
  <property name="template.ear.root" value="template-ear" />
  <property name="nuxeo.ear" value="nuxeo.ear" />
  <property name="deploy.lib.dir" value="${jboss.dir}/server/${jboss.config}/lib" />
  <property name="build.lib.dir" value="lib" />


  <!-- these properties will need to be overridden at execution time -->
  <target name="set.jboss.home" unless="jboss.home">
    <property name="jboss.home" value="${jboss.dir}" />
  </target>
  <target name="set.assembly.name" unless="assembly.name">
    <property name="assembly.name" value="template-dev" />
  </target>
  <target name="setproperties" unless="jboss.server" depends="set.jboss.home, set.assembly.name">
    <property name="assembly.ear" value="${assembly.name}" />
    <property name="jboss.server" value="${jboss.home}/server/${jboss.config}" />
    <property name="jboss.deploy" value="${jboss.server}/deploy" />
    <property name="jboss.lib" value="${jboss.server}/lib" />
    <property name="jboss.nuxeo.ear" value="${jboss.deploy}/nuxeo.ear" />
    <property name="template.ear.build" value="${template.ear.root}/target/${assembly.ear}" />
  </target>

  <target name="usage">
    <echo message="usage: ant [package|deploy|web|package-2parts|deploy-2parts|package-ldap-pg|deploy-ldap-p]" />
    <echo message="ant package         => Package template to ${build.dir}/${nuxeo.ear}" />
    <echo message="ant deploy          => Package template and copy to ${deploy.dir}" />
    <echo message="ant deploy-Nparts   => Package template and copy to ${deploy.dir} relative to the ${jbossN.dir} properties" />
    <echo message="ant web             => Copy web files to a live JBoss (${deploy.dir})" />
  </target>

  <condition property="osfamily-unix">
    <os family="unix" />
  </condition>
  <condition property="osfamily-windows">
    <os family="windows" />
  </condition>

  <target name="deploy" depends="install,package,copy,copy-lib" description="Build and copy to JBoss">
    <echo message="Deployed ${ant.project.name} to ${deploy.dir}" />
  </target>

  <target name="deploy-ldap-pg" depends="install,package-ldap-pg,copy-ldap-pg" description="Build for LDAP and Postgres and copy to JBoss">
  </target>
  <target name="deploy-2parts" depends="install,package-2parts,copy-2parts" description="Build 2parts and copy to two patched JBoss">
  </target>

  <target name="package-ldap-pg" description="Package for LDAP and Postgres">
    <antcall target="package">
      <param name="assembly.name" value="template-ldap-pg" />
    </antcall>
  </target>
  <target name="package-2parts" description="Package Nuxeo-EP in two parts">
    <antcall target="package">
      <param name="jboss.home" value="${jboss1.dir}" />
      <param name="assembly.name" value="template-stateful" />
    </antcall>
    <antcall target="package">
      <param name="jboss.home" value="${jboss2.dir}" />
      <param name="assembly.name" value="template-stateless" />
    </antcall>
  </target>
  <target name="package-3parts" description="DEPRECATED: Package Nuxeo-EP in three parts">
    <antcall target="package">
      <param name="assembly.name" value="nuxeo-core" />
    </antcall>
    <antcall target="package">
      <param name="assembly.name" value="nuxeo-indexing" />
    </antcall>
    <antcall target="package">
      <param name="assembly.name" value="nuxeo-webplatform" />
    </antcall>
  </target>
  <target name="package" depends="setproperties,package-unix,package-windows" description="Package Nuxeo-EP" />
  <target name="package-unix" if="osfamily-unix">
    <echo message="assembly NAME ${assembly.name}" />
    <exec executable="mvn" failonerror="true">
      <arg value="clean" />
      <arg value="package" />
      <arg value="-Dmaven.test.skip=true" />
      <arg value="-f" />
      <arg value="${template.ear.root}/pom.xml" />
      <arg value="-Dtemplate.ear.assembly=${assembly.name}" />
      <arg value="${mvn.opts}" />
    </exec>
    <echo message="Packaged ${ant.project.name} into ${template.ear.build}" />
  </target>
  <target name="package-windows" if="osfamily-windows">
    <exec executable="cmd" failonerror="true">
      <arg value="/c" />
      <arg value="mvn.bat" />
      <arg value="clean" />
      <arg value="package" />
      <arg value="-Dmaven.test.skip=true" />
      <arg value="-f" />
      <arg value="${template.ear.root}/pom.xml" />
      <arg value="-Dtemplate.ear.assembly=${assembly.name}" />
      <arg value="${mvn.opts}" />
    </exec>
  </target>
  <target name="install" depends="install-unix,install-windows" description="Run mvn install" />
  <target name="install-unix" if="osfamily-unix">
    <exec executable="mvn" failonerror="true">
      <arg value="clean" />
      <arg value="install" />
      <arg value="-Dmaven.test.skip=true" />
      <arg value="${mvn.opts}" />
    </exec>
  </target>
  <target name="install-windows" if="osfamily-windows">
    <exec executable="cmd" failonerror="true">
      <arg value="/c" />
      <arg value="mvn.bat" />
      <arg value="clean" />
      <arg value="install" />
      <arg value="-Dmaven.test.skip=true" />
      <arg value="${mvn.opts}" />
    </exec>
  </target>

  <target name="web" description="Copy web files to a live JBoss">
    <copy todir="${deploy.dir}/nuxeo.ear/nuxeo.war">
      <fileset dir="${basedir}/template-platform/src/main/resources/nuxeo.war/" />
    </copy>
  </target>

  <target name="rename">
    <delete dir="${build.dir}/${nuxeo.ear}" failonerror="false" />
    <move file="${build.dir}/template.ear" tofile="${build.dir}/${nuxeo.ear}" />
  </target>

  <target name="copy-lib">
    <delete failonerror="false">
      <fileset dir="${deploy.lib.dir}/">
        <include name="nuxeo*.jar" />
      </fileset>
    </delete>
    <copy todir="${deploy.lib.dir}/" failonerror="true">
      <fileset dir="${build.dir}/${build.lib.dir}/" />
    </copy>
  </target>

  <target name="copy-ldap-pg" description="Copy template on LDAP and Postgres">
    <antcall target="copy">
      <param name="assembly.name" value="template-ldap-pg" />
    </antcall>
  </target>
  <target name="copy-2parts" description="Copy Nuxeo-EP in two parts">
    <antcall target="copy">
      <param name="jboss.home" value="${jboss1.dir}" />
      <param name="assembly.name" value="template-platform-stateful" />
    </antcall>
    <antcall target="copy">
      <param name="jboss.home" value="${jboss2.dir}" />
      <param name="assembly.name" value="template-web-stateless" />
    </antcall>
  </target>
  <target name="copy-3parts" description="DEPRECATED: Copy Nuxeo-EP in three parts">
    <antcall target="copy">
      <param name="jboss.home" value="${jboss1.dir}" />
      <param name="assembly.name" value="nuxeo-core" />
    </antcall>
    <antcall target="copy">
      <param name="jboss.home" value="${jboss2.dir}" />
      <param name="assembly.name" value="nuxeo-indexing" />
    </antcall>
    <antcall target="copy">
      <param name="jboss.home" value="${jboss3.dir}" />
      <param name="assembly.name" value="nuxeo-webplatform" />
    </antcall>
  </target>
  <target name="copy" depends="delete-ear,copy-ear,copy-lib" description="Replace ear and copy libs to jboss" />
  <target name="delete-ear" depends="setproperties">
    <delete dir="${jboss.nuxeo.ear}" failonerror="false" />
  </target>
  <target name="copy-ear" depends="setproperties">
    <mkdir dir="${jboss.nuxeo.ear}" />
    <copy todir="${jboss.nuxeo.ear}">
      <fileset dir="${template.ear.build}" />
    </copy>
  </target>

  <target name="copy-jars">
    <copy todir="${deploy.dir}/${nuxeo.ear}/plugins" overwrite="true" flatten="true">
      <fileset dir="${basedir}">
        <include name="*/target/*.jar" />
        <exclude name="*/target/*-sources.jar" />
      </fileset>
    </copy>
  </target>

</project>


          

Example 53.2. build.xml sample


53.5. Recommended multi-machine packagings

53.5.1. Bi-machine: stateful/stateless

53.5.1.1. Introduction

Stateful/Stateless packaging gives a good solution to a lot of production requirements. Principle is to split Nuxeo in two parts: one that contains the core and every services that persist data, and another that provides web services. Stateless part may be duplicated.

53.5.1.2. Packaging

Bi-machine packaging is done by two assembly descriptors, each one building an EAR to deploy on a separate server.

To build your own bi-machine packaging, copy the template-project structure. Copy and adapt Ant, Maven and descriptor files. Then, configure artifactSet and fileSet that will deploy your project's artifacts into the plugin directory and the wanted resources to replace those deployed by default.

              <!-- This is a template assembly file that generates a "stateful" part of Nuxeo-EP server -->

<assembly>

  <!-- RESOURCES -->
  <assemble>
    <set>resources</set>
    <outputFile>/</outputFile>
  </assemble>
  <zipEntrySet id="resources">
    <artifact>
      org.nuxeo.ecm.platform:nuxeo-platform-ear:${nuxeo.platform.version}:zip:resources-platform-stateful
    </artifact>
  </zipEntrySet>

  <!-- ARTIFACTS -->
  <assemble>
    <outputFile>system</outputFile>
    <set>system</set>
  </assemble>
  <artifactSet id="system">
    <import>**</import>
    <includeDependencies>true</includeDependencies>
    <includes>
      <artifact group="org.nuxeo.*" category="runtime,jboss4"
        includeDependsOnCategory="false" />
      <artifact group="org.nuxeo.*" category="core,stateful" />
      <!-- add here core and stateful nuxeo-addons -->
    </includes>
    <excludes>
      <artifact group="!org.nuxeo*" />
      <artifact group="org.nuxeo.common" />
      <artifact name="nuxeo-runtime-jboss-extensions" />

      <artifact name="nuxeo-platform-webapp" />
      <artifact name="nuxeo-platform-webapp-core" />

      <artifact name="nuxeo-platform-audit-facade" />
      <artifact name="nuxeo-platform-placeful-facade" />
      <artifact name="nuxeo-platform-search-compass-plugin" />
      <artifact name="nuxeo-platform-ear" />
      <artifact group="org.nuxeo.projects.template" />
    </excludes>
  </artifactSet>

  <assemble>
    <outputFile>system</outputFile>
    <unpack>true</unpack>
    <unpackInNewDirectory>true</unpackInNewDirectory>
    <set>nuxeo-platform-unpacked</set>
  </assemble>
  <artifactSet id="nuxeo-platform-unpacked">
    <import>**</import>
    <includes>
      <artifact name="nuxeo-platform-audit-facade" />
      <artifact name="nuxeo-platform-placeful-facade" />
      <artifact name="nuxeo-platform-search-compass-plugin" />
    </includes>
  </artifactSet>

  <!-- third party libraries embedded in the ear -->
  <assemble>
    <outputFile>lib</outputFile>
    <set>nuxeo-fixed-libs</set>
  </assemble>
  <artifactSet id="nuxeo-fixed-libs">
    <artifacts>
      <artifact group="org.freemarker" name="freemarker" version="2.3.11" />
      <artifact group="org.osgi" name="osgi-core" version="4.1" />
      <artifact group="commons-collections" name="commons-collections"
        version="3.1" />
      <artifact group="commons-io" name="commons-io" version="1.2" />
      <artifact group="commons-lang" name="commons-lang" version="2.2" />
      <artifact group="commons-fileupload" name="commons-fileupload"
        version="1.1.1" />
      <artifact group="cssparser" name="cssparser" version="0.9.4-fix" />
      <artifact group="net.sf.ehcache" name="ehcache" version="1.2.3" />
      <artifact group="net.sf.ezmorph" name="ezmorph" version="0.9" />
      <artifact group="org.hibernate" name="hibernate" version="3.2.0.ga" />
      <artifact group="org.hibernate" name="hibernate-annotations"
        version="3.2.0.ga" />
      <artifact group="org.hibernate" name="hibernate-entitymanager"
        version="3.2.0.ga" />
      <artifact group="jboss" name="jboss-cache-jdk50" version="1.4.0.SP1" />
      <artifact group="org.jboss.seam" name="jboss-seam" version="1.1.5.NX3" />
      <artifact group="jboss" name="jbpm" version="3.1.2" />
      <artifact group="jboss" name="jgroups" version="2.2.9" />
      <artifact group="net.sf.json-lib" name="json-lib" version="0.9" />
      <artifact group="org.apache.lucene" name="lucene-core" version="2.0.0" />
      <artifact group="net.sf.opencsv" name="opencsv" version="1.7" />
      <artifact group="org.slf4j" name="slf4j-api" version="1.3.0" />
      <artifact group="org.slf4j" name="slf4j-log4j12" version="1.3.0" />
      <artifact group="org.apache.myfaces.tomahawk" name="tomahawk"
        version="1.1.5" />
      <artifact group="org.apache.myfaces.tomahawk" name="tomahawk-sandbox"
        version="1.1.5" />
      <artifact group="org.apache.myfaces.trinidad" name="trinidad-api"
        version="1.0.1-incubating-NXEP51M2" />
      <artifact group="org.apache.myfaces.trinidad" name="trinidad-impl"
        version="1.0.1-incubating-NXEP51M2" />
      <artifact group="org.apache.directory.server"
        name="apacheds-protocol-shared" version="1.5.1" />
      <artifact group="org.apache.directory.shared" name="shared-ldap"
        version="0.9.7" />
      <artifact group="com.sun.facelets" name="jsf-facelets" version="1.1.11" />
      <artifact group="org.nuxeo.ecm.platform" name="nuxeo-jbossws-wrapper"
        version="4.0.5.GA" />
    </artifacts>
  </artifactSet>

  <!-- template project's artifacts -->
  <assemble>
    <outputFile>plugins</outputFile>
    <set>template-plugins</set>
  </assemble>
  <artifactSet id="template-plugins">
    <import>**</import>
    <includeDependencies>true</includeDependencies>
    <includes>
        <artifact name="template-core" />
        <artifact name="template-stateful-services" />
    </includes>
    <excludes>
      <artifact group="!org.nuxeo.projects.template" />
    </excludes>
  </artifactSet>

  <!-- template project's resources -->
  <assemble>
    <outputFile>/</outputFile>
    <set>template-resources</set>
  </assemble>
  <fileSet id="template-resources">
    <directory>src/main/resources_template_common</directory>
    <excludes>
      <exclude>README.txt</exclude>
    </excludes>
  </fileSet>
  <assemble>
    <outputFile>/</outputFile>
    <set>template-resources-stateful</set>
  </assemble>
  <fileSet id="template-resources-stateful">
    <directory>src/main/resources_template_stateful</directory>
  </fileSet>

</assembly>

          

Example 53.3. Sample of customized assembly for a stateful EAR


              <!-- This is a template assembly file that generates a "stateless" part of Nuxeo-EP server -->

<assembly>

  <!-- RESOURCES -->
  <assemble>
    <set>resources</set>
    <outputFile>/</outputFile>
  </assemble>
  <zipEntrySet id="resources">
    <artifact>
      org.nuxeo.ecm.platform:nuxeo-platform-ear:${nuxeo.platform.version}:zip:resources-web-stateless
    </artifact>
  </zipEntrySet>

  <!-- ARTIFACTS -->
  <assemble>
    <outputFile>/</outputFile>
    <set>root-artifacts</set>
  </assemble>
  <artifactSet id="root-artifacts">
    <import>**</import>
    <includeDependencies>false</includeDependencies>
    <includes>
      <artifact name="nuxeo-platform-webapp" />
      <artifact name="nuxeo-platform-webapp-core" />
    </includes>
  </artifactSet>

  <assemble>
    <outputFile>system</outputFile>
    <set>system</set>
  </assemble>
  <artifactSet id="system">
    <import>**</import>
    <includeDependencies>true</includeDependencies>
    <includes>
      <artifact group="org.nuxeo.*" category="runtime,jboss4"
        includeDependsOnCategory="false" />
      <artifact group="org.nuxeo.*" category="stateless" />
      <!-- add here web and stateless nuxeo-addons -->
    </includes>
    <excludes>
      <artifact group="!org.nuxeo*" />
      <artifact group="org.nuxeo.common" />
      <artifact name="nuxeo-runtime-jboss-extensions" />

      <artifact name="nuxeo-platform-webapp" />
      <artifact name="nuxeo-platform-webapp-core" />
      <artifact name="nuxeo-platform-ear" />
      <artifact name="nuxeo-apt-extensions" />
      <artifact group="org.nuxeo.projects.template" />
    </excludes>
  </artifactSet>

  <!-- third party libraries embedded in the ear -->
  <assemble>
    <outputFile>lib</outputFile>
    <set>nuxeo-fixed-libs</set>
  </assemble>
  <artifactSet id="nuxeo-fixed-libs">
    <artifacts>
      <artifact group="org.freemarker" name="freemarker" version="2.3.11" />
      <artifact group="org.osgi" name="osgi-core" version="4.1" />
      <artifact group="commons-collections" name="commons-collections"
        version="3.1" />
      <artifact group="commons-io" name="commons-io" version="1.2" />
      <artifact group="commons-lang" name="commons-lang" version="2.2" />
      <artifact group="commons-fileupload" name="commons-fileupload"
        version="1.1.1" />
      <artifact group="cssparser" name="cssparser" version="0.9.4-fix" />
      <artifact group="net.sf.ehcache" name="ehcache" version="1.2.3" />
      <artifact group="net.sf.ezmorph" name="ezmorph" version="0.9" />
      <artifact group="org.hibernate" name="hibernate" version="3.2.0.ga" />
      <artifact group="org.hibernate" name="hibernate-annotations"
        version="3.2.0.ga" />
      <artifact group="org.hibernate" name="hibernate-entitymanager"
        version="3.2.0.ga" />
      <artifact group="jboss" name="jboss-cache-jdk50" version="1.4.0.SP1" />
      <artifact group="org.jboss.seam" name="jboss-seam" version="1.1.5.NX3" />
      <artifact group="jboss" name="jbpm" version="3.1.2" />
      <artifact group="jboss" name="jgroups" version="2.2.9" />
      <artifact group="net.sf.json-lib" name="json-lib" version="0.9" />
      <artifact group="org.apache.lucene" name="lucene-core" version="2.0.0" />
      <artifact group="net.sf.opencsv" name="opencsv" version="1.7" />
      <artifact group="org.slf4j" name="slf4j-api" version="1.3.0" />
      <artifact group="org.slf4j" name="slf4j-log4j12" version="1.3.0" />
      <artifact group="org.apache.myfaces.tomahawk" name="tomahawk"
        version="1.1.5" />
      <artifact group="org.apache.myfaces.tomahawk" name="tomahawk-sandbox"
        version="1.1.5" />
      <artifact group="org.apache.myfaces.trinidad" name="trinidad-api"
        version="1.0.1-incubating-NXEP51M2" />
      <artifact group="org.apache.myfaces.trinidad" name="trinidad-impl"
        version="1.0.1-incubating-NXEP51M2" />
      <artifact group="org.apache.directory.server"
        name="apacheds-protocol-shared" version="1.5.1" />
      <artifact group="org.apache.directory.shared" name="shared-ldap"
        version="0.9.7" />
      <artifact group="com.sun.facelets" name="jsf-facelets" version="1.1.11" />
      <artifact group="org.nuxeo.ecm.platform" name="nuxeo-jbossws-wrapper"
        version="4.0.5.GA" />
    </artifacts>
  </artifactSet>

  <!-- template project's artifacts -->
  <assemble>
    <outputFile>plugins</outputFile>
    <set>template-plugins</set>
  </assemble>
  <artifactSet id="template-plugins">
    <import>**</import>
    <includeDependencies>true</includeDependencies>
    <includes>
        <artifact name="template-web" />
        <artifact name="template-stateless-services" />
    </includes>
    <excludes>
      <artifact group="!org.nuxeo.projects.template" />
    </excludes>
  </artifactSet>

  <!-- template project's resources -->
  <assemble>
    <outputFile>/</outputFile>
    <set>template-resources</set>
  </assemble>
  <fileSet id="template-resources">
    <directory>src/main/resources_template_common</directory>
    <excludes>
      <exclude>README.txt</exclude>
    </excludes>
  </fileSet>
  <assemble>
    <outputFile>/</outputFile>
    <set>template-resources-stateless</set>
  </assemble>
  <fileSet id="template-resources-stateless">
    <directory>src/main/resources_template_stateless</directory>
  </fileSet>

</assembly>

          

Example 53.4. Sample of customized assembly for a stateless EAR


53.5.1.3. Network configuration

Stateful is identified in configuration files as nxplatformserver and nxjmsserver. Stateless is known as nxwebserver. You can set this in your hosts files.

If you deploy multiple stateless servers, the unique (for now it cannot be duplicated) stateful server only need to know one stateless server. Stateless servers do not need to communicate between each other.

Note

There is misconfiguration in Nuxeo EP 5.1.6 and 5.2.M3 (http://jira.nuxeo.org/browse/NXP-2838). Replace in nuxeo-web-stateless.ear/datasources/core-events-ds.xml

java.naming.provider.url=${jboss.bind.address}:1099

with

java.naming.provider.url=nxjmsserver:1099