Skip to content

Commit cac4d98

Browse files
119 Improvement: Customize class name and bean name for ConverterRegistrationConfiguration
Added a way to define custom class name for ConverterRegistrationConfiguration
1 parent 85744b1 commit cac4d98

File tree

13 files changed

+264
-22
lines changed

13 files changed

+264
-22
lines changed

annotations/src/main/java/org/mapstruct/extensions/spring/SpringMapperConfig.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,20 @@
1414
@Target(ElementType.TYPE)
1515
@Retention(RetentionPolicy.SOURCE)
1616
public @interface SpringMapperConfig {
17+
18+
String DEFAULT_CONVERSION_SERVICE_BEAN_NAME = "conversionService";
19+
String DEFAULT_ADAPTER_CLASS_NAME = "ConversionServiceAdapter";
20+
String DEFAULT_CONFIGURATION_CLASS_NAME = "ConverterRegistrationConfiguration";
21+
22+
/**
23+
* The class name for the generated Configuration class,
24+
* which is performing auto-registration of converters/mappers
25+
* to Spring's {@link org.springframework.core.convert.ConversionService}.
26+
*
27+
* @return The class name for the generated Configuration.
28+
*/
29+
String converterRegistrationConfigurationClassName() default DEFAULT_CONFIGURATION_CLASS_NAME;
30+
1731
/**
1832
* The package name for the generated Adapter between the MapStruct mappers and Spring's {@link
1933
* org.springframework.core.convert.ConversionService}. If omitted or empty, the package name will
@@ -29,15 +43,15 @@
2943
*
3044
* @return The class name for the generated Adapter.
3145
*/
32-
String conversionServiceAdapterClassName() default "ConversionServiceAdapter";
46+
String conversionServiceAdapterClassName() default DEFAULT_ADAPTER_CLASS_NAME;
3347

3448
/**
3549
* The bean name for the Spring {@link org.springframework.core.convert.ConversionService} to use.
3650
*
3751
* @return The bean name for the Spring {@link
3852
* org.springframework.core.convert.ConversionService}.
3953
*/
40-
String conversionServiceBeanName() default "";
54+
String conversionServiceBeanName() default DEFAULT_CONVERSION_SERVICE_BEAN_NAME;
4155

4256
/**
4357
* To set if the Lazy annotation will be added to the ConversionService's usage in the
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
dependencies {
2+
annotationProcessor project(":extensions")
3+
implementation projects.examples.model
4+
implementation projects.annotations
5+
6+
testImplementation libs.assertj
7+
testImplementation libs.bundles.junit.jupiter
8+
implementation libs.jsr250
9+
implementation libs.mapstruct.core
10+
annotationProcessor libs.mapstruct.processor
11+
implementation libs.spring.context
12+
implementation libs.spring.core
13+
testImplementation libs.spring.test
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.mapstruct.extensions.spring.example.customconfiguration;
2+
3+
import org.mapstruct.Mapper;
4+
import org.mapstruct.Mapping;
5+
import org.springframework.core.convert.converter.Converter;
6+
import org.mapstruct.extensions.spring.example.Car;
7+
import org.mapstruct.extensions.spring.example.CarDto;
8+
9+
@Mapper(config = MapperSpringConfig.class)
10+
public interface CarMapper extends Converter<Car, CarDto> {
11+
@Mapping(target = "seats", source = "seatConfiguration")
12+
CarDto convert(Car car);
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.mapstruct.extensions.spring.example.customconfiguration;
2+
3+
import org.mapstruct.MapperConfig;
4+
import org.mapstruct.extensions.spring.SpringMapperConfig;
5+
6+
@MapperConfig(componentModel = "spring", uses = ConversionServiceAdapter.class)
7+
@SpringMapperConfig(
8+
converterRegistrationConfigurationClassName = "MyConfiguration",
9+
// conversionServiceBeanName = "conversionService",
10+
generateConverterScan = true)
11+
public interface MapperSpringConfig {
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.mapstruct.extensions.spring.example.customconfiguration;
2+
3+
import org.mapstruct.Mapper;
4+
import org.mapstruct.Mapping;
5+
import org.mapstruct.extensions.spring.example.SeatConfiguration;
6+
import org.mapstruct.extensions.spring.example.SeatConfigurationDto;
7+
import org.springframework.core.convert.converter.Converter;
8+
9+
@Mapper(config = MapperSpringConfig.class)
10+
public interface SeatConfigurationMapper extends Converter<SeatConfiguration, SeatConfigurationDto> {
11+
@Mapping(target = "seatCount", source = "numberOfSeats")
12+
@Mapping(target = "material", source = "seatMaterial")
13+
SeatConfigurationDto convert(SeatConfiguration seatConfiguration);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package org.mapstruct.extensions.spring.example.customconfiguration;
2+
3+
import org.mapstruct.Mapper;
4+
import org.mapstruct.extensions.spring.example.Wheel;
5+
import org.mapstruct.extensions.spring.example.WheelDto;
6+
import org.springframework.core.convert.converter.Converter;
7+
8+
@Mapper(config = MapperSpringConfig.class)
9+
public interface WheelMapper extends Converter<Wheel, WheelDto> {
10+
@Override
11+
WheelDto convert(Wheel source);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.mapstruct.extensions.spring.example.customconfiguration;
2+
3+
import java.util.List;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.extensions.spring.example.WheelDto;
6+
import org.mapstruct.extensions.spring.example.Wheels;
7+
import org.springframework.core.convert.converter.Converter;
8+
9+
@Mapper(config = MapperSpringConfig.class)
10+
public interface WheelsDtoListMapper extends Converter<List<WheelDto>, Wheels> {
11+
@Override
12+
Wheels convert(List<WheelDto> source);
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.mapstruct.extensions.spring.example.customconfiguration;
2+
3+
import java.util.List;
4+
import org.mapstruct.Mapper;
5+
import org.mapstruct.extensions.spring.example.Wheel;
6+
import org.mapstruct.extensions.spring.example.WheelDto;
7+
import org.mapstruct.extensions.spring.example.Wheels;
8+
import org.springframework.core.convert.converter.Converter;
9+
10+
@Mapper(config = MapperSpringConfig.class, imports = Wheel.class)
11+
public interface WheelsMapper extends Converter<Wheels, List<WheelDto>> {
12+
@Override
13+
List<WheelDto> convert(Wheels source);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package org.mapstruct.extensions.spring.example;
2+
3+
import org.junit.jupiter.api.Test;
4+
import org.junit.jupiter.api.extension.ExtendWith;
5+
import org.mapstruct.extensions.spring.example.customconfiguration.ConversionServiceAdapter;
6+
import org.mapstruct.extensions.spring.example.customconfiguration.ConverterScan;
7+
import org.mapstruct.extensions.spring.example.customconfiguration.MapperSpringConfig;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.context.annotation.Bean;
10+
import org.springframework.context.annotation.ComponentScan;
11+
import org.springframework.context.annotation.Configuration;
12+
import org.springframework.core.convert.ConversionService;
13+
import org.springframework.core.convert.TypeDescriptor;
14+
import org.springframework.core.convert.support.DefaultConversionService;
15+
import org.springframework.test.context.junit.jupiter.SpringExtension;
16+
17+
import java.util.ArrayList;
18+
import java.util.List;
19+
20+
import static org.assertj.core.api.BDDAssertions.then;
21+
import static org.mapstruct.extensions.spring.example.CarType.OTHER;
22+
import static org.mapstruct.extensions.spring.example.SeatMaterial.LEATHER;
23+
import static org.mapstruct.extensions.spring.example.WheelPosition.RIGHT_FRONT;
24+
25+
@ExtendWith(SpringExtension.class)
26+
public class ConversionServiceAdapterIntegrationTest {
27+
private static final String TEST_MAKE = "Volvo";
28+
private static final CarType TEST_CAR_TYPE = OTHER;
29+
private static final int TEST_NUMBER_OF_SEATS = 5;
30+
private static final SeatMaterial TEST_SEAT_MATERIAL = LEATHER;
31+
private static final int TEST_DIAMETER = 20;
32+
private static final WheelPosition TEST_WHEEL_POSITION = RIGHT_FRONT;
33+
34+
@Autowired
35+
private ConversionService conversionService;
36+
37+
@Configuration
38+
@ComponentScan("org.mapstruct.extensions.spring.example.customconfiguration")
39+
static class ScanConfiguration {
40+
@Bean
41+
public ConversionService conversionService() {
42+
return new DefaultConversionService();
43+
}
44+
}
45+
46+
@Test
47+
void shouldKnowAllMappers() {
48+
then(conversionService.canConvert(Car.class, CarDto.class)).isTrue();
49+
then(conversionService.canConvert(SeatConfiguration.class, SeatConfigurationDto.class)).isTrue();
50+
then(conversionService.canConvert(Wheel.class, WheelDto.class)).isTrue();
51+
then(conversionService.canConvert(Wheels.class, List.class)).isTrue();
52+
then(conversionService.canConvert(List.class, Wheels.class)).isTrue();
53+
then(conversionService.canConvert(
54+
TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(WheelDto.class)),
55+
TypeDescriptor.valueOf((Wheels.class))))
56+
.isTrue();
57+
}
58+
59+
@Test
60+
void shouldMapAllAttributes() {
61+
// Given
62+
final Car car = new Car();
63+
car.setMake(TEST_MAKE);
64+
car.setType(TEST_CAR_TYPE);
65+
final SeatConfiguration seatConfiguration = new SeatConfiguration();
66+
seatConfiguration.setSeatMaterial(TEST_SEAT_MATERIAL);
67+
seatConfiguration.setNumberOfSeats(TEST_NUMBER_OF_SEATS);
68+
car.setSeatConfiguration(seatConfiguration);
69+
final Wheels wheels = new Wheels();
70+
final ArrayList<Wheel> wheelsList = new ArrayList<>();
71+
final Wheel wheel = new Wheel();
72+
wheel.setDiameter(TEST_DIAMETER);
73+
wheel.setPosition(TEST_WHEEL_POSITION);
74+
wheelsList.add(wheel);
75+
wheels.setWheelsList(wheelsList);
76+
car.setWheels(wheels);
77+
78+
// When
79+
final CarDto mappedCar = conversionService.convert(car, CarDto.class);
80+
81+
// Then
82+
then(mappedCar).isNotNull();
83+
then(mappedCar.getMake()).isEqualTo(TEST_MAKE);
84+
then(mappedCar.getType()).isEqualTo(String.valueOf(TEST_CAR_TYPE));
85+
final SeatConfigurationDto mappedCarSeats = mappedCar.getSeats();
86+
then(mappedCarSeats).isNotNull();
87+
then(mappedCarSeats.getSeatCount()).isEqualTo(TEST_NUMBER_OF_SEATS);
88+
then(mappedCarSeats.getMaterial()).isEqualTo(String.valueOf(TEST_SEAT_MATERIAL));
89+
final WheelDto expectedWheelDto = new WheelDto();
90+
expectedWheelDto.setPosition(String.valueOf(TEST_WHEEL_POSITION));
91+
expectedWheelDto.setDiameter(TEST_DIAMETER);
92+
then(mappedCar.getWheels()).hasSize(1).containsExactly(expectedWheelDto);
93+
}
94+
95+
@Test
96+
void shouldMapGenericSourceType() {
97+
// Given
98+
final WheelDto dto = new WheelDto();
99+
dto.setPosition(String.valueOf(TEST_WHEEL_POSITION));
100+
dto.setDiameter(TEST_DIAMETER);
101+
final List<WheelDto> dtoList = new ArrayList<>();
102+
dtoList.add(dto);
103+
104+
// When
105+
final Wheels convertedWheels = conversionService.convert(dtoList, Wheels.class);
106+
107+
// Then
108+
final Wheel expectedWheel = new Wheel();
109+
expectedWheel.setPosition(TEST_WHEEL_POSITION);
110+
expectedWheel.setDiameter(TEST_DIAMETER);
111+
then(convertedWheels).isNotNull().hasSize(1).containsExactly(expectedWheel);
112+
}
113+
}

extensions/src/main/java/org/mapstruct/extensions/spring/converter/ConversionServiceAdapterDescriptor.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
package org.mapstruct.extensions.spring.converter;
22

33
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
4+
import static org.mapstruct.extensions.spring.SpringMapperConfig.DEFAULT_CONFIGURATION_CLASS_NAME;
5+
import static org.mapstruct.extensions.spring.SpringMapperConfig.DEFAULT_CONVERSION_SERVICE_BEAN_NAME;
46

57
import com.squareup.javapoet.ClassName;
68
import java.util.List;
79

810
public class ConversionServiceAdapterDescriptor {
11+
public static final String DEFAULT_CONVERTER_SCAN_CLASS_NAME = "ConverterScan";
12+
public static final String DEFAULT_CONVERTER_SCANS_CLASS_NAME = "ConverterScans";
13+
914
private ClassName adapterClassName;
10-
private String conversionServiceBeanName;
15+
private String conversionServiceBeanName = DEFAULT_CONVERSION_SERVICE_BEAN_NAME;
1116
private List<FromToMapping> fromToMappings;
1217
private boolean lazyAnnotatedConversionServiceBean;
18+
private String configurationClassName = DEFAULT_CONFIGURATION_CLASS_NAME;
1319

1420
private boolean generateConverterScan;
1521

1622
boolean hasNonDefaultConversionServiceBeanName() {
17-
return isNotEmpty(getConversionServiceBeanName());
23+
return isNotEmpty(getConversionServiceBeanName())
24+
&& !DEFAULT_CONVERSION_SERVICE_BEAN_NAME.equals(getConversionServiceBeanName());
1825
}
1926

2027
public ClassName getAdapterClassName() {
@@ -56,6 +63,11 @@ public ConversionServiceAdapterDescriptor lazyAnnotatedConversionServiceBean(
5663
return this;
5764
}
5865

66+
public ConversionServiceAdapterDescriptor configurationClassName(
67+
final String configurationClassName) {
68+
this.configurationClassName = configurationClassName;
69+
return this;
70+
}
5971

6072
public boolean isGenerateConverterScan() {
6173
return generateConverterScan;
@@ -67,14 +79,14 @@ public ConversionServiceAdapterDescriptor generateConverterScan(final boolean ge
6779
}
6880

6981
public ClassName getConverterScanClassName() {
70-
return ClassName.get(getAdapterClassName().packageName(), "ConverterScan");
82+
return ClassName.get(getAdapterClassName().packageName(), DEFAULT_CONVERTER_SCAN_CLASS_NAME);
7183
}
7284

7385
public ClassName getConverterScansClassName() {
74-
return ClassName.get(getAdapterClassName().packageName(), "ConverterScans");
86+
return ClassName.get(getAdapterClassName().packageName(), DEFAULT_CONVERTER_SCANS_CLASS_NAME);
7587
}
7688

7789
public ClassName getConverterRegistrationConfigurationClassName() {
78-
return ClassName.get(getAdapterClassName().packageName(), "ConverterRegistrationConfiguration");
90+
return ClassName.get(getAdapterClassName().packageName(), configurationClassName);
7991
}
8092
}

0 commit comments

Comments
 (0)