Search

November 10, 2013

Liferay 6.2 Portal on JBoss 7.2.0

Liferay is a JSR-286 (also known as Portal 2.0) compliant portal (and a whole lot more). Since I am in the market for a portal server for an upcoming project, I figured I needed to check Liferay out. The folks at Liferay have bundled version 6.2 with a number of different open-source application servers, including JBoss 7.1.1, but what fun would it be to simply download a bundle? Liferay is also available as a war download for deployment on existing (and closed-source) application servers. So let’s see if we can get Liferay running on the JBoss 7.2.0 server we built previously.

We will need the Liferay war (liferay-portal-6.2.0-ce-ga1-20131101192857659.war) and the Liferay dependencies package (liferay-portal-dependencies-6.2.0-ce-ga1-20131101192857659.zip) available from the Additional Files tab on the Liferay download page. I will be using a PostgreSQL database as well, so I’ll need the PostgreSQL JDBC driver (postgresql-9.3-1100.jdbc4.jar) as well. Feel free to substitute the driver for your favorite DBMS.

First, Liferay will be using the directory above the JBoss installation as a installation directory, so let’s create that directory and extract JBoss:

$ mkdir liferay
$ cd liferay
$ unzip -q ../jboss-as-7.2.0.Final.zip

Liferay requires that you install the dependencies at the application server level; for JBoss that means creating a module for Liferay. The Liferay installation instructions bundle the JDBC driver with the Liferay module. That feels wrong to me, so we’ll create a separate module for the JDBC driver. In this case I am using PostgreSQL, but this can easily be adapted for any driver.

