Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

MapStruct Mapper Injection in OSGi Blueprint

DZone's Guide to

MapStruct Mapper Injection in OSGi Blueprint

In this article, we look at these two open source technologies, and how they can help developers working on integration projects. Read on for more!

· Integration Zone ·
Free Resource

The State of API Integration 2018: Get Cloud Elements’ report for the most comprehensive breakdown of the API integration industry’s past, present, and future.

What Is MapStruct?

According to the MapStruct website:

MapStruct is a code generator that greatly simplifies the implementation of mappings between Java bean types based on a convention over configuration approach. The generated mapping code uses plain method invocations and thus is fast, type-safe, and easy to understand.

Inject MapStruct Mapper Into Blueprint OSGi

Such mappings are sometimes necessary for our integration projects. We also use OSGi to create our applications and Blueprint for dependency injection. The Blueprint Maven Plugin makes it very easy to use, and it even provides annotation support.

MapStruct supports component models like cdi, spring, and jsr330, so generated classes could be used as beans. Fortunately, Blueprint Maven Plugin uses annotations from JSR 330, such as Singleton or Named.

The only thing we have to do is to add the property componentModel with a value of jsr330 to a mapping interface:

@Mapper(componentModel = "jsr330")
public interface PersonMapper {
    Person toDomain(PersonDto personDto);
}

And now we can inject PersonMapper to our beans:

@Singleton
@AllArgsConstructor
public class CreatePersonHandler {
    private final PersonRepository personRepository;
    private final PersonMapper personMapper;

    // ...
}

The Blueprint Maven Plugin will generate an XML file with the bean PersonMapperImpl and inject it into CreatePersonHandler:

<?xml version="1.0" encoding="UTF-8"?><blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
    <bean id="createPersonHandler" class="com.github.alien11689.osgi.mapstructblueprint.CreatePersonHandler">
        <argument ref="personRepository"/>
        <argument ref="personMapperImpl"/>
    </bean>
    <bean id="personMapperImpl" class="com.github.alien11689.osgi.mapstructblueprint.PersonMapperImpl"/>
    <bean id="personRepository" class="com.github.alien11689.osgi.mapstructblueprint.PersonRepository"/>
</blueprint>

Generate All Mappers With JSR 330 Annotations

If you have multiple mappers, and all of them should be beans, then you can simply add one compiler argument in the configuration and all the mappers will have @Singleton and @Named annotations by default.

<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    ...
    <build>
        <plugins>
            ...
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArgs>
                        <compilerArg>
                             -Amapstruct.defaultComponentModel=jsr330
                        </compilerArg>
                    </compilerArgs>
                </configuration>
            </plugin>
            ...
        </plugins>
    </build>
</project>

Try it on Your Own

The code is available on GitHub.

Your API is not enough. Learn why (and how) leading SaaS providers are turning their products into platforms with API integration in the ebook, Build Platforms, Not Products from Cloud Elements.

Topics:
osgi ,blueprint ,java ,lombok ,integration

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}