There has been a tremendous lack of understanding around what Liferay means by "hot deploy" and "auto deploy". Most people get the two concepts confused, believing them to be one and the same. In reality, Liferay has TWO completely separate and different concepts: hot and auto deploy (i.e. Hot Deploy != Auto Deploy).
Many of you are familiar with hot deployment in the context of JEE application servers. This basically means if an application artifact (WAR or EAR) file is present in a specifically configured directory, the application server (e.g. Tomcat, Weblogic, etc) will pick up that artifact, deploy it within the application server, and start the application. If you are not familiar with this concept, please consult your application server’s documentation.
This model works really well for development purposes; you don't have to wait 5 minutes for server restart (Weblogic/Websphere) to test changes to your code. This model also works for single node production deployments. I’m personally not a fan of this since many applications do not handle start/stops and classloader destruction properly, but that’s a different topic.
This model completely breaks down when you deploy to a multi-node production deployment. In a multi-node environment, you have many more constraints to deal with:
Most application servers solve this by using a master/slave type of design: an admin server with multiple managed servers. When you “hot deploy”, you use the admin server’s user interface (or via vendors console tools like wsadmin, wladmin) to add the archive, select which managed servers should deploy it, and start the application. Application server vendors often have different names and tools for this:
JBoss “domain” mode
Weblogic “production” mode
Websphere deployment manager
This is something that resides completely outside of Liferay Portal and is strictly in the application server’s realm.
Liferay piggy backs off this capability and performs additional initialization after a given application has been started (e.g. via javax.servlet.ServletContextListener mechanisms). This is really more “application lifecycle” and inter-application dependency management as opposed to “hot deploy”. When Liferay moves fully to OSGi in 7.0, we will more cleanly separate “hot deploy” and “application lifecycle concepts.
There are some specific Liferay capabilities that won't work unless your application server has hot deploy capabilities. Specifically, the "hot deployment" of custom-jsps in hooks. Liferay's JSP hook override very much depends upon the application server's ability to have:
- Deployment based on an exploded WAR (specifically the portal's WAR)
- Load changes to JSP files at runtime.
Application servers running in "production", "domain", etc modes cannot support this because in those deployment models, the servers often don't use exploded WARs and since no exploded WAR's they also do not support JSP reload/recompile. Even for Tomcat, it's generally advisable to deactivate JSP reloading for production deployments.
So what do you do if you use hooks to override Liferay JSPs AND you must use non-exploded WAR deployments? Simple: inject a pre-processing stage as part of your build process. You can deploy the hooks, allow them to make changes to the portal WAR file. Then you can rebundle the portal's WAR file and deploy it using the application server's deployment tools. Of course, you'll still need to deploy your hook as well, but you no longer need to worry about the JSP overrides not being loaded by your application server.
The Liferay Auto Deploy feature is a mostly optional feature that works in conjunction with the hot deployment capabilities of the application server.
So what does the auto deploy feature actually do? It:
Picks up a Liferay recognized archive (e.g. *-portlet.*, *-theme.*, *-web.*, *.lpkg, etc)
Inject required libraries (e.g. util-java.jar, util-taglib.jar, etc)
Inject dependent jars (specified in liferay-plugins.properties)
Inject required taglib descriptors (e.g. liferay-theme.tld)
Inject required deployment descriptors (e.g. app server specific descriptors, etc)
Inject Liferay specific deployment descriptors if missing (e.g. liferay-portlet.xml, etc)
It’s a huge timesaver during development and it makes it a lot easier for a portlet developer to not have to learn all of Liferay’s deployment descriptors. However, this feature is completely incompatible with how many application servers work in their farm or multi-node modes.
So how do you get Liferay to work if you intend to configure your application server in those modes? Very simple: Don’t use the auto deployer at runtime, use it at build time.
Liferay’s Plugins SDK allows you to preprocess your archives and inject all the required elements and thus bypassing the auto deployer at runtime. You simply need to call the ant task: direct-deploy (e.g. ant direct-deploy).
The direct-deploy task will create an exploded WAR file from which you can easily create a WAR file. The location of the exploded WAR depends upon what you have configured for the application server’s deploy directory in your Plugins SDK’s build.properties.
If you choose to not use the Liferay Plugins SDK, then you can examine the build-common.xml in the SDK to see how Liferay invokes the deployer tools.
Hopefully, this will clear up some of the confusion out there about “hot” and “auto” deploy.