Running Liferay on Shared Hosting

26 06 2009

This is a little off my usual set of topics, but something that hopefully others will find valuable, since there is such little information about this on the net.

Let’s say that you have are launching a new portal website for a Java technology project (such as projavafx.com), and have the following constraints/desires:

  1. You need a site that can handle dynamic content, access controls, forums, blogs, etc.
  2. The underlying portal technology needs to be Java-based.  No way you are hacking PHP (been there, never again…)
  3. You are on a budget.  It is a choice between server hosting and paying your cable bill, and not having the latter would impact your happiness more than the former.

So, with those constraints, you might be brave enough to try putting Liferay Portal on a Shared Tomcat Hosting plan.  Would a dedicated VPS be easier?  Sure, but you also pay more $$$ per bandwidth/disk/cpu.

(I am intentionally not mentioned any hosting companies by name, but if you look around you should be able to find shared Tomcat hosting for under $10/month.)

What to Download

By default Liferay directs you to a self-contained Tomcat installer that will set up a new Tomcat instance from scratch.  You will need to grab this as well as the WAR distribution that is a little bit more buried on the site.  There are also some ancillary downloads, such as the tunnel-web jar that are helpful as well, all of which can be found in the Additional Files section:
http://www.liferay.com/web/guest/downloads/additional

At a minimum you will need:

  • Liferay Portal 5.x Bundled with Tomcat 6.0 (default download)
  • Liferay Portal 5.x WAR

(5.2.3 was the current version at the time of this writing, but feel free to grab the latest and let me know if anything has materially changed by leaving a comment.)

Basic Setup

The default Liferay configuration assumes that you have access to the Tomcat directory and can drop shared libraries and such into the base installation.  This is definitely not possible in a shared environment, so instead we will hack the WAR file to make everything work cleanly instead:

  1. Unpack liferay-portal-tomcat-6.0-5.x.zip
  2. Look for the jar files under tomcat-6.x/lib/ext
  3. Copy all the jar files from that folder into liferay-portal-5.x.war under WEB-INF/lib

Note:  You would think that the Liferay Portal Dependencies jar from the Additional Files section would contain all the jars you need, but it only has a subset.  Unfortunately, the only way to get the full set of jars is by grabbing them from the bundled Tomcat distribution.

The next problem is that you won’t have access to the shared Tomcat context to setup custom context properties.  Fortunately, all of this can be easily configured in a portal-ext.properties file, which is formatted as a standard Java properties file.  Some of the parameters that you will need to use include:

  • portal.ctx – This allows you to set the LifeRay root context if you are running from a sub-folder (which is very common in a shared hosting environment)
  • liferay.home – Folder where liferay will store documents and artifacts.  This should be set to an absolute path within your home folder that is configured to be writable by the Tomcat process.
  • jdbc.default.* – You can set the dirverClassName, url, username, and password that are specific to your hosting environment.

Here is an example portal-ext.properties file:

portal.ctx=/portal
liferay.home=/home/widgetfx/liferay
jdbc.default.driverClassName=com.mysql.jdbc.Driver
jdbc.default.url=jdbc:mysql://localhost/widgetfx_liferay?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false
jdbc.default.username=xxxxxxxx
jdbc.default.password=xxxxxxxx

Once you have updated it for your server hosting settings, add it to liferay-portal-5.x.war under WEB-INF/classes.

All that is left is to make sure your database is setup and deploy this WAR file to your hosting provider.  Liferay should come up by itself, or if not check catalina.out for common errors (like database access permissions).

cPanel Tip: If your shared hosting provider uses cPanel to deploy Tomcat applications, you may have trouble getting it to map requests from Apache to Tomcat under the Liferay directory.  An easy way to do this without hacking Apache is to put a .htaccess file under the Liferay root directory with the following contents:

SetHandler jakarta-servlet
SetEnv JK_WORKER_NAME ajp13

Setting up Multiple Instances

All the instructions so far assume you are only setting up one instance (and that no one else has already setup a Liferay instance on the same server).  However, if you want to go multi-instance or just prevent future collisions, some more invasive hacking is required.

Inside of liferay-portal-5.x.war, hidden in portal-impl.jar there is some magical JMX and MBean magic to handle statistcs and configuration that will blow up horribly with multiple instances.  To disable this you will need to:

  • extract WEB-INF/lib/portal-impl.jar
  • inside portal-impl.jar edit META-INF/hibernate-spring.xml and change the statistics key to a unique value (highlighted in bold):
    <entry key="Hibernate:name=statistics">
  • inside portal-impl.jar edit META-INF/messaging-sprint.xml and comment out the JMX bean and reference to it in MessagingConfigurator bean:
    <!--<ref bean="com.liferay.portal.kernel.messaging.jmx.JMXMessageListener" />-->

Once these changes are deployed you can now safely bring up multiple instances as separate Tomcat web applications.

Congratulations, you now have a Liferay instance working on your shared server configuration!

What Next?

