My organization is creating a "base" Java web app that is meant to be customized by adding jar files (with customized classes) by adding the jar files to the web app's WEB-INF/lib directory. The goal is that our developers can simply create custom code, packaged as a simple jar file, which can be loaded into this "base" web app, so the developer doesn't have to worry about all the web app plumbing, just the actual custom code.
We're investigating a few different deployment models, but one idea was to put these jar files somewhere on a network directory. When the Java web app starts up, a ServletContextListener copies these jar files into the web app's WEB-INF/lib directory (the web app is originally deployed as a war file).
Then, another ServletContextListener uses Stripes' ResolverUtil class (JavaDoc here) to load all of the classes of a particular type (in this case, that implement a particular interface) that are located in the jar files that were copied into WEB-INF/lib.
Unfortunately, ResolverUtil fails to find those classes, even though they are in those copied jars. If I restart Tomcat (with those jar files still in WEB-INF/lib) they are found, as expected.
The jar files need to be in WEB-INF/lib because we want to use the Servlet 3.0 feature in which JSPs can be served from jar files, and for that to work, apparently those jar files need to be in WEB-INF/lib. If that weren't the case we would just add those jar files in the shared.loader property in catalina.properties.
So, it appears that Tomcat has already scanned the classpath for all class definitions by the time a web app is started, and since those jar files weren't in WEB-INF/lib when the web app started up, the classes will not be found.
Is there a way for those classes to be found? I don't need Tomcat to completely reload itself; I just need those new jar files and the class files they contain to be visible to the class loader. Is there a way to tell the classloader, "Hey, check the classpath again for new jars!" as I would only need to do it once, when the web app starts up?
Any other ideas?
Thank you!!
Related
I'm having trouble deploying a Java web app. It centers on our application config file (myapp.properties). In certain situations, having this file external to the WAR seems to work fine, but whenever I try to deploy it properly (Docker, proper JBoss deployment, etc.) the deployments inevitably fail due to being unable to find/read from myapp.properties.
I've seen a few references here and elsewhere to packaging these files inside the WAR archive, but I can't find any information on how to actually do that. So, my questions is:
What is the proper way to include an application config file in a WAR archive and/or deployment?
It depends in how you want to access the file.
If you want to load it via classloader resources, you need it to be in the class-path, so the best location is inside WEB-INF/classes.
That's by the way, where resources in src/main/resources will end up if you are using Maven
You can also put it anywhere inside your WAR, for example, WEB-INF/config and access it via ServletContext.getResourceAsStream("/WEB-INF/config/..... Beware but, that it's not inside the WEB-INF directory, you will have to explicitly forbid the access to the file in the web.xml deployement descriptor, otherwise it would be accessible to client requests.
I am majorly confused about where the classpath is. I understand when we create a spring mvc, resources folder, or inside web-inf is considered classpath. And we can use "classpath:" inside xml files to declare the folder. However, where is this classpath exactly? How is it set ? I have been reading about it for a long time, i still couldnt manage to get a real clear image in my head how the classpath is initially determined etc.
For example when we create a war file, and deploy it on a tomcat server, all the resource files can still be read via given paths with "classpath:" in the xml files. How does this work?
Thanks.
Ok, if it's web application, the classpath begins in WEB-INF/classes. Also, jar files in WEB-INF/lib are also on the classpath.
The Classpath is where the JVM will look for class files and other resources. Since you are using Spring MVC, I assume you are deploying a Web application (ie WAR file). This means that the classpath is set by the container which is following the Servlet spec.
The classpath for a WAR file includes the WEB-INF/classes and WEB-INF/lib folders. The Java EE/Servlet container where the WAR file is deployed will also include other common folders in the classpath.
Here is how Tomcat works.
You might also want to try this StackOverflow article/answer
I have a web application that was deployed in tomcat. As part of third party library i am getting standalone jar file from my vendors. This jar file is set of few folders as well as class files and lib folder. this lib folder contains libraries which is required by the classes. Now i want to call the method of class (belongs to stand alone jar) in my web application and want to execute that method.when i tried it was throwing error not able to resolve dependency of jar files which is getting used by claases of standalone jar. Can somebody give me some thoughts on this.
I plan to deploy an EAR packaged application into JBoss v4.2 as a folder containing the content of the EAR. Until now the EAR is deployed as a single file. I hope to be able to replace single JARs without the need to restart the application.
Is there any kind of event listener or annotation that can be used to register those JAR files upon deployment? The idea is a plugin like deployment of some features implementing a known interface. The plugins shall be used in a Seam webapp environment and may be exchanged with updated versions on the fly.
Any ideas? Thanks.
AFAIK, this is not possible/supported. When using an exploded EAR, touching an individual module would trigger the hot deployment of the whole EAR.
From Lightweight Java Web Application Development: Leveraging EJB3, JSF, POJO, and Seam:
3.4.2. Hot Deployment
Another JBoss feature that helps agile
development is exploded archives. The
EAR, EJB3 JAR and WAR files are not
necessarily JAR files in the JBoss
container. They can be directories
containing the contents of the JAR
file. For instance, instead of
deploying the dvdcatalog.ear file as a
single file, you can deploy it as
directory.
With the exploded directories, you can
make changes to any single JSP page or
Java class file in the application
while the server is running. Then you
can touch the META-INF/application.xml
file in the exploded directory (i.e.,
update the file's timestamp to
current) to re-deploy the entire EAR
application. This further saves
significant amount of time for rapid
turn-around agile developers.
What you're looking for doesn't sound simple. It would require detecting the change, unloading loaded class definitions coming from that JAR (assuming this information is known), reloading classes (something like that but I'm pretty sure I'm oversimplifying). Maybe more a job for an OSGI server.
See also
JBossClassLoadingUseCases
ClassLoadingConfiguration
My Project has 2 java files (A.java and B.java in same package). A.java uses methods in B.java. And, an external jar has been added in the project build path. In order to create a web service (bottom up) from the class, I created a new Dynamic Web Project in Eclipse with axis2 as the runtime platform, and imported A.java and B.java source files. Next, since all my methods that need to be exposed are contained in A.java, I right click on it and created web service using the standard settings. When I deploy the web service on my apache, I get "Fault Service" and a few ClassNotFound Exceptions for some of the classes in my external jar file (I have already imported it as an external jar).
Does the external jar needs to be imported in another way?
I would expect a deployable application to be self contained, hence the "external" jars need to be included in my application. In my environment (WebSphere) you can also deploy external jars in some "shared" places and special directories, but for simple cases I prefer my app to be be self contained.
So, either include the JARs in WEB-INF/lib or package the app in an EAR file, place the JARs in teh root of the EAR and adjust the Manifest for your WAR to refer to those JARs.