How to hot reload classes in JBoss - java

I'm using JBoss AS 4.2.3.GA and I want to make it to hot reload changed classes.
Now, I have a running JBoss AS with deployed exploded war, after changing (recompiling) some classes, it starts to redeploy all war:
14:14:03,732 INFO [StandardContext] Reloading this Context has started
and redeployment takes a very long time. I want to avoid such time wasting, and maybe there is a way to tell JBoss, just to replace changed class files w/o redeploying all the war?
I've also tried reloadable="true" in
jboss-4.2.3.GA\server\default\deploy\jboss-web.deployer\server.xml
But, perhaps, that's not what i seek. I don't know if it matters, but the exploded war's directory is external to server's /default/deploy/ dir. All my classes are in WEB-INF/classes dir.

You probably need to research framework-specific solutions. Look for OSGi, Spring Dynamic Modules, JEE6 dependency injection.
Also, there may be an Eclipse plugin that will facilitate this for you. I know there is one for Glassfish and JEE6.
What technology are you developing this with?

Related

Deploying war on server mechanism

When I developed any web application I added many jars which my code depended on them.
I want to know when I deployed the war on the server how server or containers using these jars,
And if I but them on server's modules directly is it will be an advantage for publishing or deploying ?!
When your code is executed the container will look within your war to see if the dependent jar is available. If it cannot find the dependent jar within your war then the container will traverse it's tree to see if it can find the dependency somewhere within the container itself. Through configuration, it is possible to reverse so the war is checked last.
The war should be self-contained, with the dependent jars in the war's WEB-INF/lib folder. Configure the container (likely default) to check the war first. This maintains isolation which helps keep the app stable over time. For example, the container might be updated but your app should not need to be updated.
Deploying those dependent jars outside the war, to somewhere within the container to a shared folder, will likely make those dependent jars visible to all deployed apps and/or the container itself. This eventually leads to jar version conflicts and class loader issues. Don't do it!
There is no advantage using jar dependencies on the server classpath. This will force you to depend on the server itself which is not a good idea when dealing with continuous delivery.
BTW you shall know that every war file has it own classpath when deployed, so if you deploy some war, let's suppose on a Tomcat Server, it will use it's own classpath which contains the necessary jars. The container (Tomcat in this case) will know nothing about these jars but your application will.

Spring jars in tomcat lib folder

I am completely confused over how the class loading happens in tomcat. So please bear with me if my question sounds stupid.
We deploy multiple spring webapps on single tomcat server. To reduce the memory footprint, we thought of having spring, hibernate and database driver jars in tomcat lib folder so that those are shared by all webapps.
I started first by marking spring dependencies as provided and copied those jars to tomcat lib. But on server startup I started getting multiple ClassNotFoundErrors, like for commons-logging, commons-fileupload, jackson, so I had to move these jars as well to tomcat lib.
But then this started feeling fishy. What if in future I add another spring dependency to my project, say spring-data-cassandra. Would I need to move it's dependent jars as well? This might be unending. Also I might get CNF errors at runtime.
I tried to follow this link and brought back spring-context and spring-web back to application war. But it didn't work, got ClassNotFound on some class during WebApplicationIntializer initialization. I tried to understand the order of classes getting loaded in tomcat, but could not understand much.
Then I found a complete different explanation for JDBC driver loading which kinda contradicts to all other explanations and left me completely confused.
As I read more, I think it is not a right approach to move spring jars to tomcat lib, but still haven't got a good reasoning. And then why JDBC driver works? Can someone please explain? Also does classloader for each webapp creates a copy of each class?
Edit 1: I came to know that few dependencies are optional in spring jars, and will be required if are in use in my webapp. So spring-web depends on jackson libraries but is optional for my app. So I need to find out which all jars are required for my project and are also required by spring, those jars need to be moved to tomcat lib.
I will try to explain what I know.
When you deploy a WAR on your tomcat, the class loading will happen this way :
look for the class to load in your WAR classLoader
if not found move to parent (tomcat /lib folder)
What happen in your case is that spring also have a lot of dependencies, if you package it in your war, its dependencies would have been packaged as well and everything would have worked fine. But since you defined spring as provided, all its dependencies are considered provided as well, and when you put it in /lib folder, spring is accessible, but its dependencies are not.
What you need to do is put all spring dependencies and the dependencies of dependencies (etc.) in lib folder as well. Another solution is to define an intermediary WAR in your classloading hierarchy which will contains all your common libs.
If you prefer to create this type of thin WAR, one solution would be to first gather all runtime/provided dependencies and then copy them explicitly under Tomcat's common (or shared) library directory:
If under a Maven project, gather everything (including transitive dependencies) under target/dependency:
mvn dependency:copy-dependencies -DincludeScope=runtime
mvn dependency:copy-dependencies -DincludeScope=provided
Afterwards, copy to library. For example:
cp target/dependency/*.jar /usr/local/tomcat/lib/

Is there a way to deploy a Maven project with "jar" packaging into Tomcat7?

My project generates a Jar as the output package and uses an external War file, available on our Artifactory, as the Web Application to be deployed on Tomcat (currently using version 7). This War file contains all libs and modules required for the application to run.
I have already packaged and ran those projects outside eclipse on a "vanilla" Tomcat installation. In this scenario, the Jar my project generates is loaded on the context.xml file this way:
<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="/home/igor/workspace/myapp/myapp-2.4.3.jar"/>
Is there a way I can deploy this project on Tomcat using Eclipse and still be able to debug it? Can I use the Jar generated for this purpose or do I have to deploy the workspace project?
As for the War file, do (or can) I have to add it as an dependency?
Thanks in advance!
EDIT
We actually provide an Web Framework, which is packaged as a war. Other applications that use that framework are exported as jars and loaded into the framework through the context file as cited above.
Your question is confusing probably because of your custom plugin/classloader and deployment which is sort of orthogonal to debugging.
What I recommend is you keep whatever system you have to build/package/deploy and use JVM remote debugging. That is do not use the Eclipse WTP since you seem to have custom steps for deployment but rather build your code deploy & run a separate Tomcat instance and then run the remote debugger in Eclipse.
You will get some hotcode swapping with this method but not as much as something like JRebel.. (which you could use also) it will certainly be better than constantly redeploying.

Is there some easy way to execute code upon JBoss deployment of a JAR inside an EAR?

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

How to use xml-apis in web application that will be running under JBoss 5.1?

We need to use jasper reports in web application under JBoss on AIX.
Today we get a problem when we tried to add xml-apis to WEB-INF/lib - JBoss did not start at all.
What should we do in order to use xml-apis under JBoss?
PS.
As far as I know we need org.w3c.dom.xpath.XPathEvaluator and org.w3c.dom.svg.*
Are you sure you need to? JBoss already has those APIs in its standard library set, your WAR should automatically have access to them. Try removing the JAR from your WEB-INF/lib.
The only way to replace JBoss's copy of that JAR is to place it in the top-level JBoss lib/endorsed directory, and make sure it doesn't clash. This will affect the entire JBoss server, though, so you need to very sure you know what you're doing. JBoss itself uses these libraries.

Categories

Resources