$ cd jboss-as-7.2.0.Final/modules
$ mkdir -p org/postgresql/main
$ cp ../../../postgresql-9.3-1100.jdbc4.jar org/postgresql/main/
$ mkdir -p com/liferay/portal/main
$ cd com/liferay/portal/main
$ unzip -q \
../../../../../../../liferay-portal-dependencies-6.2.0-ce-ga1-20131101192857659.zip
$ mv liferay-portal-dependencies-6.2.0-ce-ga1/* ./
$ rmdir liferay-portal-dependencies-6.2.0-ce-ga1
$ cd ../../../../../..

Next you’ll need to create the two module.xml files. First, for PostgreSQL create the file jboss-as-7.2.0.Final/modules/org/postgresql/main/module.xml with contents:

<?xml version="1.0"?>
<module xmlns="urn:jboss:module:1.0" name="org.postgresql">
    <resources>
       <resource-root path="postgresql-9.3-1100.jdbc4.jar" />
    </resources>
    <dependencies>
       <module name="javax.api" />
       <module name="javax.transaction.api" />
    </dependencies>
</module>

Next for the Liferay module, note that we will be adding a dependency on the PostgreSQL module. The file is jboss-as-7.2.0.Final/modules/com/liferay/portal/main/module.xml:

<?xml version="1.0"?>
<module xmlns="urn:jboss:module:1.0" name="com.liferay.portal">
    <resources>
       <resource-root path="hsql.jar" />
       <resource-root path="portal-service.jar" />
       <resource-root path="portlet.jar" />
    </resources>
    <dependencies>
       <module name="javax.api" />
       <module name="javax.mail.api" />
       <module name="javax.servlet.api" />
       <module name="javax.servlet.jsp.api" />
       <module name="javax.transaction.api" />
       <module name="org.postgresql" />
    </dependencies>
</module>

While we are mucking around with the modules, it seems like a good time to make the Liferay-recommended changes to the system modules of JBoss. Open up jboss-as-7.2.0.Final/modules/system/layers/base/sun/jdk/main/module.xml and add the following <path> tags under the existing <paths> tag:

<path name="com/sun/crypto" />
<path name="com/sun/org/apache/xml/internal/resolver" />
<path name="com/sun/org/apache/xml/internal/resolver/tools" />

The Liferay documentation at this point indicates there are some steps to do to work around JBPAPP6-932. However, that bug only affects environments using the IBM JDK, which I am not planning on doing. Further, I am using JBoss 7.2.0 and the patch is for 7.1.x; it is not clear if the bug exists in 7.2.0 or if the patch is appropriate for 7.2.0. The upshot is I am skipping that step but you may want to consider if you need it.

Next up are some edits to the JBoss configuration file, standalone-full.xml. (I typically configure my servers to use standalone-full.xml instead of just standalone.xml, YMMV.) We’ll start by adding some system properties following the <extensions> tag:

<system-properties>
  <property name="org.apache.catalina.connector.URI_ENCODING"
    value="UTF-8"/>
  <property
    name="org.apache.catalina.connector.USE_BODY_ENCODING_FOR_QUERY_STRING"
    value="true"/>
</system-properties>

We also need a to set a timeout for the deployment scanner by adding the deployment-timeout attribute to the existing deployment-scanner tag:

<subsystem xmlns="urn:jboss:domain:deployment-scanner:1.1">
  <deployment-scanner path="deployments" relative-to="jboss.server.base.dir"
    scan-interval="5000" deployment-timeout="240"/>
</subsystem>

Next we need to configure the Liferay login system. Add a <security-domain> tag to the existing <security-domains> tag in the existing <subsystem xmlns="urn:jboss:domain:security:1.2"> tag

<security-domain name="PortalRealm">
  <authentication>
    <login-module code="com.liferay.portal.security.jaas.PortalLoginModule"
      flag="required"/>
  </authentication>
</security-domain>

We will be replacing the standard JBoss welcome application with Liferay later, so we need to set the enable-welcome-root attribute to false on the existing <virtual-server> tag. We will also set the JSP mode to development by adding <configuration> and <jsp-configuration> tags in the web <subsystem>:

<subsystem xmlns="urn:jboss:domain:web:1.4" default-virtual-server="default-host" native="false">
  <configuration>
    <jsp-configuration development="true"/>
  </configuration>
  <connector name="http" protocol="HTTP/1.1" scheme="http"
    socket-binding="http"/>
  <virtual-server name="default-host" enable-welcome-root="false">
    <alias name="localhost"/>
    <alias name="example.com"/>
  </virtual-server>
</subsystem>

While we are here, let’s create a mail session for Liferay to use by modifying the existing <mail-session> tag in the <subsystem xmlns="urn:jboss:domain:mail:1.0"> tag:

<subsystem xmlns="urn:jboss:domain:mail:1.0">
  <mail-session
    jndi-name="java:/mail/MailSession"
    from="MAIL_ADDRESS">
    <smtp-server outbound-socket-binding-ref="mail-smtp">
      <login name="MAIL_USER" password="MAIL_PASSWORD"/>
    </smtp-server>
  </mail-session>
</subsystem>

We also need to tell JBoss that the socket binding mail-smtp should talk to the right mail server. Change the host attribute of the existing <remote-destination> tag for the mail-smtp socket binding:

<outbound-socket-binding name="mail-smtp">
  <remote-destination host="MAIL_HOST" port="25"/>
</outbound-socket-binding>

Of course, replace the MAIL_ADDRESS, MAIL_HOST, MAIL_USER and MAIL_PASSWORD tokens in the above with the proper values for your environment.

Finally we create a JDBC data source for Liferay to use in two steps. First, add a <datasource> tag to the existing <datasources> in the <subsystem xmlns="urn:jboss:domain:datasources:1.1"> subsystem:

<datasource jta="true" jndi-name="java:/jdbc/LiferayPool"
  pool-name="LiferayPool" enabled="true" use-java-context="true" use-ccm="true">
  <connection-url>jdbc:postgresql://DB_SERVER:5432/DB_DATABASE</connection-url>
  <driver>postgresql</driver>
  <pool>
    <min-pool-size>1</min-pool-size>
    <max-pool-size>20</max-pool-size>
    <prefill>true</prefill>
  </pool>
  <security>
    <user-name>DB_USERNAME</user-name>
    <password>DB_PASSWORD</password>
  </security>
    <validation>
        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker"/>
        <validate-on-match>false</validate-on-match>
        <background-validation>false</background-validation>
    </validation>
    <statement>
        <prepared-statement-cache-size>16</prepared-statement-cache-size>
        <share-prepared-statements>true</share-prepared-statements>
    </statement>
</datasource>

Then add a <driver> tag to the existing <drivers> tag within the <datasources> tag:

<driver name="postgresql" module="org.postgresql">
  <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>

Again, replace the DB_SERVER, DB_DATABASE, DB_USERNAME and DB_PASSWORD tokens with the correct values for your environment. If you are using a different database server, you’ll have to change the <connection-url>, the class-name for the <validation-connection-checker> and the <xa-datasource-class> as well, but you knew that already. For the database, use an empty schema and Liferay will populate it when it first starts.

Liferay requires certain system properties to be set when JBoss is started. Use your favorite mechanism to ensure the following values are set:

-Dfile.encoding=UTF-8
-Djava.net.preferIPv4Stack=true
-Djava.security.manager
-Djava.security.policy=$JBOSS_HOME\bin\server.policy
-Djboss.home.dir=$JBOSS_HOME

If you are developing on Windows, use the standalone/standalone.conf.bat file. If you have set up JBoss on CentOS per my instructions, you can use the /etc/jboss-as/jboss-as.properties file (drop the -D prefixes of course).

Don’t forget to set the set the -Xmx and -XX:MaxPermSize options while you are editing files in the bin directory. Liferay recommends -Xmx1024m -XX:MaxPermSize=256m.

The Liferay documentation suggests setting the user.timezone property to GMT as well. I encountered problems with that setting when deploying JSP changes. The Liferay deployer left the JSP timestamped with GMT time value on the file system; since these were always in the past for me the JSPs always looked older than their last compile time from JBoss’s point of view. So they did not get recompiled. So I have skipped that setting.

While we are fooling around with the JBoss start-up mechanism, it seems like a good time to create the server.policy file in jboss-as-7.2.0.Final/bin:

grant {
    permission java.security.AllPermission;
};

Next we need to define the portal-ext.properties file in the liferay directory. We tell Liferay where in the JNDI to find our data source and mail session. We also disable the mechanism where it tries to launch a browser every time it starts.

jdbc.default.jndi.name=java:/jdbc/LiferayPool
mail.session.jndi.name=java:/mail/MailSession
browser.launcher.url=

Something to note here is that the Liferay documentation omits the first slash in the JNDI names which causes issues on JBoss 7.2.0. Include the slash and make sure your names are consistent between the portal-ext.properties and standalone-full.xml files.

OK, we are to install Liferay itself. We extract the contents of the Liferay war download into a new directory under deployments. Then we need to delete the eclipselink.jar from the lib directory. Finally we create a .dodeploy file to trigger the deployment:

$ cd jboss-as-7.2.0.Final/standalone/deployments/
$ mkdir liferay-portal.war
$ cd liferay-portal.war
$ jar xf ../../../../../liferay-portal-6.2.0-ce-ga1-20131101192857659.war
$ rm WEB-INF/lib/eclipselink.jar
$ cd ..
$ touch liferay-portal.war.dodeploy

Note that we are differing from the Liferay instructions again, mainly because JBoss 7.2.0 does not have a ROOT.war deployment to clear out. Instead we use the much clearer name liferay-portal.war.

At this point you are ready to go. Fire up JBoss and enjoy your Liferay portal at http://localhost:8080/. Don’t forget that we used the standalone-full.xml file, not the default standalone.xml file when you start your application server.