Running code at application/class startup

It’s not rare the scenario where you end up needing to run some code during the initialization of a given class or of an application. This article will present a few options in how to achieve this task.

Run code when the class is loaded

In this scenario, you want to run some code when a given class is loaded by the JRE, but you want that code to be executed only once, regardless of the number of instances of that class. For this, you can use a static initialization block.

You can also watch the video below, where I show step-by-step the creation of the examples and a few more details:

StaticBlock.java
package com.lucianomolinari.startup;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StaticBlock {

	private static final Logger LOGGER = LoggerFactory.getLogger(StaticBlock.class);
	
	static {
		LOGGER.info("Static block being initialized");
	}
	
	public static void someStaticMethod() {
		LOGGER.info("SomeStaticMethod invoked");
	}
	
	public StaticBlock() {
		LOGGER.info("Constructor being initialized");
	}
	
}

As we can see, a static initialization block is declared by using the static keyword and then using curly brackets do determine the boundaries of the block. The output of the class below shows that the message is just printed the first time the class is loaded and even before its first instance was created.

StaticBlockTest.java
package com.lucianomolinari.startup;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StaticBlockTest {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	@Test
	public void instantiateClass() {
		logger.info("Invoking static method");
		StaticBlock.someStaticMethod();
		logger.info("Instantiating class");
		new StaticBlock();
		new StaticBlock();
	}
	
}
Output of test execution
[main] INFO com.lucianomolinari.startup.StaticBlockTest - Invoking static method
[main] INFO com.lucianomolinari.startup.StaticBlock - Static block being initialized
[main] INFO com.lucianomolinari.startup.StaticBlock - SomeStaticMethod invoked
[main] INFO com.lucianomolinari.startup.StaticBlockTest - Instantiating class
[main] INFO com.lucianomolinari.startup.StaticBlock - Constructor being initialized
[main] INFO com.lucianomolinari.startup.StaticBlock - Constructor being initialized

Run code every time an instance of a class is created

You may be wondering: “I can do this using the constructor of the class, can’t I?”. Yes, you surely can. But there’s an alternate way that you should be aware of: Initialization block, which has the same idea of the static initialization block, but in this case the code is executed every time an instance is created, right before the constructor. Actually, the code from an initialization block is copied into all the constructors by the Java compiler, so it’s a way to share code without needing to explicitly invoke it from all the constructors.

InitializationBlock.java
package com.lucianomolinari.startup;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class InitializationBlock {

	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	{
		logger.info("Initialization block being invoked");
	}
	
	public InitializationBlock() {
		logger.info("Default constructor");
	}
	
	public InitializationBlock(String message) {
		logger.info("Constructor with string {}", message);
	}
	
}

An initialization block is defined by just using the curly brackets. It’s very similar to the static initialization block, with exception to the static keyword.

InitializationBlockTest.java
package com.lucianomolinari.startup;

import org.junit.Test;

public class InitializationBlockTest {

	@Test
	public void instantiateClass() {
		new InitializationBlock();
		new InitializationBlock("Hello world");
	}
	
}
Output of test execution
[main] INFO com.lucianomolinari.startup.InitializationBlock - Initialization block being invoked
[main] INFO com.lucianomolinari.startup.InitializationBlock - Default constructor
[main] INFO com.lucianomolinari.startup.InitializationBlock - Initialization block being invoked
[main] INFO com.lucianomolinari.startup.InitializationBlock - Constructor with string Hello world

As you can see, the message is printed every time an instance of the class is created, before the constructor’s code. It’s the same behaviour as adding the code as part of the constructor.

Running code when a JEE application is started

The approaches showed above work very well for when you have code to be run when a given class is initialized/instantiated. However, in many cases you have a web/enterprise application and you want to run code when the application gets deployed. For these cases, you need different ways of running initialization code, and Java EE provides a few ways to achieve that.

Servlet Context Listener

The first approach is to create a Servlet Context Listener and place the logic within the method contextInitialized(). This type of listener is activated as soon as your web application is deployed and then the method contextInitialized() is invoked. See below an example of this approach.

InitializerListener.java
package com.lucianomolinari.startup;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebListener
public class InitializerListener implements ServletContextListener {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	public void contextInitialized(ServletContextEvent event) {
		logger.info("--> Servlet listener invoked");
	}

	public void contextDestroyed(ServletContextEvent event) {
	}

}

Servlet init method

The Servlet lifecycle specification states that just one instance of a Servlet is created and then the init() method is invoked. However, by default the Servlet is just created the first time it’s invoked, but it’s possible to change this to a eager initialization by using the loadOnStartup attribute, like shown in the code below:

InitializerServlet.java
package com.lucianomolinari.startup;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@WebServlet(loadOnStartup = 1)
public class InitializerServlet extends HttpServlet {
	private static final long serialVersionUID = 583565687437382094L;
	
	private final Logger logger = LoggerFactory.getLogger(getClass());
	
	@Override
	public void init() throws ServletException {
		logger.info("--> Servlet initialized");
	}
	
}

Singleton EJB

If you’re running your application in a JEE container, it’s also possible to create a Singleton EJB and then use the Startup and PostConstruct annotations. The Startup annotation will make sure your EJB is created as soon as the app is deployed and, as result, the method annotated with PostConstruct will be invoked.

InitializerEJB.java
package com.lucianomolinari.startup;

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
@Startup
public class InitializerEJB {

	private final Logger logger = LoggerFactory.getLogger(getClass());

	@PostConstruct
	public void init() {
		logger.info("--> EJB being initialized");
	}

}

Conclusion

The aim of this article was just to show a few options of how to run some initialization code for a class and/or application. Hope it can be useful. See you.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s