Running Liferay on Shared Hosting
steveonjava | June 26, 2009This 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:
- You need a site that can handle dynamic content, access controls, forums, blogs, etc.
- The underlying portal technology needs to be Java-based. No way you are hacking PHP (been there, never again…)
- 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:
- Unpack liferay-portal-tomcat-6.0-5.x.zip
- Look for the jar files under tomcat-6.x/lib/ext
- 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.
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
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
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.
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
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
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.
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.
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.
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.
I have an issue with multiple tomcat instances. I was building 5.3 from source and deployed it to tomcat. I left there only /webapp, /lib/ext, conf/server.xml, and modified /bin/startup.sh&shutdown.sh script for having different $CATALINA_BASE. I setup server.xml for connector to listen on different IP and changed hostname.
/opt/jdk1.6.0_16/bin/java -Dnop Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xms766m -Xmx1024m -XX:MaxPermSize=512m -Djava.endorsed.dirs=/opt/aaa/apache-tomcat-6.0.20/endorsed -classpath :/opt/aaa/apache-tomcat-6.0.20/bin/bootstrap.jar -Dcatalina.base=/opt/apache-tomcat-6.0.20 -Dcatalina.home=/opt/aaa/apache-tomcat-6.0.20 -Djava.io.tmpdir=/opt/apache-tomcat-6.0.20/temp org.apache.catalina.startup.Bootstrap start
It boots up, listens on that IP and port, but doesn’t respond at all, it’s like the requests get lost and doesn’t even get logged.
Sounds like you got the basic Tomcat mult-instance steps down. Since setting up multiple instances of Tomcat on the same box is not the point of this article, you might want to refer to another resource like this: http://azeditech.com/tomcat/multiple-tomcat-instances.html
Hi Steve. Great article. There isn’t much (Liferay) information around on how to deploy the standalone war. I missed your comment about automatic deployment of the plugins/portlets/themes, etc. i got Liferay working, but had indeed the problem of automatic deployment. It took me a while to figure out why this doesn’t work in this setup. If the additional dependencies are loaded by Tomcat at startup from /lib/ext (add to common.loader in /conf/catalina.properties) everything works fine. If the additional dependencies are added to the liferay context in /WEB-INF/lib, automatic deployment and registration of plugins/portlets/themes fails. Perhaps it has something to do with class loaders etc?
If you know how to solve this, it would be nice to hear. Otherwise, it would be nice how one could work around this by manually installing and registering the plugins/portlets/themes.
Thanks for this article anyway. Helped a lot!
With regards,
Andor Vierbergen
Hi, is possible that you explain how did you achieved “If the additional dependencies are loaded by Tomcat at startup from /lib/ext (add to common.loader in /conf/catalina.properties) everything works fine.”
Would you add the catalina.properties setup and a detail about which jar do u have and where are they.
Thanks in Advance
Alexander
By the way, the steps in this article still work on:
– Liferay 6.0.5
– Tomcat 6.0.26
– Java 1.6.0_21
Hi,
how to change jvm memory size in tomcat shared hosting.
that is adding -Xms128m -Xmx512m -XX:MaxPermSize=128m
Thanks,
Manoj
You will have to ask your ISP to change the settings globally since you are in a shared host. For my ISP they have a fairly high limit (almost 2GB of memory allocated), so I would ask for the sky…
we use liferay since 4.x, and all our websites (20), including JUG Indonesia and JUG asia, using liferay. cool virtual host feature make one liferay multiple dotcom
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?
Did you try accessing that url directly yourself? You should be able to type in the url into your browser and it will either work (in which case the error message is bogus), or it will not (which might be a corrupt installation or a url mapping issue in your server setup).