Both @PostConstruct and @PreDestroy annotations (often used in spring applications) are located in java.xml.ws.annotation package which is a part of Java EE module. J2EE has been deprecated in Java 9 and it’s scheduled to be removed in Java 11. Let’s look how to run your application without errors again in two approaches: with and without code modification.
Approach 1: Without code modification
There are three methods I have found to get both @PostConstruct and @PreDestroy annotations still working in Java 9 and newer.
Method 1 (recommended): Add necessary dependencies to pom.xml or build.gradle
This is the most recommended method. Especially if you don’t want to modify existing code and you are able to add missing javax.annotation-api dependency. Blow you can find both pom.xml and build.gradle examples. The newest version of jar you can find here.
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api --> <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
Method 2: Download dependencies manually and change the application run command
The idea behind this method is similar like in previous one. You have to download missing javax.annotation-api jar manually and add it to the classpath. If you want to run jar file, you have to change run command from java -jar to java -cp like below:
java -cp MyApplication.jar:lib/*.jar my.app.MainClass
Method 3: Add java.se.ee module
This method is not recommended because it won’t be working in JDK 11. As I have mentioned before java.xml.ws.annotation is deprecated to remove in JDK 11. But you can use this method temporary for both JDK 9 and JDK 10. Only you have to do is to add java.se.ee module to the JVM by using –add-modules switch. Below is an example of application invocation.
java --add-modules java.se.ee -jar MyApplication.jar
Approach 2: With code modification
The problem mentioned in the topic becomes easier to solve when you are able to modify an application code.
There is several ways you can achieve similar behaviour like @PostConstruct annotation. Most of them are described here. I recommend you to change implementation from @PostConstruct annotation to implement org.springframework.beans.factory.InitializingBean interface.
Instead of the @PreDestroy annotation I recommend you to implement destroy method from org.springframework.beans.factory.DisposableBean interface. Let’s see what you have to change based on the example below:
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; @Component public class MyBean { @PostConstruct private void init() { //TODO: init code } @PreDestroy private void shutdown() { //TODO: destroy code } }
Below is what the code looks like after modifications:
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.stereotype.Component; @Component public class MyBean implements InitializingBean, DisposableBean { private void init() { //TODO: init code } private void shutdown() { //TODO: destroy code } @Override public void afterPropertiesSet() throws Exception { init(); } @Override public void destroy() throws Exception { shutdown(); } }
As you can see you have to just implement afterPropertiesSet from the InitializingBean interface and call the init() method inside it. Instead of @PreDestroy annotation you have to implement destroy method from DisposableBean and call the shutdown method in it. After all remove unused @PostConstruct and @PreDestroy annotations.
That’s all what I’ve prepared for you in this tutorial, if I helped you, please consider sharing this post to help me gain a wider audience.
Thanks and I hope to see you in my next tutorial.