It's now easy to assemble a special purpose server as part of your maven build. As an example we'll show how to take a fairly large existing application, the liferay 4.4.1 portal, and construct a custom server that runs it. We'll use the maven archetypes to construct most of the maven projects.
For a completed example see the roller plugins at https://svn.apache.org/repos/asf/geronimo/plugins/roller/trunk
Notes:
- The archetypes are not included in geronimo 2.1 but the snapshots should be readily available
- Some of this would not be necessary given a project built with maven in the first place
- As of writing, the server doesn't start. Hopefully we'll figure out why soon.
Process overview.
- Get the necessary artifacts into the local maven repo if they are not already available
- Construct the base maven project
- Use the maven war archetype to build a project to modify the artifacts as necessary using for instance the maven-war-plugin overlay to remove dependencies from WEB-INF/lib so copies in geronimo's repository can be used
- Use the geronimo-module-archetype to build projects to build plugins for the components
- Use the geronimo-assembly-archetype to build a project to assemble the server.
Preparation – find the artifacts
Liferay does not publish its code to any maven repo. Start by downloading:
wget http://downloads.sourceforge.net/lportal/liferay-portal-4.4.1.war?modtime=1202491348&big_mirror=1 wget http://downloads.sourceforge.net/lportal/liferay-portal-dependencies-4.4.1.zip?modtime=1202491352&big_mirror=1
unpacking:
unzip liferay-portal-dependencies-4.4.1.zip
and installing to your local repo:
mvn install:install-file -Dfile=liferay-portal-4.4.1.war -DgroupId=com.liferay -DartifactId=liferay-portal -Dversion=4.4.1 -Dpackaging=war mvn install:install-file -Dfile=liferay-portal-dependencies-4.4.1/portal-kernel.jar -DgroupId=com.liferay -DartifactId=portal-kernel -Dversion=4.4.1 -Dpackaging=jar mvn install:install-file -Dfile=liferay-portal-dependencies-4.4.1/portal-service.jar -DgroupId=com.liferay -DartifactId=portal-service -Dversion=4.4.1 -Dpackaging=jar
Set up a parent maven project
I can't find an archetype to create an empty "parent" project. So...
Find a suitable location and run
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.0 -DgroupId=org.apache.geronimo.plugins -DartifactId=liferay-parent -Dversion=1.0-SNAPSHOT cd liferay-parent rm -rf src
Edit the pom.xml to change the packaging to pom and remove the dependency.
Repackage the liferay war
(not done yet)
Build a database plugin
in liferay-parent run
mvn archetype:create -DarchetypeGroupId=org.apache.geronimo.buildsupport -DarchetypeArtifactId=geronimo-module-archetype -DarchetypeVersion=2.2-SNAPSHOT -DgroupId=org.apache.geronimo.plugins -DartifactId=liferay-derby -Dversion=1.0-SNAPSHOT
Change the plan so it looks like this:
<?xml version="1.0" encoding="UTF-8"?> <connector xmlns="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2"> <resourceadapter> <outbound-resourceadapter> <connection-definition> <connectionfactory-interface>javax.sql.DataSource</connectionfactory-interface> <connectiondefinition-instance> <name>jdbc/LiferayPool</name> <config-property-setting name="Password">liferay</config-property-setting> <config-property-setting name="UserName">liferay</config-property-setting> <config-property-setting name="DatabaseName">liferay</config-property-setting> <connectionmanager> <local-transaction/> <single-pool> <max-size>10</max-size> <min-size>0</min-size> <match-one/> </single-pool> </connectionmanager> </connectiondefinition-instance> <!-- Leave until we figure out if non-jta datasource is needed --> <!-- <connectiondefinition-instance> <name>jdbc/NoTxrollerdb</name> <config-property-setting name="Password">roller</config-property-setting> <config-property-setting name="UserName">roller</config-property-setting> <config-property-setting name="DatabaseName">roller</config-property-setting> <connectionmanager> <no-transaction/> <single-pool> <max-size>10</max-size> <min-size>0</min-size> <match-one/> </single-pool> </connectionmanager> </connectiondefinition-instance> --> </connection-definition> </outbound-resourceadapter> </resourceadapter> </connector>
and modify the pom setting the geronimoVersion to 2.1 and with
<dependencies> <!-- if you are deploying a jee application, use scope provided --> <dependency> <groupId>org.tranql</groupId> <artifactId>tranql-connector-derby-embed-local</artifactId> <version>1.4</version> <type>rar</type> <scope>provided</scope> </dependency> <!-- other dependencies will normally end up as dependencies in the plan and geronimo-plugin.xml --> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>system-database</artifactId> <type>car</type> <version>${geronimoVersion}</version> </dependency> <!-- include dependencies on all deployer modules needed, with scope provided --> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>connector-deployer</artifactId> <type>car</type> <version>${geronimoVersion}</version> </dependency> </dependencies>
and
<plugin> <groupId>org.apache.geronimo.buildsupport</groupId> <artifactId>car-maven-plugin</artifactId> <configuration> <deploymentConfigs> <!-- gbean deployer is default. For jee apps include all deployers your app needs, see properties --> <deploymentConfig>${gbeanDeployer}</deploymentConfig> <deploymentConfig>${connectorDeployer}</deploymentConfig> </deploymentConfigs> <!-- if you are deploying a jee app specify it here --> <module> <groupId>org.tranql</groupId> <artifactId>tranql-connector-derby-embed-local</artifactId> <type>rar</type> </module> <!-- Normally you can use the maven dependencies unaltered. If you need to specify import scope you can list the dependencies here as you want them in the plan.xml --> <useMavenDependencies> <value>true</value> <includeVersion>true</includeVersion> </useMavenDependencies> <!-- the instance sets up most of the optional geronimo-plugin.xml content --> <instance> <plugin-artifact> </plugin-artifact> </instance> </configuration> </plugin>
Build the liferay war plugin
run
mvn archetype:create -DarchetypeGroupId=org.apache.geronimo.buildsupport -DarchetypeArtifactId=geronimo-module-archetype -DarchetypeVersion=2.2-SNAPSHOT -DgroupId=org.apache.geronimo.plugins -DartifactId=liferay-jetty -Dversion=1.0-SNAPSHOT
Edit the plan so it looks like:
NOTE: this is derived from the liferay plan at and is under the liferay (MIT) license
<?xml version="1.0"?> <web-app xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1"> <environment> <inverse-classloading/> </environment> <context-root>${LiferayContextPath}</context-root> <security-realm-name>PortalRealm</security-realm-name> <security use-context-handler="false" xmlns="http://geronimo.apache.org/xml/ns/security-2.0"> <!-- requires security to be set up for default subject <default-subject> <realm>PortalRealm</realm> <id>default</id> </default-subject> --> <role-mappings> <role role-name="users"> <principal class="com.liferay.portal.security.jaas.PortalRole" name="users" /> </role> </role-mappings> </security> <gbean name="CredentialStore" class="org.apache.geronimo.security.credentialstore.SimpleCredentialStoreImpl"> <xml-attribute name="credentialStore"> <credential-store xmlns="http://geronimo.apache.org/xml/ns/credentialstore-1.0"> <realm name="PortalRealm"> <subject> <id>default</id> <!-- you will have so set up the backing store appropriately --> <credential> <type>org.apache.geronimo.security.credentialstore.NameCallbackHandler</type> <value>anonymous</value> </credential> <credential> <type>org.apache.geronimo.security.credentialstore.PasswordCallbackHandler</type> <value>anonymous</value> </credential> </subject> </realm> </credential-store> </xml-attribute> <dependency> <name>PortalRealm</name> </dependency> </gbean> <gbean name="PortalRealm" class="org.apache.geronimo.security.realm.GenericSecurityRealm"> <attribute name="realmName">PortalRealm</attribute> <reference name="ServerInfo"> <name>ServerInfo</name> </reference> <xml-reference name="LoginModuleConfiguration"> <log:login-config xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0"> <log:login-module control-flag="REQUIRED" wrap-principals="false"> <log:login-domain-name>PortalDomain</log:login-domain-name> <log:login-module-class>com.liferay.portal.security.jaas.ext.tomcat.PortalLoginModule</log:login-module-class> </log:login-module> </log:login-config> </xml-reference> </gbean> </web-app>
and the pom to have geronimoVersion 2.1, liferayVersion 4.4.1 and include
<dependencies> <!-- if you are deploying a jee application, use scope provided --> <!-- other dependencies will normally end up as dependencies in the plan and geronimo-plugin.xml --> <!-- include dependencies on all deployer modules needed, with scope provided --> <dependency> <groupId>com.liferay</groupId> <artifactId>liferay-portal</artifactId> <version>${liferayVersion}</version> <type>war</type> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>javamail</artifactId> <type>car</type> <version>${geronimoVersion}</version> </dependency> <dependency> <groupId>org.apache.geronimo.plugins</groupId> <artifactId>liferay-derby</artifactId> <type>car</type> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>portlet-api</groupId> <artifactId>portlet-api</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.liferay</groupId> <artifactId>portal-kernel</artifactId> <version>${liferayVersion}</version> </dependency> <dependency> <groupId>com.liferay</groupId> <artifactId>portal-service</artifactId> <version>${liferayVersion}</version> </dependency> <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.apache.geronimo.framework</groupId> <artifactId>geronimo-gbean-deployer</artifactId> <type>car</type> <version>${geronimoVersion}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>jetty6-deployer</artifactId> <type>car</type> <version>${geronimoVersion}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>jasper-deployer</artifactId> <type>car</type> <version>${geronimoVersion}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.geronimo.configs</groupId> <artifactId>persistence-jpa10-deployer</artifactId> <type>car</type> <version>${geronimoVersion}</version> <scope>provided</scope> </dependency> </dependencies>
and
<plugin> <groupId>org.apache.geronimo.buildsupport</groupId> <artifactId>car-maven-plugin</artifactId> <configuration> <deploymentConfigs> <!-- gbean deployer is default. For jee apps include all deployers your app needs, see properties --> <deploymentConfig>${gbeanDeployer}</deploymentConfig> <deploymentConfig>${j2eeDeployer}</deploymentConfig> <deploymentConfig>${jetty6Deployer}</deploymentConfig> <deploymentConfig>${jasperDeployer}</deploymentConfig> <!--<deploymentConfig>${jpaDeployer}</deploymentConfig>--> </deploymentConfigs> <!-- if you are deploying a jee app specify it here --> <module> <groupId>com.liferay</groupId> <artifactId>liferay-portal</artifactId> <version>${liferayVersion}</version> <type>war</type> </module> <!-- Normally you can use the maven dependencies unaltered. If you need to specify import scope you can list the dependencies here as you want them in the plan.xml --> <useMavenDependencies> <value>true</value> <includeVersion>true</includeVersion> </useMavenDependencies> <!-- the instance sets up most of the optional geronimo-plugin.xml content --> <instance> <plugin-artifact> <!-- extract stuff from the car to the specified location (good for config info --> <!--<copy-file relative-to="server" dest-dir="var/roller-data">themes</copy-file>--> <!-- content that should go into var/config/config.xml for module customization --> <!-- note the variable ${RollerContextPath} which is further specified in var/config/config-substitutions.properties --> <config-xml-content server="default"> <gbean name="org.apache.geronimo.plugins/liferay-jetty/${liferayPluginVersion}/car"> <attribute name="contextPath">${LiferayContextPath}</attribute> </gbean> </config-xml-content> <!-- a user-tweakable variable to go into var/config/config-substitutions.properties --> <config-substitution key="LiferayContextPath">/liferay</config-substitution> </plugin-artifact> </instance> </configuration> </plugin>
Build an assembly
In liferay-parent run
mvn archetype:create -DarchetypeGroupId=org.apache.geronimo.buildsupport -DarchetypeArtifactId=geronimo-assembly-archetype -DarchetypeVersion=2.2-SNAPSHOT -DgroupId=org.apache.geronimo.plugins -DartifactId=geronimo-jetty-liferay -Dversion=1.0-SNAPSHOT
Edit the geronimo-jetty-liferay pom to set geronimoVersion to 2.1 and include the top level modules you want in your server (console-jetty is optional)
NOTE: do not remove the boilerplate!
<!-- List the plugins you want in your server --> <dependency> <groupId>org.apache.geronimo.plugins</groupId> <artifactId>liferay-jetty</artifactId> <version>1.0-SNAPSHOT</version> <type>car</type> </dependency> <dependency> <groupId>org.apache.geronimo.plugins</groupId> <artifactId>console-jetty</artifactId> <version>${geronimoVersion}</version> <type>car</type> </dependency>
The packaged servers will be in geronimo-jetty-liferay/target and in your local maven repo. Unpack and run:
tar xzf geronimo-jetty-liferay-1.0-SNAPSHOT-bin.tar.gz cd geronimo-jetty-liferay-1.0-SNAPSHOT ./bin/gsh geronimo/start-server
As of writing this results in an OOM permGen error.