Comments (7)
We're aware of the difficulties in manually configuring the ConversionService
. The examples give an idea of how to do this "by hand". I agree that some form of fallback autoconfiguration would be convenient, especially for testing purposes in Spring Boot projects. However, I can't really see anything beyond what you've already provided in your example.
I'm happy to take a look at what WebMvcAutoConfiguration
does. Maybe we can replicate the ConversionService
creation and addition of the Converter
s. But I suspect the user will always have to at least create the ApplicationContext
themselves (via @ComponentScan
and/or manual @Bean
configuration).
from mapstruct-spring-extensions.
I played around with my tests to get a easily reusable context configuration for tests that need ConversionServiceAdapter, but do not have Spring Web autoconfigured. How about something like this:
Annotation to be placed on test classes:
@ComponentScan
@ImportAutoConfiguration(classes = MapStructAutoConfiguration.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MapStructTest {
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] basePackages();
}
AutoConfiguration:
@AutoConfiguration
public class MapStructAutoConfiguration {
@Bean
@ConditionalOnMissingBean(ConversionService.class)
ConversionService fallbackConversionService(List<Converter<?,?>> converters) {
var conversionService = new DefaultConversionService();
converters.forEach(conversionService::addConverter);
return conversionService;
}
}
Then test can look like:
@DataJpaTest
//this also works: @SpringBootTest(classes = MyTestConfig.class)
@MapStructTest(basePackages = "com.example.mappers")
class Test {
@Autowired
private ConversionServiceAdapter adapter;
}
This disadvantage of this would be that one needs to provide packages(s) of Mapper
s and ConversionServiceAdapter
to the annotation (in my example they reside in the same package). Any ideas on how to solve it? Could annotation processing help here by generating a class with the required @ComponentScan
packages and including that to the configuration?
Didn't spend too much time on the example, possibly some rough edges/useless annotations somewhere, but at least I have now a setup that can be easily reused between tests.
EDIT: Could also be worthwhile to investigate the option of enabling this autoconfiguration without explicitly adding the annotation.
EDIT2: Can use regular @Import
and @Configuration
variants instead of @ImportAutoConfiguration
& @AutoConfiguration
EDIT3: Come to think of it, having to define the packages for the annotation might not be such a bad thing. If we add @Inherited
to @MapStructTest
, users can opt to create their own meta-annotations that define the packages for their project. Also, instead of @MapStructTest
, @AutoConfigureMapStruct
could be more fitting to follow Spring conventions
from mapstruct-spring-extensions.
This looks nice. We can consider a separate module for testing purposes and provide this kind of thing. I'd be even more on board if we could indeed avoid using things like @AutoConfiguration
which are specific to Spring Boot and thus even make this available to teams that do "only" Spring core projects.
from mapstruct-spring-extensions.
I think it can work with plain Spring. At least it didn't need the @AutoConfiguration
. I can make a PR next week for a separate module. Or do you prefer to take over yourself?
from mapstruct-spring-extensions.
I've already started a branch. 😃 Could you do me a favor and play around with it in order to see whether this is what you're looking for? I tried doing it all with Spring core mechanisms for now which means e.g. there's no @ConditionalOnMissingBean
either.
from mapstruct-spring-extensions.
There's a problem with this when @SpringMapperConfig#conversionServiceBeanName
is used. I've had to use it since Spring Data REST and WebMvcAutoConfiguration both provide a ConversionService
bean. With yours (and mine) solution, the ConversionService
provided by the new configuration is not accepted by the ConversionServiceAdapter
due to mismatch in qualifiers. Not sure how it can be solved. I had to re-use the same qualifier in the new Configuration class.
Possibly some changes needed in how ConversionServiceAdapter
selects the ConversionService
if multiple are present.
Perhaps instead of:
public ConversionServiceAdapter(
@Qualifier("valueFromConversionServiceBeanName") @Lazy final ConversionService conversionService) {
this.conversionService = conversionService;
}
You do:
public ConversionServiceAdapter(@Lazy Map<String, ConversionService> conversionServices) {
this.conversionService = // select bean from Map
}
Where selection logic could be something like:
- If bean qualifier by
conversionServiceBeanName
is found, use it - If any bean other than the
basicConversionService
is found, use it - Use
basicConversionService
from mapstruct-spring-extensions.
conversionServiceBeanName
has been giving some headaches since the start. I'm curious whether we could also use this opportunity to rectify that. I'll play around with generating a version of the annotation based on the property. This could then even be used beyond testing.
from mapstruct-spring-extensions.
Related Issues (20)
- DelegatingConverter and CycleAvoidingMappingContext HOT 4
- Allow inherited DelegatingConverter to be processed HOT 1
- Not auto register converters after manually create a ConversionService bean. HOT 14
- Support SpringBoot3 HOT 1
- maven package jar but no class file in jar HOT 2
- Java version requisite is 11 ?
- Java version requisite is 11 ? HOT 2
- how can i use "Inverse mappings" HOT 1
- Problem of defining parent-child JPA mapping. HOT 3
- maven Compilation failed [JDK20 MAVEN3.9.2 ] javax.annotation.processing.Processor: Provider org.mapstruct.extensions.spring.converter.ConverterMapperProcessor could not be instantiated HOT 2
- ConversionServiceAdapterGenerator does not respect mapstruct.suppressGeneratorTimestamp
- Combining various default starters can result in multiple `ConversionService`s being in the `ApplicationContext`.
- How to inject Spring CustomComponent in Mapper interface? HOT 2
- Compiler Error with Qualified Mapping and Custom Converter - Duplicate Method Generation HOT 6
- Generate additional delegating mappers for @InheritInverseConfiguration HOT 5
- Name collision with same class name in different packages HOT 2
- 'No converter found' when injection ConversionService into Spring Service. / indirect reference to ConversionService HOT 6
- spring-beans vulnerability CVE-2022-22965 HOT 4
- Provide mechanism for adding annotations to generated code HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mapstruct-spring-extensions.