Showing posts with label dagger. Show all posts
Showing posts with label dagger. Show all posts

Friday, 7 October 2022

How to configure Java Annotation Processor in Eclipse?

In this post, I am going to explain how to configure ‘dagger-compiler’ annotation processor in Eclipse.

 

Right click on the project -> properties.

 


 

Java Compiler -> Annotation Processing and select the checkbox ‘Enable annotation processing’.




Add plugin jar (For ex: dagger-compiler) to the factory path

Java Compiler -> Annotation Processing -> Factory Path.

 

Select the checkbox "Enable project specific settings" and add your JAR file to the list.

 


 

Apply the changes.

 

Clean and build the project….that’s it you are done.


Previous                                                 Next                                                 Home

Dagger 2 : hello world application

In this post, I will walk you through, how can we achieve dependency injection using Dagger library.

 

Application that we are going to develop

We are going to implement ‘DataPrinter’ application, that reads data from a data source and print it to the console. Here data source can be a MySQLDataSource, FileDataSource etc.,

 

To work with dagger, we need to use 'dagger-compiler' annotation processor to generate the code at compile time.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-compiler-plugin</artifactId>
	<version>${maven-compiler-plugin.version}</version>
	<configuration>
		<annotationProcessorPaths>
			<path>
				<groupId>com.google.dagger</groupId>
				<artifactId>dagger-compiler</artifactId>
				<version>${dagger.version}</version>
			</path>
		</annotationProcessorPaths>
	</configuration>
</plugin>

 

DataPrinter class looks like below.

 

DataPrinter.java
public class DataPrinter {

	private DataSource sqlSource;

	private DataSource fileSource;

	@Inject
	public DataPrinter(@Named("sql") DataSource sqlSource, @Named("file") DataSource fileSource) {
		this.sqlSource = sqlSource;
		this.fileSource = fileSource;
	}

	public void print() {
		String dataFromSQL = sqlSource.read();
		String dataFromFile = fileSource.read();

		System.out.println(dataFromSQL);
		System.out.println(dataFromFile);
	}

}

As you see the above snippet

a.   @Inject annotation is applied on the constructor to inhect the dependencies for sqlSource and fileSource.

b.   @Named annotation is used to inject the bean by a qualifier name . It helps to differentiate two objects of same type.

 

Define a module that provide dependencies

@Module
public class DependenciesProviderModule {
	
	@Provides
	@Named("sql")
	public static DataSource provideMySqlDataSource() {
		return new MySQLDataSource();
	}
	
	@Provides
	@Named("file")
	public static DataSource provideFileDataSource() {
		return new FileDataSource();
	}
}

Define a component to generate injector

@Component(modules = {DependenciesProviderModule.class})
public interface DataPrinterComponent {
	
	DataPrinter dataPrinter();

}

As you see above snippet, we passed the modules information to the component, Dagger build the DataPrinter dependencies using the modules specified in component definition.

 

Generate injector code

Navigate to the pom.xml file and execute the command ‘mvn compile’ to generate the code from annotations.




The classes starts with Dagger are generated by Dagger library. We can use ‘DaggerDataPrinterComponent’ class to get an instance of DataPrinterComponent.

DataPrinterComponent dataPrinterComponent = DaggerDataPrinterComponent.builder().build();
DataPrinter dataPrinter = dataPrinterComponent.dataPrinter();
dataPrinter.print();

Find the below working application.

 

Step 1: Create new maven project ‘dagger-hello-world’.

 

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>dagger-hello-world</artifactId>
	<version>1</version>


	<properties>
		<maven.compiler.target>1.8</maven.compiler.target>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
		<dagger.version>2.44</dagger.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>com.google.dagger</groupId>
			<artifactId>dagger</artifactId>
			<version>${dagger.version}</version>
		</dependency>


	</dependencies>

	<build>
		<plugins>
			<!-- Annotation processor for Dagger 2 -->
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>${maven-compiler-plugin.version}</version>
				<configuration>
					<annotationProcessorPaths>
						<path>
							<groupId>com.google.dagger</groupId>
							<artifactId>dagger-compiler</artifactId>
							<version>${dagger.version}</version>
						</path>
					</annotationProcessorPaths>
				</configuration>
			</plugin>

			<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 DataSource.

 

DataSource.java

 

package com.sample.app.interfaces;

public interface DataSource {
	
	public String read();

}

 