While this covers the basics, here are some things that require additional tweaking:

  • Plug-ins cannot be cannot be installed automatically
  • Additional Liferay themes need to be manually deployed
  • Tunnel-web needs to be configured differently

If I am feeling adventurous (and there is interest), I will do a part 2 of this to go over tunnel-web and plug-in/theme configuration in a shared hosting environment.


Actions

Information

18 responses

26 06 2009
nihed

You can download additional jar from http://www.liferay.com/web/guest/downloads/additional
*Liferay Portal 5.2.3 Dependencies
instead Unpack liferay-portal-tomcat-6.0-5.x.zip

26 06 2009
steveonjava

As I mentioned in the Note within the post, the Tomcat portal dependencies zip is missing several jar files that you will need to run Liferay. All of these can be found in the lib/ext directory of the Tomcat distribution, which is the most painless way I have found of making this work.

12 08 2009
Zahid

I want to host my liferay on a shared server , can you elaborate on how after making all the changes in the .WAR file ,what are next steps like putting the unzipped liferay bundled tomcat on to the shared server and then deploying the WAR file and how to put my portlet or portlets into the tomcat.

I have not done any thing like this before so please help.

Thanks in advance

19 08 2009
steveonjava

Zahid,
Deployment depends on your provider. It should be similar to any other WAR application deployment, and may involve unzipping or other steps depending on your provider.

To include your own portlets you will also have to bundle those in the same WAR with liferay.

19 08 2009
Romualdo

Hi, Steve.

After performing each step, I’ve got the following error:

09:04:22,765 ERROR [ContextLoader:215] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘messageListener.scheduler’ defined in class path resource [META-INF/messaging-spring.xml]: Cannot resolve reference to bean ‘com.liferay.portal.kernel.scheduler.SchedulerEngine’ while setting constructor argument;

The complete log file is:
———————–
Aug 19, 2009 9:03:20 AM org.apache.catalina.core.AprLifecycleListener init
INFO: The Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/local/jdk1.6.0_13/jre/lib/i386/server:/usr/local/jdk1.6.0_13/jre/lib/i386:/usr/local/jdk1.6.0_13/jre/../lib/i386:/usr/java/packages/lib/i386:/lib:/usr/lib
Aug 19, 2009 9:03:20 AM org.apache.coyote.http11.Http11Protocol init
INFO: Initializing Coyote HTTP/1.1 on http-12013
Aug 19, 2009 9:03:20 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 414 ms
Aug 19, 2009 9:03:20 AM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Aug 19, 2009 9:03:20 AM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.14
Aug 19, 2009 9:03:20 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive ROOT.war
Aug 19, 2009 9:03:21 AM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive liferay.war
Loading jar:file:/home/romualdo/jvm/apache-tomcat-6.0.14/domains/infociencias.net/liferay/WEB-INF/lib/portal-impl.jar!/system.properties
Loading jar:file:/home/romualdo/jvm/apache-tomcat-6.0.14/domains/infociencias.net/liferay/WEB-INF/lib/portal-impl.jar!/portal.properties
Loading file:/home/romualdo/jvm/apache-tomcat-6.0.14/domains/infociencias.net/liferay/WEB-INF/classes/portal-ext.properties
09:03:30,369 INFO [DialectDetector:64] Determining dialect for MySQL 5
09:03:30,441 INFO [DialectDetector:97] Using dialect org.hibernate.dialect.MySQLDialect
Loading jar:file:/home/romualdo/jvm/apache-tomcat-6.0.14/domains/infociencias.net/liferay/WEB-INF/lib/portal-impl.jar!/captcha.properties
09:03:32,959 INFO [PortalImpl:252] Portal lib directory /home/romualdo/jvm/apache-tomcat-6.0.14/domains/infociencias.net/liferay/WEB-INF/lib/
09:04:22,765 ERROR [ContextLoader:215] Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘messageListener.scheduler’ defined in class path resource [META-INF/messaging-spring.xml]: Cannot resolve reference to bean ‘com.liferay.portal.kernel.scheduler.SchedulerEngine’ while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘com.liferay.portal.kernel.scheduler.SchedulerEngine’: Injection of BeanReference fields failed; nested exception is java.lang.OutOfMemoryError: Java heap space
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:479)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:162)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:925)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:835)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:440)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:728)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:380)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
at com.liferay.portal.spring.context.PortalContextLoaderListener.contextInitialized(PortalContextLoaderListener.java:49)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3830)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4337)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:825)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:714)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:490)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1138)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:566)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘com.liferay.portal.kernel.scheduler.SchedulerEngine’: Injection of BeanReference fields failed; nested exception is java.lang.OutOfMemoryError: Java heap space
at com.liferay.portal.spring.annotation.BeanReferenceAnnotationBeanPostProcessor.postProcessAfterInstantiation(BeanReferenceAnnotationBeanPostProcessor.java:68)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:959)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:269)
… 45 more
Caused by: java.lang.OutOfMemoryError: Java heap space
Aug 19, 2009 9:04:23 AM org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
Aug 19, 2009 9:04:23 AM org.apache.catalina.core.StandardContext start
SEVERE: Context [/liferay] startup failed due to previous errors
log4j:ERROR LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.
Aug 19, 2009 9:04:24 AM org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-12013
Aug 19, 2009 9:04:24 AM org.apache.catalina.connector.MapperListener registerEngine
WARNING: Unknown default host: localhost
Aug 19, 2009 9:04:24 AM org.apache.catalina.startup.Catalina start
INFO: Server startup in 63867 ms
————

