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.
To run an application in a nonexecutable JAR file, we have to use -cp option instead of -jar. We'll use the -cp option (short for classpath) to specify the JAR file that contains the class file we want to execute: java -cp jar-file-name main-class-name [args …]
To check our CLASSPATH on Windows we can open a command prompt and type echo %CLASSPATH%. To check it on a Mac you need to open a terminal and type echo $CLASSPATH.
forName("com. myclass") where com. myclass is a class that is inside (and only inside) your target jar; if that throws a ClassNotFoundException , then the jar is not on you current classpath. Bear in mind, though, that loading a jar at runtime is not very simple, you need to mess with classloaders.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With