I'm trying to understand the model that Apache Tomcat adheres to, and the documentation apparently doesn't make sense to me.
As I understand it, Tomcat is a server for hosting a wide variety of services - so it's pretty generic. I've got this application that I'm trying to understand how to host, and its main method of deployment appears to be as a Tomcat-hosted web service - the application is called Camunda (its on github). After going through the docs for Camunda, my Tomcat directory becomes absolutely filled with Camunda-related jars, and config files, etc. The docs say to just plop everything right into the Tomcat lib folder, conf folders, etc.
Most of my experience with other "platform" / "service" style host applications has been that the application itself, in this case Tomcat, stays pretty untouched in its own directory. Through config files, etc, it knows how to host whatever it needs to host.
In the case of Tomcat, it seems that it's customary to basically "pollute" the Tomcat dir with a bunch of libs for the hosted content?
This is why I made the title "is Tomcat meant to be one install per application", because for all intents and purposes once you host something in Tomcat the directory becomes so coupled with that something that the Tomcat directory IS that something.
Is this normal? Just looking for some clarification in perhaps other terms that the docs put it, because the docs don't seem to be very clear to me.
Here is a link to the install process that I am following and referring to: https://docs.camunda.org/manual/latest/installation/full/tomcat/manual/
It's been a while since I've used Tomcat, but not only is it not one-install-per-application, it's not even one-install-per-virtual-host.
Tomcat is (amongst other things) a servlet container. The directory layout and such for servlets was standardized in the Java Servlet Specification v2.2. You can download the latest servlet spec here.
The docs say to just plop everything right into the Tomcat lib folder, conf folders, etc.
Hopefully they're talking about the ones in a .war file or similar, or shared libs in the shared locations. You can put shared libraries in a location where they can be reused across applications (or even virtual hosts), which was probably useful back when disk space was more expensive, but these days I assume most people put the libs for an app in the /WEB-INF/lib directory in the application's .war file.
This page talks about the "directory" layout of a .war file (which is basically a .jar with a particular structure).
It's true that typically .war files are expanded into subdirectories of the Tomcat installation directory, but as indicated in the answer that Dan_Maff linked to in a comment, you can modify the server.xml file to have it look elsewhere instead.
You can install a webapp called Manager that helps with installing, activating, deactivating, and managing web apps via .war files. (There's also a Host Manager for managing virtual hosts.)
All that said, you certainly could do one application per Tomcat install if you wanted. You'd need a reverse proxy in front of it (Apache, Nginx, etc.) so the same port (e.g., 80) could be used for the external URL of the various applications, and you'd need to assign each Tomcat install its own internal port for the reverse proxy to talk to.
Related
I have a program which permits to upload a file from somewhere into another place. This another place is the path that will be on database. Where should I upload this file:
Into c://?
Into projectSomething/ (I´m working with glassfish and in this folder it saves on C:\Users\Alvaro\Documents\glassfish-4.0\glassfish\domains\domain1\config)
Into projectSomething/src/
Answers to such questions are always (at least partially) opinion based which is bad on SO. But I'll try to give you what is considered as good practice.
As you speak of glassfish, I suppose it is a web application. For evident security reasons, you should never allow uploaded files where you could have any of your application files. You should also think that some servlet containers or Java EE servlet can display an application without exploding the war. It is clear that in such cases, you won't be able to write anything under your project root!
So where can you put it? IMHO, the best is to see that as a deployment detail and configure it in a property file, a java system property or in a environment variable and clearly identify that in your documentation. That way it is no longer your problem as a programmer. You will be able to deploy it under windows or linux (where C:/ does not exists) under a special directory under your project root if it is guaranteed that the war will be exploded and the application will have appropriate permissions on that directory.
I have created many hooks for Liferay with Eclipse Java EE IDE for Web Developers.
The problem is that when I create a hook is deployed inside the webapps folder.
My webapps folder tree:
There are many hooks. How can how can I move them into a new folder inside webapps?
in order to have something like this:
webapps
calendar-portlet
hooks
blogs-hook
breadcrumb-hook
dockbar-hook
login-hook
blogs-hook
sitepages-hook
truefalsetocheckbox-hook
userinfo-hook
wiki-hook
marketplace-portlet
my-theme
resources-importer-web
ROOT
Any help is greatly appreciated! Thank you so much!
I suppose you're speaking about Tomcat's (or whatever appserver you're using) webapp folder. You cannot merge different apps into one folder: it has to keep the structure on deploy.
So what you can do is to aggregate those hooks on source level (i.e., create only one hook project in Eclipse with the Liferay IDE so you can put everything there). So you could put them into the same plugin.
Btw I would discourage using several hooks, because they might occasionally overwrite each other's behaviour. Imagine you have some sort of property defined in a-hook and b-hook in a properties file. You cannot tell which one will be used after the deployment.
Adding a bit of reasoning to rlegendi's answer, here's what you might consider:
If you use Liferay's auto-deploy mechanics, e.g. through the plugins-sdk deployment, Liferay places the hooks in tomcat's webapps folder (in case you use tomcat) and you'd also have to override this.
You might be able to configure tomcat to monitor different directories, even on the same virtual host (I've only tried this for different virtual hosts and don't know if this will work properly with Liferay), but the auto-deploy problem would persist, you'd basically have to change the whole deployment logic, or deploy manually to tomcat as you'd do with "big iron" appservers.
If you're happy about the development-time separation between the hooks, but would like some better runtime overview, you might want to merge different hooks into one for deployment. However, you'd have to do this on your own.
But my final recommendation is to not care too much about what's in the webapps directory anyway - you shouldn't rely on directory listings of this directory for knowing what's running on your appserver. Rather use proper deployment techniques that monitor your implementations, and limit access for manual changes. E.g. deploy your applications scripted and install a system that alerts you should required components not be available and running.
I have several webapps deployed to production. I have used Tomcat as my servlet engine for ~10 years now. I'm considering moving to embedding Jetty model from the deploy-a-war-into-Tomcat model.
These webapps are deployed over several servers and some of the are horizontally scaled (using nginx IP hash based partitioning).
I see some advantages:
I can configure my servlet engine for a particular webapp (instead of having a generic configuration for Tomcat which is running several different webapps)
It's easier to horizontally scale my webapp by running multiple Jetty instances (configured to listen on different ports) on the same host. I could also do this with Tomcat (and I have run multiple tomcat instance on the same host in the past), but I've moved to using Debian packages (.deb archives) for deployment and it's not as easy to run multiple Tomcats using this method.
My deployment package (.deb) is more "complete" at build time i.e. I don't have to be sure the Tomcat instance is configured correctly.
And disadvantages:
More instances of a servlet engine running on a server means more resources being used
I've never used Jetty. I don't think I have any Tomcat-specific stuff going on in my webapps, but I'm not sure.
My main concern is the amount of resources that Jetty will use. If I had one Tomcat instance running 4 webapps, what will the difference in resources (memory/processor) be with four Jetty instances running?
This question is probably too open-ended, but I'm curious to know if I'm overlooking something or if anybody has any experience moving from Tomcat to (embedded) Jetty.
The web container I've found easiest to embed in a jar file (and it is still a valid WAR too) is Winstone (http://winstone.sourceforge.net/).
Jenkins - http://jenkins-ci.org/ - use this container so it has been pretty stress-tested. Note that it is Servlet 2.4 only.
Well I think there is no direct answer;
I might not fully understand the ".deb" part as I'm not a debian freak :)
I prefer having an instance of tomcat with a number of configurations aka CATALINA_HOME folders where you may specify apps and ports running, so you can always have all your configs separately and change the tomcat instance if needed.
Also, see related post:
Jetty: To embed or not to embed?
I also was used to Tomcat, so in my new project I tried using Jetty to learn about it.
In an enterprise environment (where you have production / testing / development servers) I would stick to Tomcat, mainly because it helps you in getting to separate code from configuration files (now I am working in setting the conf files in a separate jar, because that way when I move changes from testing to production they do not have to manually update the jars that I'll pass to sysadmin).
Other issue is that it looks like that Jetty has changed ownership not so long ago, and looking for info often got me to the old version.
Apart from that, using Jetty is not that different from Tomcat; had to run a little through docs for finding where everything is, but structure is (as last what I have seen, I have not tried anything too complicated) more or less like Tomcat.
Currently, we support many clients using the same web app, but each client has a different configuration for accessing their database, setting files etc. As the client list grows, updating the web apps is becoming increasingly arduous, and the duplication of resources is a waste of memory, file space, etc..
What we'd like to do is have a parent web app which is shared by all children web apps. Then have each child web app carry only files specific to them. When the child web app starts up, Tomcat loads the web app from the parent web app and then overrides any files defined in the child web app following an identical package structure.
We've been googling around and haven't found a ready or complete solution. Solutions we've looked at:
Tomcat common/share - could handle class and JAR files, but we don't see a way to handle static and JSP resources residing above the WEB-INF dir.
CATALINA_BASE appears to be more suited for running multiple instances of Tomcat which we'd rather avoid
A Maven possible solution, but we are not big fans of Maven, so would rather avoid it also.
Anybody have suggestions or ideas on how to solve this? If Tomcat configuration is not possible, what about a different application server (such as Glassfish) or a tool for doing dynamic file updated (such as OSGi, rsync). Would like to remove the resource duplication if possible.
Thank you.
There is no such thing as "parent" or "child" webapps. It's not part of J2EE spec and AFAIK it's not supported by any application server.
That said, your problem is twofold:
1) Having shared resources. This part is pretty easy assuming "resources" means static resources (images / CSS / javascript / etc...).
If they are truly shared (e.g. you don't need to have a separate version in some of your webapps), host them elsewhere (separate "common" webapp or put Apache in front of your Tomcat and host them there.
If you do need to have "local" versions of some of those resources you may be able to do some clever conditional URL rewriting or simply write a servlet that would check whether particular resource exists locally and, if not, take it from "common" location.
Precompile your JSPs so you only have to deal with JARs.
If your Tomcat instance only hosts your apps, you can indeed put your JARs in shared (or lib in the latest version); otherwise you can deploy them with each application .
2) Simplifying deployment. I'm not really sure what the big problem is here... It's rather trivial to write an Ant (batch, shell, what have you) script that would assemble and deploy WARs based on "common" and "per-app" directory structures.
Alternatively, you may want to take a look at using JNDI to severely reduce the number of files that have to be deployed (in theory, to a single context.xml for each application).
You can build parent-child hierarchy if you use Spring at your web-apps - Using a shared parent application context in a multi-war Spring application.
I.e. you can define all shared stuff at the 'parent' context and have 'child' contexts just to use it.
If all you had was setting file and configuration changes you could manage these through the context.xml and then you can point the docBase of each application context at a common directory for all the applications to share the same source.
the drawback to this is changes to the application will require a tomcat restart.
This does not however solve your problem if you want to override logic.
A option that I am exploring for a similar scenario is to move the client custom portion into ajax widgets / gadgets. Then have it be part of the configuration files to tell the application which version of the gadget to pull for which client.
you can review documentation for having applications share a docbase here http://tomcat.apache.org/tomcat-5.5-doc/config/context.html
I'm currently working on a j2ee project that's been in beta for a while now. Right now we're just hammering out some of the issues with the deployment process. Specifically, there are a number of files embedded in the war (some xml-files and .properties) that need different versions deploying depending on whether you are in a dev, testing or production environment. Stuff like loglevels, connection pools, etc.
So I was wondering how developers here structure their process for deploying webapps. Do you offload as much configuration as you can to the application server? Do you replace the settings files programmatically before deploying? Pick a version during build process? Manually edit the wars?
Also how far do you go in providing dependencies through the application servers' static libraries and how much do you put in the war themselves? All this just to get some ideas of what the common (or perhaps best) practice is at the moment.
I think that if the properties are machine/deployment specific, then they belong on the machine. If I'm going to wrap things up in a war, it should be drop-innable, which means nothing that's specific to the machine it's running on. This idea will break if the war has machine dependent properties in it.
What I like to do is build a project with a properties.example file, each machine has a .properties that lives somewhere the war can access it.
An alternative way would be to have ant tasks, e.g. for dev-war, stage-war, prod-war and have the sets of properties part of the project, baked in in the war-build. I don't like this as much because you're going to end up having things like file locations on an individual server as part of your project build.
I work in an environment where a separate server team performs the configuration of the QA and Production servers for our applications. Each application is generally deployed on two servers in QA and three servers in Production. My dev team has discovered that it is best to minimize the amount of configuration required on the server by putting as much configuration as possible in the war (or ear). This makes server configuration easier and also minimizes the chance that the server team will incorrectly configure the server.
We don't have machine-specific configuration, but we do have environment-specific configuration (Dev, QA, and Production). We have configuration files stored in the war file that are named by environment (ex. dev.properties, qa.properties, prod.properties). We put a -D property on the server VM's java command line to specify the environment (ex. java -Dapp.env=prod ...). The application can look for the app.env system property and use it to determine the name of the properties file to use.
I suppose if you have a small number of machine-specific properties then you could specify them as -D properties as well. Commons Configuration provides an easy way to combine properties files with system properties.
We configure connection pools on the server. We name the connection pool the same for every environment and simply point the servers that are assigned to each environment to the appropriate database. The application only has to know the one connection pool name.
wrt configuration files, I think Steve's answer is the best one so far. I would add the suggestion of making the external files relative to the installation path of the war file - that way you can have multiple installations of the war in the one server with different configurations.
e.g. If my dev.war gets unpacked into /opt/tomcat/webapps/dev, then I would use ServletContext.getRealPath to find the base folder and war folder name, so then the configuration files would live in ../../config/dev relative to the war, or /opt/tomcat/config/dev for absolute.
I also agree with Bill about putting as little as possible in these external configuration files. Using the database or JMX depending on your environment to store as much as it makes sense to. Apache Commons Configuration has a nice object for handling configurations backed by a database table.
Regarding libraries, I agree with unknown to have all the libs in the WEB-INF/lib folder in the war file (self-packaged). The advantage is that each installation of the application is autonomous, and you may have different builds of the war using different versions of the libraries concurrently.
The disadvantage is that it will use more memory as each web application will have its own copy of the classes, loaded by its own class loader.
If this poses a real concern, then you could put the jars in the common library folder for your servlet container ($CATALINA_HOME/lib for tomcat). All installations of your web application running on the same server have to use the same versions of the libraries though. (Actually, that's not strictly true as you could put overriding versions in the individual WEB-INF/lib folder if necessary, but that's getting pretty messy to maintain.)
I would build an automated installer for the common libraries in this case, using InstallShield or NSIS or equivalent for your operating system. Something that can make it easy to tell if you have the most up to date set of libraries, and upgrade, downgrade, etc.
I usually make two properties files:
one for app specifics (messages, internal "magic" words) embedded in the app,
the other for environment specifics (db access, log levels & paths...) exposed on each server's classpath and "sticked" (not delivered with my app). Usually I "mavenise" or "anttise" these one to put specific values, depending on the target env.
Cool guys use JMX to maintain their app conf (conf can be modified in realtime, without redeploying), but it's too complex for my needs.
Server's (static ?) libraries: I strongly discourage server library use in my apps as it adds dependency to the server:
IMO, my app must be "self-packaged": dropping my war, and that's all. I have seen wars with 20 Mbs of jars in it, and that's not disturbing for me.
A common best-practice is to limit your external dependencies to what is offered by the J2EE dogma: the J2EE API (use of Servlets, Ejbs, Jndi, JMX, JMS...). Your app has to be "server agnostic".
Putting dependencies in your app (war, ear, wathever) is self-documenting: you know what libraries your app depends on. With server libs, you have to clearly document these dependencies as they are less obvious (and soon your developers will forget this little magic).
If you upgrade your appserver, chances that the server lib you depends on will also change. AppServer editors are not supposed to maintain compatibility on their internal libs from version to version (and most of the time, they don't).
If you use a widely-used lib embedded in your appServer (jakarta commons logging, aka jcl, comes to mind) and want to ugrade it's version to get the latest features, you take the huge risk that your appServer will not support it.
If you relies on a static server object (in a static field of a server class, e.g. a Map or a log), you'll have to reboot your appserver to clean this object. You loose the ability to hot-redeploy your app (old server object will still exists between redeployments). Using appServer-wide objects (other than those defined by J2EE) can lead to subtle bugs, especially if this object is shared between multiple apps. That's why I strongly discourage the use of objects which resides in a static field of an appServer lib.
If you absolutely need "this object in this appserver's jar", try to copy the jar in your app, hoping there's no dependency on other server's jar, and checking your app's classloading policy (I take the habit to put a "parent last" classloading policy on all my apps: I'm sure I won't be "polluted" by server's jars - but I don't know if it is a "best practice").
I put all configuration in the database. The container (Tomcat, WebSphere, etc) gives me access to the initial database connection and from then on, everything comes out of the database. This allows for multiple environments, clustering, and dynamic changes without downtime (or at least without a redeploy). Especially nice is being able to change the log level on the fly (although you'll need either an admin screen or a background refresher to pick up the changes). Obviously this only works for things that aren't required to get the app started, but generally, you can get to the database pretty quickly after startup.