0

I've got a jar that's being built as part of a large application. It currently only contains src/main/resources.

What is the simplest way to add src/main/java and implement something that would run itself, without the need to be invoked elsewhere in the application code?

I don't understand how Tomcat executes anything, so it's possible I'm asking for the default way to run code in Tomcat.

naugtur
  • 16,827
  • 5
  • 70
  • 113
  • Your question is not really clear. Can you maybe reformulate? Give some concrete example. – Gaël J Jun 28 '21 at 21:03
  • I just need to run code as part of a jar that didn't have code before. Example: I want to get a log or a http request to a different server whenever the jar is included. – naugtur Jun 28 '21 at 21:50

2 Answers2

4

Tomcat does not execute random code. It can execute some code that follows some rules. The most common for java developers is the servlet API.

So an application built to follow the servlet API can run from tomcat as tomcat will execute some specific code for some specific url. It will also execute some code during initialization and destruction of the servlet context for some specific web app deployed.

Even a spring application in the end is deployed as code that implements the servlet API.

Panagiotis Bougioukos
  • 15,955
  • 2
  • 30
  • 47
  • How do I do a background process then? would I have to invoke it with a http request? – naugtur Jun 28 '21 at 21:42
  • 1
    https://stackoverflow.com/a/42503987/7237884 . This answer may be deployed as a war file in a running tomcat. See this article as an example of how to create a sample war file for tomcat https://www.javatpoint.com/steps-to-create-a-servlet-using-tomcat-server – Panagiotis Bougioukos Jun 28 '21 at 21:51
2

If you want to distribute your code as a JAR file (as opposed to files inside WEB-INF/classes of a WAR file), a ServletContainerInitializer is what you need.

This sums up to:

  1. Creating a class (e.g. com.example.Initializer) that implements ServletContainerInitializer,
  2. Putting its qualified name into a file META-INF/services/javax.servlet.ServletContainerInitializer,
  3. (Optional) Creating a file META-INF/web-fragment.xml with content:
<?xml version="1.0" encoding="UTF-8"?>
<web-fragment xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
    version="3.0" metadata-complete="true">

    <name>a_short_name</name>

</web-fragment>

The last step is useful if your users want to enable just a selected set of ServletContainerInitializers (using <absolute-ordering>). Usually all ServletContainerInitializers are enabled.

Edit: You can also use a ServletContextListener as in the question cited by Boug. In this case you don't need step 2, but you need to declare the ServletContextListener in the web-fragment.xml file.

Piotr P. Karwasz
  • 12,857
  • 3
  • 20
  • 43