@Target(value=TYPE) @Retention(value=SOURCE) public @interface DecoratedWith
A typical decorator implementation will be an abstract class and only implement/override a subset of the methods of the mapper type which it decorates. All methods not implemented or overridden by the decorator will be implemented by the code generator by delegating to the generated mapper implementation.
NOTE: The usage of decorated mappers differs depending on the selected component model.
NOTE: This annotation is not supported for the component model cdi
. Use CDI's own
@Decorator
feature instead.
NOTE: The decorator feature when used with component model jsr330
is considered experimental
and it may change in future releases.
For the examples below, consider the following mapper declaration:
@Mapper(componentModel = "...") @DecoratedWith(PersonMapperDecorator.class) public interface PersonMapper { @Mapping(target = "name", ignore = true) PersonDto personToPersonDto(Person person); AddressDto addressToAddressDto(Address address); // not touched by the decorator }
If a constructor with a single parameter accepting the type of the decorated mapper is present, a delegate with generated implementations of all the mapper methods will be passed to this constructor. A typical implementation will store the passed delegate in a field of the decorator and make use of it in the decorator methods:
public abstract class PersonMapperDecorator implements PersonMapper { private PersonMapper delegate; public PersonMapperDecorator(PersonMapper delegate) { this.delegate = delegate; } @Override public PersonDto personToPersonDto(Person person) { PersonDto dto = delegate.personToPersonDto( person ); dto.setName( person.getFirstName() + " " + person.getLastName() ); return dto; } }
Nothing special needs to be done. When using Mappers.getMapper( PersonMapper.class )
, the decorator
is returned, with the injected original mapper.
The generated implementation of the original mapper is annotated with the Spring annotation
@org.springframework.beans.factory.annotation.Qualifier("delegate")
. To autowire that bean in your decorator,
add that qualifier annotation as well:
public abstract class PersonMapperDecorator implements PersonMapper { @Autowired @org.springframework.beans.factory.annotation.Qualifier("delegate") private PersonMapper delegate; @Override public PersonDto personToPersonDto(Person person) { PersonDto dto = delegate.personToPersonDto( person ); dto.setName( person.getFirstName() + " " + person.getLastName() ); return dto; } }
The generated class that extends the decorator is annotated with Spring's @Primary
annotation. To autowire
the decorated mapper in the application, nothing special needs to be done:
@Autowired private PersonMapper personMapper; // injects the decorator, with the injected original mapper
JSR 330 doesn't specify qualifiers and only allows to specifically name the beans. Hence, the generated
implementation of the original mapper is annotated with
@javax.inject.Named("fully-qualified-name-of-generated-impl")
and @Singleton
(please note that when
using a decorator, the class name of the mapper implementation ends with an underscore). To inject that bean in your
decorator, add the same annotation to the delegate field (e.g. by copy/pasting it from the generated class):
public abstract class PersonMapperDecorator implements PersonMapper { @Inject @javax.inject.Named("org.examples.PersonMapperImpl_") private PersonMapper delegate; @Override public PersonDto personToPersonDto(Person person) { PersonDto dto = delegate.personToPersonDto( person ); dto.setName( person.getFirstName() + " " + person.getLastName() ); return dto; } }
Unlike with the other component models, the usage site must be aware if a mapper is decorated or not, as for
decorated mappers, the parameterless @javax.inject.Named
annotation must be added to select the
decorator to be injected:
@Inject @javax.inject.Named private PersonMapper personMapper; // injects the decorator, with the injected original mapper
public abstract Class<?> value
For component-model default
, the decorator type must either have a default constructor or a constructor
with a single parameter accepting the type of the decorated mapper.
Copyright © 2012-2016 Gunnar Morling; All rights reserved. Released under the Apache Software License 2.0.