Do you know how to solve this problem?

Thanks in advance,

Romualdo.

19 08 2009
steveonjava

Romualdo,
You go an OutOfMemoryException, which probably means your Tomcat instance is overtaxed or underpowered. I would try rebooting Tomcat and if that doesn’t help, ask your ISP to run some diagnostics on Tomcat about memory utilization.

27 08 2009
Gunnar

Hi Steve on Java, and thanks for writing about how to install Liferay on a shared hosted server. Perhaps i have almost the same questions as Zahid but anyway..

I followed your instructions and steps but want to know more about portal-ext.properties, you wrote:
“portal.ctx – This allows you to set the LifeRay root context if you are running from a sub-folder (which is very common in a shared hosting environment)”

Can you explain what i need to install on my shared area on the hosted server, and what is Liferay root context? You mean root.xml, context.xml files?

To deploy my edited .war file? Is it to send this file to the adminstrator of the hosted server?

Thanks again!

/Gunnar

6 09 2009
steveonjava

There are no requirements for adding files to the shared space on your provider. If you follow the instructions, you should end up with a self-contained war file.

portal-ext.properties is a file in the WAR file under WEB-INF/classes that you will need to modify to customize the liferay server settings. One of these settings is the context. The root context is your domain’s top-level holder: “http://yourdomain.com/”, and a sub-context would be something like: “http://yourdomain.com/portal”. If you install in the root context you will not be able to run any other applications on your server other than Liferay.

To deploy the war file you should follow the instructions provided by your hosting service, because this can vary greatly depending upon your ISP.

31 08 2009
karthik

Thanks Steve,
This article is very help , Steve one more request,is it possible for your you to explain how to deploy new portlets and themes to this shared environment. It will be great if you write an article about this. Thanks

21 09 2009
Constantin

Hi Steve, I have some questions for you related to this post:
I followed all above settings, I renamed de *.war in liferay-portal.war and tomcat deployed this archive in liferay portal… Now I’m trying to test the portal in windows, and, when I access http://localhost:8080/liferay-portal it seems that the content is redirected to http://localhost:8080/web/guest and get the error page from Tomcat (The requested resource (/web/guest) is not available.).

PS. I understand that this instructions you maded in Linux SO. In file portal-ext.properties I didn’t set the portal.ctx and liferay.home, I guess that this variables are optional, or, if not, give me an example on how to set this variable for windows OS.

21 09 2009
Constantin

OK, I resolved that issue 🙂

23 09 2009
mikeg

This article is great, I’ve been able to deploy a working liferay application following the instructions in this article. I agree with karthik – an article on deploying portlets and themes would be great.

3 11 2009
trex

Kudos on a great writeup. Easy to read, easy to follow.

My question goes to your statement on plug-ins and themes not being able to be installed automatically. I’ve been attempting to install plug-ins such as WOL with mixed success. I was wondering if you have any words of wisdom? Right now i can get the war(s) up and running, they just don’t appear to want to integrate with the liferay portal/database.

Many thanks.

1 12 2009
Suresh

Hi Steve,

Great article! I got it working, but the problem I am having is that , when I deploy a portlet, it is not seen in either of the instances. The portlets deploy without an error, but when you go to add an application, you do not see the deployed portlets at all.

5 06 2010
Markus

Great information, exactly what I need.
I’ll first do the steps for liferay base installation and let you know my trials about theme and portlet deployment, what i definitevely need too.

2 05 2011
Ghorobei

Hi Steve,
I got great information ,Thanks a million For your try’s,
Sir. Steve I have a big problem with installing Liferay Tomcat 6 on shared hosting with Linux Apache web server,I didn’t get which bundle of this portal should upload and unzip to home directory in my shared host,
now i unzipped a liferay-portal-tomcat-6.0.6-20110225.zip on my home directory , please help me what should i do ?
thanks

3 05 2011
steveonjava

I haven’t tried this on Liferay 6 yet, although a similar process should work. If you can get it working, please mention what has changed and I will update this post.

9 09 2011
Kostas

I did all the steps but after starting I get this error
16:36:42,865 INFO [PortalImpl:3829] Current URL /portal/el/ generates exception
: /html/portal/layout/view/portlet.jsp(17,1) /html/portal/init.jsp(17,1) File “/
html/common/init.jsp” not found

Any idea on this?

Leave a reply to karthik Cancel reply