views:

769

answers:

8

I have a Spring app that has a lot of dependencies (18 megabytes of JAR files..) - Now, when I am testing on the remote Tomcat 6.0 server, I'd like to not have to upload that 19 megabytes of dependencies, and just upload the classes. Pretty simple, right?

I can't get the damn thing to work.

I'm using Eclipse 3.4, and if in Java Build Path->Order and Export I remove the export of all of the dependencies, I get a nice small WAR.

So here's what I tried:

I uploaded all of the libs to the server, and stuck them in common/lib in Tomcat. The directory didn't exist, so I created it and modified catalina.properties:

shared.loader=${catalina.home}/common/lib/*.jar

I've tried a bunch of other configs, but none worked. Restart the server, deployed war fails to start. Specifically:

SEVERE: Error configuring application listener of class org.springframework.web.context.ContextLoaderList$java.lang.ClassNotFoundException:org.springframework.web.context.ContextLoaderListener       at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1

It's dying trying to load the Log4J listener, which it can't find in its classpath. The spring lib that listener is in is in common/lib.

Also - when I deploy the full 18 megabyte war, it works just fine. Everything inits and the app starts. Of course it works fine locally as well.

Oh - and I've replaced the hardcoded logging JARs with the ones out of the extras folder to allow Log4j to work.

Any help here? I have no idea why this isn't working.

A: 
  1. Is WEB-INF/lib empty?
  2. Where is log4j.jar?
  3. Where is spring.jar?

This looks like classloader visibility problem.

rodrigoap
+3  A: 

"I have a Spring app that has a lot of dependencies (18 megabytes of JAR files..) - Now, when I am testing on the remote Tomcat 6.0 server, I'd like to not have to upload that 19 megabytes of dependencies, and just upload the classes. Pretty simple, right?"

I don't understand this - 19MB is not a lot. You'd be much better off just packaging a WAR and be done with it.

I recommend that you do your testing locally on your own identical Tomcat instance, get it all working, and then deploy the WAR to the remote Tomcat instance.

UPDATE: One issue I have with putting those JARs in Tomcat's /lib directory is that now every app that you deploy to that instance sees those JARs - change them for one, all are affected. If you put the JARs in each individual WEB-INF/lib, you can modify each application without affecting others. The cost is duplicate JARs and disk space, which is cheap.

Another problem if you have to migrate from devl->test->prod, now every environment has to have the identical JARs deployed in order for your app to work. Miss one and you're broken. Your app depends on having those dependencies available. If they aren't on the server you're out of luck. Keep control in your own hands and package the JARs in the WAR file.

duffymo
Ya that's doable.However, the issue is that deploying to the remote server (not production at this point, just a dev server setup remotely) takes quite a long time. If the best practice is to keep the jars in the WAR, then sure - but these are bog-standard jars, stuff like Spring, Hibernate, etc - stuff that will be shared all across all apps. This is not a shared app server - it's being used for this application, period.
Jason Maskell
Also - it's hard to get my Vista dev box to be identical to the Debian EC2 server instance. Yes, I could setup a VBox locally, and that might be a good idea, but it's not something I've done.
Jason Maskell
I don't think it requires your dev box to be "identical", except for the fact that it has the same JVM and version of Tomcat running locally. No need for a virtual machine. Simply install a local instance of Tomcat and start using that to deploy as you develop. If you're using version control system you can have a nice, tight development loop: test, code, deploy, debug, commit, rinse, repeat.
duffymo
+1  A: 

You need to be careful externalizing the dependencies like that in a web server environment. Depending on the server there can be unexpected class-loading issues even when it seems to start up fine.

I agree with duffymo... 19MB is not really all that big... is there some reasoning behind wanting to do this? I wouldn't recommend it.

cjstehno
A: 

Listen to duffymo and cjstehno.

Adding jars to tomcat's is a sure recipe for disaster.

Keep your jars in your webapps directory.

lumpynose
why is it a disaster?
David Rabinowitz
A: 

It is strange that Tomcat can't find the jar files. Anyway, place all jars in the common folder (${catalina.home}/lib). (This is even worse than using the shared.folder, but it should work for you).

Of course, like others said, you shouldn't do that in your production system. I believe that is OK for a development system though - especially if you need to do extensive testing with the production system anyway.

Another note: you should only do this if you have full control of the server and you are the only one installing applications.

kgiannakakis
+1  A: 

find the webapp folder

upload the files direct into the folder

for example

/path-to-tomcat/webapp/myapp/

keep the /path-to-tomcat/webapp/myapp/WEB-INF/lib folder and upload the changes to ur /path-to-tomcat/webapp/myapp/classes folder

then use tomcat manager to restart the app

Dapeng
A: 

Why would you change the default ${shared.loader} property of tomcat?

Bas
+1  A: 

I second the suggestion of sending updates directly to ${CATALINA_HOME}/webapps/<your-app> on the target server. WARs are for production deployment, but if you have a slow connection and a large WAR that's no fun.

You'll want your web app to restart after the update, of course. Tomcat in development mode will monitor a few files for changes; by default WEB-INF/web.xml is one of them, so update that along with whatever else you're updating and you should get an app restart soon. In a pinch, you can use the Manager web app to kick the app awake.

For more control and convenience, you'd eventually do well to use the Tomcat ant tasks (found near the Tomcat distribution, not included with ant!) to restart the server, and perhaps to deploy your changes as well. Takes some fiddling but this is well worth it as you'll want to re-use it for each project you do.

Carl Smotricz