Monday 23 January 2023

Micronaut: Replace a bean factory using @Replaces annotation

@Replaces annotation can be used to replace a bean factory.

@Factory
public class BooksBeanFactoryV1 {
	
	@Singleton
	@Named("java_tutorial_1")
	public Book javaBook1() {
		Book book1 = new Book("Complete reference to Java");
		return book1;
	}
	
	@Singleton
	@Named("java_tutorial_2")
	public Book javaBook2() {
		Book book1 = new Book("Java for beginners");
		return book1;
	}
	
	@Singleton
	@Named("c_tutorial")
	public String cBook() {
		return new String("Let us C");
	}

}


@Factory
@Replaces(factory = BooksBeanFactoryV1.class)
public class BooksBeanFactoryV2 {

	@Singleton
	@Named("java_tutorial_1")
	public Book javaBook() {
		Book book1 = new Book("Programming for beginners (https://self-learning-java-tutorial.blogspot.com)");
		return book1;
	}
}

 

In this example, BooksBeanFactoryV1#cBook() is not replaced because this factory does not have a factory method that returns a String. But other methods javaBook1, javaBook2 will be replaced.

 

Find the below working application.

 

Step 1: Create new maven project ‘micronaut-replace-factory’.

 

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-replace-factory</artifactId>
	<version>1</version>

	<properties>
		<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
		<micronaut.version>3.7.1</micronaut.version>

		<maven.compiler.target>15</maven.compiler.target>
		<maven.compiler.source>15</maven.compiler.source>
	</properties>

	<dependencies>

		<dependency>
			<groupId>io.micronaut</groupId>
			<artifactId>micronaut-inject-java</artifactId>
			<version>${micronaut.version}</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>

			<plugin>
				<artifactId>maven-assembly-plugin</artifactId>
				<configuration>
					<archive>
						<manifest>
							<mainClass>com.sample.app.App</mainClass>
						</manifest>
					</archive>
					<descriptorRefs>
						<descriptorRef>jar-with-dependencies</descriptorRef>
					</descriptorRefs>
				</configuration>

				<executions>
					<execution>
						<id>make-assembly</id>
						<phase>package</phase>
						<goals>
							<goal>single</goal>
						</goals>
					</execution>
				</executions>
			</plugin>

		</plugins>
	</build>
</project>

 

Step 3: Define Book class.

 

Book.java

package com.sample.app.beans;

public class Book {

	private String title;

	public Book(String title) {
		this.title = title;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	@Override
	public String toString() {
		return "Book [title=" + title + "]";
	}

}

 

Step 4: Define bean factory classes.

 

BooksBeanFactoryV1.java

package com.sample.app.bean.factories;

import com.sample.app.beans.Book;

import io.micronaut.context.annotation.Factory;
import jakarta.inject.Named;
import jakarta.inject.Singleton;

@Factory
public class BooksBeanFactoryV1 {
	
	@Singleton
	@Named("java_tutorial_1")
	public Book javaBook1() {
		Book book1 = new Book("Complete reference to Java");
		return book1;
	}
	
	@Singleton
	@Named("java_tutorial_2")
	public Book javaBook2() {
		Book book1 = new Book("Java for beginners");
		return book1;
	}
	
	@Singleton
	@Named("c_tutorial")
	public String cBook() {
		return new String("Let us C");
	}

}

BooksBeanFactoryV2.java

package com.sample.app.bean.factories;

import com.sample.app.beans.Book;

import io.micronaut.context.annotation.Factory;
import io.micronaut.context.annotation.Replaces;
import jakarta.inject.Named;
import jakarta.inject.Singleton;

@Factory
@Replaces(factory = BooksBeanFactoryV1.class)
public class BooksBeanFactoryV2 {

	@Singleton
	@Named("java_tutorial_1")
	public Book javaBook() {
		Book book1 = new Book("Programming for beginners (https://self-learning-java-tutorial.blogspot.com)");
		return book1;
	}
}

Step 5: Define main application class.

 

App.java

package com.sample.app;

import com.sample.app.beans.Book;

import io.micronaut.context.ApplicationContext;
import io.micronaut.inject.qualifiers.Qualifiers;;

public class App {

	public static void main(String[] args) {
		try (ApplicationContext applicationContext = ApplicationContext.run()) {
			Book javaTutorial = applicationContext.getBean(Book.class, Qualifiers.byName("java_tutorial_1"));
			String cTutorial = applicationContext.getBean(String.class, Qualifiers.byName("c_tutorial"));

			System.out.println(javaTutorial);
			System.out.println(cTutorial);

			System.out.println(
					"\n\nAs BooksBeanFactoryV1 is replaced with BooksBeanFactoryV2, getting a bean with name 'java_tutorial_2' will throw NoSuchBeanException");

			try {
				javaTutorial = applicationContext.getBean(Book.class, Qualifiers.byName("java_tutorial_2"));
			} catch (Exception e) {
				e.printStackTrace();
			}

		}
	}
}

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-replace-factory-1-jar-with-dependencies.jar’ in project target folder.

$ ls ./target/
archive-tmp
classes
generated-sources
maven-archiver
maven-status
micronaut-replace-factory-1-jar-with-dependencies.jar
micronaut-replace-factory-1.jar
test-classes

Execute below command to run the application.

java -jar ./target/micronaut-replace-factory-1-jar-with-dependencies.jar
$ java -jar ./target/micronaut-replace-factory-1-jar-with-dependencies.jar
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Book [title=Programming for beginners (https://self-learning-java-tutorial.blogspot.com)]
Let us C


As BooksBeanFactoryV1 is replaced with BooksBeanFactoryV2, getting a bean with name 'java_tutorial_2' will throw NoSuchBeanException
io.micronaut.context.exceptions.NoSuchBeanException: No bean of type [com.sample.app.beans.Book] exists for the given qualifier: @Named('java_tutorial_2'). Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
	at io.micronaut.context.DefaultBeanContext.resolveBeanRegistration(DefaultBeanContext.java:2805)
	at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:1617)
	at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:867)
	at io.micronaut.context.DefaultBeanContext.getBean(DefaultBeanContext.java:852)
	at com.sample.app.App.main(App.java:22)

You can download this application from this link.

Can I replace one or more factory methods but retain the rest?

Yes, we can do. By applying the @Replaces annotation on the method(s) and denote the factory to apply to, we can replace one or more factory methods and retain the rest.

@Factory
public class BooksBeanFactoryV2 {

	@Singleton
	@Named("java_tutorial_1")
	@Replaces(value = Book.class, factory = BooksBeanFactoryV1.class, named = "java_tutorial_1")
	public Book javaBook() {
		Book book1 = new Book("Programming for beginners (https://self-learning-java-tutorial.blogspot.com)");
		return book1;
	}
}

 

 


Previous                                                    Next                                                    Home

No comments:

Post a Comment