Saturday 13 May 2023

Micronaut: Custom type converters

In this post, let’s see how can we define custom type converters in Micronaut.

 

Let’s define a custom type converter, that read the employee details in csv format and map it to the employee object.

 

How to define custom type converter?

By implementing TypeConverter interface, we can define custom type converter.

 

Example

@Singleton
public class EmployeeConverter implements TypeConverter<String, Employee> {

  private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeConverter.class);

  @Override
  public Optional<Employee> convert(String str, Class<Employee> targetType, ConversionContext context) {
    try {
      return Optional.of(Employee.toEmployee(str));
    } catch (Exception e) {
      context.reject(str, e);
      LOGGER.error("{}", e);
      return Optional.empty();
    }
  }

}

 

Above snipper get an employee object from a string. If an exception occurs during binding, call reject(..) which propagates additional information to the container.

 

Find the below working application.

 

Step 1: Create new maven project ‘micronaut-custom-type-converter’.

 

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-custom-type-converter</artifactId>
  <version>1</version>

  <parent>
    <groupId>io.micronaut</groupId>
    <artifactId>micronaut-parent</artifactId>
    <version>3.7.3</version>
  </parent>


  <properties>
    <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.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>
    </dependency>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
    </dependency>

  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${maven-compiler-plugin.version}</version>
        <configuration>
          <annotationProcessorPaths>
            <path>
              <groupId>io.micronaut</groupId>
              <artifactId>micronaut-inject-java</artifactId>
            </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: Create application.yml file in src/main/resources folder.

application.yml

emp1: 1,Krishna,34,India
emp2: 2,Ram,35,Canada

 

Step 4: Define Employee model class.

 

Employee.java

package com.sample.app.model;

public class Employee {

  private Integer id;
  private String name;
  private Integer age;
  private String country;

  public Employee() {
  }

  public Employee(Integer id, String name, Integer age, String country) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.country = country;
  }

  public Integer getId() {
    return id;
  }

  public void setId(Integer id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Integer getAge() {
    return age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public String getCountry() {
    return country;
  }

  public void setCountry(String country) {
    this.country = country;
  }

  @Override
  public String toString() {
    return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", country=" + country + "]";
  }

  public static Employee toEmployee(final String str) {
    if (str == null) {
      throw new IllegalArgumentException("Can't get employee instance from null string");
    }
    String[] tokens = str.split(",");
    if (tokens.length != 4) {
      throw new IllegalArgumentException("Information missig to construct employee object");
    }

    try {
      Integer id = Integer.valueOf(tokens[0]);
      String name = tokens[1];
      Integer age = Integer.valueOf(tokens[2]);
      String country = tokens[3];

      return new Employee(id, name, age, country);

    } catch (Exception e) {
      throw e;
    }
  }

}

 

Step 5: Define EmployeeConverter.

 

EmployeeConverter.java

package com.sample.app.converters;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sample.app.model.*;

import io.micronaut.core.convert.ConversionContext;
import io.micronaut.core.convert.TypeConverter;
import jakarta.inject.Singleton;

@Singleton
public class EmployeeConverter implements TypeConverter<String, Employee> {

  private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeConverter.class);

  @Override
  public Optional<Employee> convert(String str, Class<Employee> targetType, ConversionContext context) {
    try {
      return Optional.of(Employee.toEmployee(str));
    } catch (Exception e) {
      context.reject(str, e);
      LOGGER.error("{}", e);
      return Optional.empty();
    }
  }

}

 

Step 6: Define AppConfig class.

 

AppConfig.java

 

package com.sample.app.configuration;

import com.sample.app.model.Employee;

import io.micronaut.context.annotation.Property;
import jakarta.inject.Singleton;

@Singleton
public class AppConfig {

  @Property(name = "emp1")
  protected Employee emp1;

  @Property(name = "emp2")
  protected Employee emp2;

  public Employee getEmp1() {
    return emp1;
  }

  public void setEmp1(Employee emp1) {
    this.emp1 = emp1;
  }

  public Employee getEmp2() {
    return emp2;
  }

  public void setEmp2(Employee emp2) {
    this.emp2 = emp2;
  }

}

 

Step 7: Define main application class.

 

App.java
package com.sample.app;

import com.sample.app.configuration.AppConfig;

import io.micronaut.context.ApplicationContext;

public class App {

  public static void main(String[] args) {

    try (ApplicationContext applicationContext = ApplicationContext.run()) {

      AppConfig appConfig = applicationContext.getBean(AppConfig.class);

      System.out.println(appConfig.getEmp1());
      System.out.println(appConfig.getEmp2());
    }

  }
}

 

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-custom-type-converter-1-jar-with-dependencies.jar’ in project target folder.

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

 

Execute below command to run the application.

$java -jar ./target/micronaut-custom-type-converter-1-jar-with-dependencies.jar
Employee [id=1, name=Krishna, age=34, country=India]
Employee [id=2, name=Ram, age=35, country=Canada]

 You can download this application from this link.


 


Previous                                                    Next                                                    Home

No comments:

Post a Comment