Win a copy of Transfer Learning for Natural Language Processing (MEAP) this week in the Artificial Intelligence and Machine Learning forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Paul Clapham
  • Devaka Cooray
  • Bear Bibeault
Sheriffs:
  • Junilu Lacar
  • Knute Snortum
  • Liutauras Vilda
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Tim Holloway
  • Piet Souris
Bartenders:
  • salvin francis
  • Carey Brown
  • Frits Walraven

Externalized Tomcat config getting deleted

 
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi!

I recently looked into ways how to make externalized config work with Tomcat 8.
To release a new version to our production Tomcat, I usually just login via FTP, delete the old webapp/war and upload the new webapp/war. AutoDeploy does the rest. We currently don't use the Tomcat Manager.

Now, i can't have my config be a part of my war anymore. It needs to instead sit on the server in a persistent way (=externalized config). Tomcat seems to make this basically impossible for me. I am now using for my config. In the context, i have a JNDI environment entry that specifies where the workspace folder for this app (which includes config files etc.) is located. I can not hardcode this in my war, because the same war is used for development, production and staging, and the workspace location is different for all of those.
Example:

This external context XML works fine, until Tomcat deletes it. If see basically no way, without the manager, to redeploy my war without this file getting deleted. I can't restart the server (our admin does that) and i don't see why i should be forced to shut down the server just to prevent tomcat from deleting my configuration when i delete the old war. This Tomcat behaviour doesn't make any sense for me.

- Some people have suggested to make the config read-only. This doesn't work, because tomcat will not autoDeploy a new war if it cannot delete the config.
- Some people suggest not using autoDeploy. As explained, this would require me to restart tomcat on every deploy or use the manager.

So, what i would like to get more information on:
Do i HAVE to use the manager? Or am i just stupid?
And is the manager capable of deploying a new war without deleting my context?
And why is this stupid behaviour still a thing? I have seen tons of posts of people with this problem, here, on stackoverflow, on the mailing lists. It creates problems for everyone it seems, and i have not seen a proper solution that applies to my situation.
 
Saloon Keeper
Posts: 21960
149
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't recall ever having my Config file deleted by Tomcat. But then I usually don't delete the WAR, I overwrite it. And at that, I don't do it on a live server. From about Tomcat 4 on there were problems with Tomcat running out of PermGen space until PermGen finally became obsolete at about Java version 8 so after 2 or 3 hot-deploys Tomcat was usually pretty sick.

Then again, in the shops I've worked in, application developers weren't supposed to be able to modify the production servers at all. We'd submit a change request with instructions for the system operator who would pull the module from production archives and install as indicated. They liked me because I bundled my apps in OS installer packages, which have the advantage of being able to put files in locations outside the WAR (such as conf/Catalina/localhost) and do non-Java setup functions such as installing cron scripts.

Incidentally, it's very unsafe to use relative file path names in your configuration. JEE doesn't actually support the idea of a "current directory" and Tomcat might change directories without warning as it runs.

As far as deployment options go, there are several for Tomcat. There's the brute-force copy like you're doing, there's the administrative webapp, there's Tomcat's administrative web services and you may be able even to deploy via MBeans. And, of course, a build via Maven, Ant, or something similar can generally be set up to deploy as a target option.

If you're going to deploy "hot", I would recommend that you use one of the deployment interfaces instead of simply copying files. The deployment interfaces should be capable of keeping things together. Note, however that you'll probaby have to supply the Context information along with the WAR. The JSR that defines such features requires 2 "deployment descriptors". The Context element is the external server-dependent deployment descriptor. There's also an interna server-independent deployment descriptor. It's the WEB-INF/web.xml file.
 
Kath Tharsas
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Tomcat deleting context config on undeploy (and thus on redeploy because that includes undeploy) is documented, intended (sadly), and easily reproducable, see:

https://marc.info/?l=tomcat-user&w=2&r=1&s=tomcat+deletes+context.xml&q=b
https://serverfault.com/questions/192784/why-does-tomcat-like-deleting-my-context-xml-file
https://stackoverflow.com/questions/4032773/why-does-tomcat-replace-context-xml-on-redeploy
https://blog.alwold.com/2008/05/07/getting-tomcat-to-stop-deleting-your-context-xml-files/

