Reputation: 4578
I have a a library that is bundled as an executable jar file and added to weblogic / tomcat classpath, how can I execute a main method from the jar file when the server is starting and loading the classes from the jar file.
what I want to is to have some initialization code to be executed first thing when the jar file is loaded and server is starting without any user intervention.
Note: I know I can bundle my jar in a war file, but I have some aspectj code in my library that I want to weave all running applications in the jvm, when I bundle my jar in war file, the aspectj code will only weave into the classes in the war file so I added my library jar file in the classpath.
Thanks in advance.
Upvotes: 8
Views: 3229
Reputation: 576
You need to register a Java Agent. See this link: java.lang.instrument.
java.lang.instrument
provides services that allow Java programming language agents to instrument programs running on the JVM.
This is the right way to do this.
Upvotes: 0
Reputation: 14408
Add a class inside your JAR with the following code:
public class TomcatStartupListener implements org.apache.catalina.LifecycleListener {
public void lifecycleEvent(org.apache.catalina.LifecycleEvent event) {
if (event.getType().equals("after_start")) {
// call your main method here
}
}
}
Note: In order to compile this, you need to add <tomcat-dir>/lib/catalina.jar
to your classpath. Otherwise when compiling it won't be able to find the necessary interfaces (org.apache.catalina.LifecycleListener
and org.apache.catalina.LifecycleEvent
). Once you're done with the compiling, put the JAR as usual under <tomcat-dir>/lib
.
Now open <tomcat-dir>/conf/server.xml
and add the following under the <Server>
section:
<Listener className="com.yourpackage.TomcatStartupListener" />
Now whenever your Tomcat server starts, this TomcatStartupListener
class inside your JAR will be called, and you can invoke your main method. There are a whole lot of other event types too! You can use any of these event types:
This approach is necessary because of the way the classloaders work in Tomcat (or even most JVMs). Here are the important points from that link:
There are three aspects of a class loader behavior
Lazy Loading
Class Caching
Separate Namespaces
The JVM will get very heavy if all classes inside all JARs get loaded indiscriminately. So the classes inside shared JARs are loaded only on-demand. The only way for you to invoke the main method is to add the above lifecycle listener.
Upvotes: 5
Reputation: 48057
As application servers / servlet containers typically have a lot of different classloaders, you'll most likely need a different strategy for weaving aspects into your code than in standalone applications.
I would recommend to add the aspects to every war file deployed at build time. This might be following a common technique - as opposed to a server specific one.
Further, I'm not sure it can actually be done (properly & supported) on a server. Typically a server is built to separate all webapps from each other. You might get it to work, but it might break on the next update of the server.
It might be easier to suggest an alternative technique if you'd state the problem that you want to solve with your proposed approach.
Edit after your comment: Consider the standard web application lifecycle: You can execute some code, e.g. in a servlet, upon it being deployed. If you insist on your code being contained in main
, you can call this method from your webapp's initialization code.
Upvotes: 0
Reputation: 272217
Perhaps the simplest thing to do is to deploy a trivial servlet in a .war file that references your .jar file. The servlet can be configured to start up upon deployment/container start, and then it can invoke the class containing your main()
method.
Upvotes: 2