Friday, 7 October 2022

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

No comments:

Post a Comment