Step 4: Define DataSource implementations.

 

FileDataSource.java
package com.sample.app.interfaces.impl;

import com.sample.app.interfaces.DataSource;

public class FileDataSource implements DataSource{

	@Override
	public String read() {
		return "Hi there!!!!!";
	}

}

 

MySQLDataSource.java

package com.sample.app.interfaces.impl;

import com.sample.app.interfaces.DataSource;

public class MySQLDataSource implements DataSource{

	@Override
	public String read() {
		return "hello world!!!!!";
	}

}

 

Step 5: Define DataPrinter class.

 

DataPrinter.java
package com.sample.app.util;

import javax.inject.Inject;
import javax.inject.Named;

import com.sample.app.interfaces.DataSource;

public class DataPrinter {

	private DataSource sqlSource;

	private DataSource fileSource;

	@Inject
	public DataPrinter(@Named("sql") DataSource sqlSource, @Named("file") DataSource fileSource) {
		this.sqlSource = sqlSource;
		this.fileSource = fileSource;
	}

	public void print() {
		String dataFromSQL = sqlSource.read();
		String dataFromFile = fileSource.read();

		System.out.println(dataFromSQL);
		System.out.println(dataFromFile);
	}

}

 

Step 6: Define module.

 

DependenciesProviderModule.java

 

package com.sample.app.modules;

import javax.inject.Named;

import com.sample.app.interfaces.DataSource;
import com.sample.app.interfaces.impl.FileDataSource;
import com.sample.app.interfaces.impl.MySQLDataSource;

import dagger.Module;
import dagger.Provides;

@Module
public class DependenciesProviderModule {
	
	@Provides
	@Named("sql")
	public static DataSource provideMySqlDataSource() {
		return new MySQLDataSource();
	}
	
	@Provides
	@Named("file")
	public static DataSource provideFileDataSource() {
		return new FileDataSource();
	}
}

 

Step 7: Define DataPrinterComponent.

 

DataPrinterComponent.java

 

package com.sample.app.components;

import com.sample.app.modules.DependenciesProviderModule;
import com.sample.app.util.DataPrinter;

import dagger.Component;

@Component(modules = {DependenciesProviderModule.class})
public interface DataPrinterComponent {
	
	DataPrinter dataPrinter();

}

Step 8: Define main application class.

 

App.java

package com.sample.app;

import com.sample.app.components.DataPrinterComponent;
import com.sample.app.util.DataPrinter;
import com.sample.app.components.DaggerDataPrinterComponent;

public class App {
	
	public static void main(String[] args) {
		DataPrinterComponent dataPrinterComponent = DaggerDataPrinterComponent.builder().build();
		DataPrinter dataPrinter = dataPrinterComponent.dataPrinter();
		
		dataPrinter.print();
	}

}

Total project structure looks like below.



How to generate the jar file?

Navigate to the folder where pom.xml is located and execute below command.

mvn package

How to run the jar file?

‘jar’ file is located at target folder.

$ls -l target/*jar
-rw-r--r--  1 krishna  staff  49611 Oct  1 21:08 target/dagger-hello-world-1-jar-with-dependencies.jar
-rw-r--r--  1 krishna  staff  13103 Oct  1 21:08 target/dagger-hello-world-1.jar

As you see there are two jars generated one with dependencies and other without dependencies.

 

Run the jar with dependencies by executing below command.

java -jar target/dagger-hello-world-1-jar-with-dependencies.jar

$java -jar target/dagger-hello-world-1-jar-with-dependencies.jar
hello world!!!!!
Hi there!!!!!

You can download this application from this link.


References

https://dagger.dev/dev-guide/


Previous                                                 Next                                                 Home

Thursday, 6 October 2022

Dagger 2 tutorial

Dagger is a dependency injection framework written in Java, to ease the creation of reusable and interchangeable modules.

 

Unlike other frameworks (Like Spring, Google Guice) which rely on runtime reflection and proxies, Dagger is a fully static, compile-time dependency injection framework. Dagger uses the compile time data to implement dependency injection.

 

Following dependency is used for this tutorial.

<dependency>
	<groupId>com.google.dagger</groupId>
	<artifactId>dagger</artifactId>
	<version>2.4.4</version>
</dependency>

 

       Dagger 2 : hello world application
      How to configure Java Annotation Processor in Eclipse?

 

 

Previous                                                 Next                                                 Home