Annotation Type DecoratedWith
-
@Target(TYPE) @Retention(CLASS) public @interface DecoratedWith
Specifies a decorator to be applied to a generated mapper, which e.g. can be used to amend mappings performed by generated mapping methods.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.Examples
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 }
1. Component model 'default'
Referencing the original mapper in 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; } }
Using the decorated mapper
Nothing special needs to be done. When using
Mappers.getMapper( PersonMapper.class )
, the decorator is returned, with the injected original mapper.2. Component model 'spring'
Referencing the original mapper in the decorator
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; } }
Using the decorated mapper in the decorator
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
3. Component model 'jsr330' or 'jakarta'
Referencing the original mapper
JSR 330 / Jakarta Inject doesn't specify qualifiers and only allows to specifically name the beans. Hence, the generated implementation of the original mapper is annotated with
@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; } }
Using the decorated mapper in the decorator
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
- Author:
- Gunnar Morling
-
-
Element Detail
-
value
Class<?> value
The decorator type. Must be an abstract class that extends or implements the mapper type to which it is applied.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.- Returns:
- the decorator type
-
-