@Singleton-scoped beans are created lazily and on-demand by default. If you want to initialize these beans eagerly, you can go with @Parallel annotation, which allows parallel initialization of your bean without impacting overall startup time.
@Singleton
@Named("mySingletonBean1")
@Parallel
public DemoBean singletonBean1() {
DemoBean bean = new DemoBean("singletonBean1");
return bean;
}
@Parallel annotation indicate that the beans can be initialized in parallel with the application context. This allows optimized startup time by allowing beans that have slow initialization paths to startup and without impacting the overall startup time of the application.
If a parallel bean fails to startup, it will by default stop the ApplicationContext with an error unless shutdownOnError attribute set to false.
@Singleton
@Named("mySingletonBean2")
@Parallel(shutdownOnError = false)
public DemoBean singletonBean2() {
DemoBean bean = new DemoBean("singletonBean2");
return bean;
}
Find the below working application.
Step 1: Create new maven project ‘micronaut-parallel-init-of-beans’.
Step 2: Update pom.xml with maven dependencies.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>micronaut-parallel-init-of-beans</artifactId>
<version>1</version>
<parent>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-parent</artifactId>
<version>3.7.0</version>
</parent>
<properties>
<packaging>jar</packaging>
<jdk.version>11</jdk.version>
<release.version>11</release.version>
<micronaut.version>3.7.0</micronaut.version>
<micronaut.runtime>netty</micronaut.runtime>
<exec.mainClass>com.sample.app.App</exec.mainClass>
</properties>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-inject</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-validation</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-client</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-jackson-databind</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.micronaut.test</groupId>
<artifactId>micronaut-test-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.micronaut.build</groupId>
<artifactId>micronaut-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Step 3: Define model class.
DemoBean.java
package com.sample.app.model;
import java.util.concurrent.atomic.AtomicInteger;
public class DemoBean {
private static AtomicInteger counter = new AtomicInteger(1);
private int id;
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public DemoBean() {
System.out.println("DemoBean default constructor called for ");
}
public DemoBean(String description) {
this.description = description;
this.id = counter.getAndIncrement();
System.out.println("DemoBean constructor called for " + description);
}
@Override
public String toString() {
int identityHashCode = System.identityHashCode(this);
return "DemoBean [id=" + id + ", description=" + description + ", identityHashCode= " + identityHashCode + "]";
}
}
Step 4: Define BeansFactory.
BeansFactory.java
package com.sample.app.factory;
import com.sample.app.model.DemoBean;
import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Parallel;
import jakarta.inject.Named;
import jakarta.inject.Singleton;
@Factory
public class BeansFactory {
@Singleton
@Named("mySingletonBean1")
@Parallel
public DemoBean singletonBean1() {
DemoBean bean = new DemoBean("singletonBean1");
return bean;
}
@Singleton
@Named("mySingletonBean2")
@Parallel(shutdownOnError = false)
public DemoBean singletonBean2() {
DemoBean bean = new DemoBean("singletonBean2");
return bean;
}
@Singleton
@Named("mySingletonBean3")
public DemoBean singletonBean3() {
DemoBean bean = new DemoBean("singletonBean3");
return bean;
}
}
Step 5: Define HelloWorldController class.
HelloWorldController.java
package com.sample.app.controller;
import com.sample.app.model.DemoBean;
import io.micronaut.context.ApplicationContext;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.inject.qualifiers.Qualifiers;
import jakarta.inject.Inject;
@Controller
public class HelloWorldController {
@Inject
private ApplicationContext applicationContext;
private String output() {
DemoBean mySingletonBean1 = applicationContext.getBean(DemoBean.class, Qualifiers.byName("mySingletonBean1"));
DemoBean mySingletonBean2 = applicationContext.getBean(DemoBean.class, Qualifiers.byName("mySingletonBean2"));
DemoBean mySingletonBean3 = applicationContext.getBean(DemoBean.class, Qualifiers.byName("mySingletonBean3"));
StringBuilder builder = new StringBuilder();
builder.append(mySingletonBean1).append("\n");
builder.append(mySingletonBean2).append("\n");
builder.append(mySingletonBean3).append("\n");
return builder.toString();
}
@Get(value = "/hello", produces = MediaType.TEXT_PLAIN)
public String index() {
return output();
}
}
Step 6: Define main application class.
App.java
package com.sample.app;
import io.micronaut.runtime.Micronaut;
public class App {
public static void main(String[] args) {
Micronaut.run(App.class, args);
}
}
Total project structure looks like below.
Build the project using mvn package command.
Navigate to the folder where pom.xml is located and execute the command ‘mvn package’.
Upon command successful execution, you can see the jar file ‘micronaut-factory-annotation-demo-1-jar-with-dependencies.jar’ in project target folder.
$ls ./target/
classes maven-status
generated-sources micronaut-parallel-init-of-beans-1.jar
generated-test-sources original-micronaut-parallel-init-of-beans-1.jar
maven-archiver test-classes
Execute below command to start the application.
java -jar ./target/micronaut-parallel-init-of-beans-1.jar
You will see below messages in the console.
DemoBean constructor called for singletonBean2 DemoBean constructor called for singletonBean1
As we do not annotate ‘singletonBean3’ with @Parallel annotation, it will be initialized on demand. To confirm the same, open the url ‘http://localhost:8080/hello’ in browser, you will see below message in the console.
DemoBean constructor called for singletonBean3
You can download this application from this link.
No comments:
Post a Comment