Also, i do not use relative paths in production. The example in OP is from my "dev" config, were i use embedded tomcat and the base is always the project directory (and if it changes, it doesn't really matter. Its just dev). The point is that i needs to be adjustable, and it needs to be adjustable per war, but not defined in the war.

So all in all, what you are telling me, is that i should use the manager webapp or http interface that maven/grade plugins are using? Well it seems to be only option left, i just hope that this doesn't delete my stuff, too.
 
Tim Holloway
Saloon Keeper
Posts: 21960
149
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The Tomcat "working directory/current directory" is probably going to be the CATALINA_BASE directory, but it's not guaranteed, so it's better not to get into the habit even for testing.

Anyway, remember that I said that the Context XML file is the "server-dependent deployment descriptor? If you deploy a webapp, it's required as part of the deployment. That's how it was designed per the original JSR spec. It's not just a Tomcat thing.
 
Kath Tharsas
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well if that is how it was designed, it seems to be a very bad design. Like, what is the official way to supply external persistent config to your webapps, that works when you want to deploy the same webapp multiple times on one server? Don't tell me there is none and that i have to KNOW my the target environment at the time when i build my war file, because that makes no sense. That would mean i would have to build a war file for dev, one for staging, one for production, and additional ones for every kind of server that i would want to deploy my war on.

About the path: I could probably fiddle with my build so i can put my current project dir into the dev context instead of relative paths. Then i would not need relative paths at all.
 
Tim Holloway
Saloon Keeper
Posts: 21960
149
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Actually, they thought they were pretty clever. Every app deployment needs a certain amount of information to be provided to the webapp server. Some of that information - such as the welcome page location, security context, and error page information is portable and doesn't care whether the webapp is running on Tomcat or on Wildfly or WebSphere. So that goes in the server-independent deployment descriptor (web.xml).

But some is specific to the webapp server itself. Stuff like the database connection pool configuration (which can be shared between multiple webapps), the security realm configuration, and, of course the JNDI data. So it goes in the server-dependent deployment descriptor. Which is a Context file for Tomcat, but has a completely different name and format for WebSphere and for Wildfly. You can submit the exact same WAR for deployment under any of these servers and only the server-dependent deployment descriptor changes, not the WAR file. This is part of the "write once/run anywhere" characteristic of Java and JEE. Although Tomcat and jetty strain the concept, since they're not complete JEE implementations.

Tomcat's rules for deployment aren't entirely intuitive. Until recently, if you copied a new WAR file into the default Tomcat webapps directory, the default behavior was for Tomcat to explode that WAR file into its component files and directories and use them. BUT if you copied an updated WAR file into the webapps directory, that file wasn't exploded. Instead, Tomcat continued to use the old exploded WAR until you manually deleted it. That quirk was only fixed very recently. Before that, my standard deployments either turned off exploding or I deleted the exploded WAR, and the contents of the Tomcat work and temp directories every time I updated the WAR.

The Context file doesn't just define stuff statically. If you update it, Tomcat will re-deploy the WAR. If you delete the WAR, the reason that it deletes the Context is that the Context is defining a URL context path and a pointer to application classes and resources (the WAR) and if you delete the actual WAR, then the Context is broken. Tomcat doesn't have a concept of being incompletely deployed. If a Context is present, the app is considered deployed. If you undeploy the app, its deployment descriptor must therefore be removed.

 
Kath Tharsas
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, i noticed the behaviour you describe (i can't just overwrite the unexploded war) in Tomcat 7/8. I also have Tomcat 9 here for testing, ill try if what you describe works there, and see if that also deletes the external context.

Anyway, it seems to me that either the JSR's or Tomcats concept of the server-dependent deployment descriptor is lacking, because the concept of an "incomplete" context (or some kind of persistent config) is necessary in reality. And not allowing people to do this does not make sense imho as explained.
 
Greenhorn
Posts: 3
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The general issue as described by the title is covered by Re-deploy from war without deleting context which is still an open issue at this time.

There is an acknowledged distinction between re-deploy which does not delete the context, and deploy after un-deploy where the un-deploy deletes the context. The documentation was out of date, and the manager GUI still does not support re-deploy.
 
Kath Tharsas
Greenhorn
Posts: 9
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Interesting, however the latest (updated?) docs are still wrong it think: Docs


Application already exists at path /foo

The context paths for all currently running web applications must be unique. Therefore, you must undeploy the existing web application using this context path, or choose a different context path for the new one. The update parameter may be specified as a parameter on the URL, with a value of true to avoid this error. In that case, an undeploy will be performed on an existing application before performing the deployment.



So the doc says that an undeploy will happen even with the update option. This is very confusing/wrong, because undeploy means that the context.xml gets deleted. According to the issue it doesn't.

I have since bitten the bullet and created separate Gradle profiles for each of my possible deployment types, which creates separate builds for each profile that each have their own context.xml inside META-INF. Not pretty, but i don't trust Tomcat with this stuff anymore.
 
Tim Holloway
Saloon Keeper
Posts: 21960
149
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I really don't (strongly don't) recommend configuring Tomcat using META-INF/context.xml. My own  very strict policy is that the same WAR should be deployable unmodified on desktop, test and production servers. That ensures that when production goes sour that I know I'm working with exactly the same code and resources back when I try to diagnose and repair the problem on my local machine. And it also ensures that the wrong deployable doesn't end up on a server that it shouldn't and thereby do things like corrupt production databases because it was being used for testing.

I think the safest way to upgrade a webapp is to undeploy and redeploy. If your application uptime is so critical that you cannot accept the small amount of time it takes to do this, then I'd recommend running a cluster so that you can keep running old copies of the app on some nodes while upgrading on others until you have the entire set updated.

One of the biggest reasons I don't encounter this problem myself is because I don't just plunk down stuff into Tomcat. Most commonly I build OS-installable packages that include the new WAR, context xml file and any other extra-WAR support files. This is actually pretty easy to do with Maven or Ant. Some people even deploy straight from Maven, Ant, or whatever their preferred build system may be.

Other people like to do more of a continuous-build process and use Jenkins or a similar product to push out the updated WARs and their context configurations.
 
Hug your destiny! And hug this tiny ad:
the value of filler advertising in 2020
https://coderanch.com/t/730886/filler-advertising
    Bookmark Topic Watch Topic
  • New Topic