Bootstrap jar executable in classpath on server startup

I have a library that comes as a jar executable and is added to the classpath for weblogic / tomcat, how can I execute the main method from the jar file when the server starts and loads the classes from the jar file.

I want some initialization code to be executed first when the jar file is loaded and the server starts without user intervention.

Note. I know that I can link my jar in a war file, but I have aspectj code in my library that I want to bind all running applications in jvm, when I collect my jar in a war file, aspectj code will only weave into classes in the military file, so I added the jar library file to the class path.

Thanks in advance.

+8
java classpath jar tomcat weblogic
source share
4 answers

Add a class inside the 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. To compile this, you need to add <tomcat-dir>/lib/catalina.jar to your classpath. Otherwise, during compilation, he will not be able to find the necessary interfaces ( org.apache.catalina.LifecycleListener and org.apache.catalina.LifecycleEvent ). Once you are done compiling, put the JAR as usual in <tomcat-dir>/lib .

Now open <tomcat-dir>/conf/server.xml and add the following to the <Server> section:

 <Listener className="com.yourpackage.TomcatStartupListener" /> 

Now that your Tomcat server is starting up, this TomcatStartupListener class inside your JAR will be called, and you can call your main method. There are also many other types of events! You can use any of these types of events:

  • before_init
  • after_init
  • before_start
  • configure_start
  • start
  • after_start
  • before_stop
  • stop
  • configure_stop
  • after_stop
  • before_destroy
  • after_destroy

This approach is necessary because of the way class loaders work in Tomcat (or even most JVMs). Here are the important points from this link:

 There are three aspects of a class loader behavior Lazy Loading Class Caching Separate Namespaces 

The JVM will be very difficult if all classes inside all JARs load indiscriminately. Thus, classes inside shared JARs are only loaded on demand. The only way to invoke the main method is to add the above lifecycle listener.

+5
source share

Perhaps the simplest is to deploy a trivial servlet in a .war file that references your .jar file. The servlet can be configured to start when the container starts / starts , and then it can call the class containing your main() method.

+2
source share

Since application servers / servlet containers typically have many different class loaders, you will most likely need a different strategy for weaving in your code than in stand-alone applications.

I would recommend adding aspects to every war file deployed during build. This may be due to a common method - unlike a specific server.

In addition, I'm not sure if this can actually be done (correctly and supported) on the server. Typically, a server is built to separate all webapps from each other. You can make it work, but it may break the next time you upgrade the server.

Perhaps it would be easier to propose an alternative method if you stated the problem you want to solve using your approach.

Edit after your comment. Consider the standard life cycle of a web application: you can execute some code, for example. in the servlet, after its deployment. If you insist that your code is contained in main , you can call this method from your Webapp initialization code.

0
source share

You need to register a Java agent. See this link: java.lang.instrument .

java.lang.instrument provides services that enable Java agents to program programs running on the JVM.

This is the right way to do it.

0
source share

All Articles