-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
'No converter found' when injection ConversionService into Spring Service. / indirect reference to ConversionService #93
Comments
Have you tried injecting the |
just got some to test this a bit. Thanks for pointing me into the direction of #21. In fact I now think this is basically the same issue just that I had a Service-Layer in between that hid the real cause - still in cyclic dependency, but indirectly. Firstly the solution, if anyone stumbles upon the same issue. One solution is to either: @Mapper(config = MapperSpringConfig.class)
public abstract class ExampleMapper implements Converter<ExampleDTO, Example> {
@Lazy
@Autowired
ExampleService exampleService;
} Or inside the Service: @Service
public class ExampleService {
@Lazy
@Autowired
ConversionService conversionService;
// methods that do something ...
} This basically comes down to the same thing discussed in #21:
Furthermore, after reading among others: #22 and https://mapstruct.org/documentation/spring-extensions/reference/html/#mapperAsConverter it seems to be recommended to inject the @Mapper(config = MapperSpringConfig.class)
public abstract class ExampleMapper implements Converter<ExampleDTO, Example> {
// @Autowired
ConversionService conversionService;
@Autowired
public void setConversionService(ConversionService conversionService) {
this.conversionService = conversionService;
}
} This results in the same error. But this works: @Mapper(config = MapperSpringConfig.class)
public abstract class ExampleMapper implements Converter<ExampleDTO, Example> {
// @Autowired
MyAdapter conversionServiceAdapter;
@Autowired
public void setConversionServiceAdapter(MyAdapter conversionServiceAdapter) {
this.conversionServiceAdapter = conversionServiceAdapter;
}
} So how is the proper way to handle this (somehow injecting a ConversionService into a mapper) now? Inject the PS: after now knowing the actual issue now, I can see a couple of related issues, maybe it would be nice to add a docs entry about using ConversionService inside a mapper. |
Why would you want to inject the As for the various forms of injection: Ideally I'd want to use constructor injection, but MapStruct has no way of specifying this yet. I typically rely on field injection for things I can't put into the The underlying issue is that the |
I agree that direct injection does not make sense. Like the initial issue explains, I'm actually using a service in between. This was just to show the issue because it produces the same result. Maybe a little bit more explanation of what I'm trying to accomplish would help. Maybe there's another way to solve this (still trying to make it as short as possible): // ImageEntity.java
@Entity
public class ImageEntity {
// some fields ...
}
// ButtonEntity.class
@Entity
public class ButtonEntity {
ImageEntity background;
// ...
} // Image.class
public record Image(/* some fields */){}
// Button.class
public record Button(
Image background
// ...
){} // ButtonDTO
public record ButtonDTO(
int backgroundID
// ...
){} So when receiving the dto on a post it needs firstly needs to be converted back to a domain object. For this I have a Mapper: // ButtonDTOToButtonMapper.java
@Mapper(config = MapperSpringConfig.class)
public abstract class ButtonDTOToButtonMapper implements Converter<ButtonDTO Button> {
@Mapping(target = "background", source = "backgroundId", qualifiedByName = "mapBackground"),
public abstract Field convert(@Nullable ViewController.FieldDTO fieldDTO);
@Autowired
@Lazy // here the issue started, without using @Lazy
private ImageService imageService;
@Named("mapBackground")
public Image mapBackground(Integer backgroundId) {
// service required to get the actual object by id
return imageService.findById(backgroundId);
}
} The service encapsulates all the Entity/DB specific logic. // ImageService.class
@Service
@RequiredArgsConstructor
public class ImageService {
private final ImageRepository repository;
private final ConversionService conversionService; // ConversionService is required here
@Override
public Image findById(int id) {
ImageEntity entity = repository.findById(id).orElse(null);
// do some stuff
return conversionService.convert(entity, Image.class);
}
} The ImageEntity -> Image mapper is just a simple 1 to 1 mapping: // ImageEntityToImageMapper.java
@Mapper(config = MapperSpringConfig.class)
public interface ImageEntityToImageMapper extends Converter<ImageEntity, Image> {
Image convert(@Nullable ImageEntity imageEntity);
} So one way to deal with this / work more with Hope this helps to understand my reasoning. |
Thanks, that makes some sense. Some of the Mappers function as enrichers with DB information. I still think the best option in this scenario is using |
OK, thanks. |
Already looked through existing issues but couldn't find anything. (Although this helped me with some other common issues like componentmodel=spring, central config, Injecting the Interface instead of the Adapter, ...)
I created an MVP to show an issue I had in one of my applications.
Given a Mapper like this:
With Services:
Central Config:
When running the application like this it results in the following error:
But when changing to the other Mapper (ExampleServiceWithoutConversionService.java in this example) then everything works. So something gets broken when injecting a Service into a Mapper that uses ConversionService.
(PS: In the real application this Service also injects a lot of other things like jpa repositories and does more, but not relevant for this problem as this does not result in the issue mentioned - so I also don't think its a Spring Context problem because injecting Repositories and other Services works but something seems special about ConversionService)
Full source of this example available on my Github: https://github.com/SimonFischer04/spring-mapstruct-issue
The text was updated successfully, but these errors were encountered: