How can i combine Guice and Mapstruct? - java

I'm using jersey and Guice DI and I want to use Mapstruct interfaces
with #Inject annotation.
So is there some way to force Guice to autowire Mapstruct interface implementations ?

You can configure the implementations of the Mappers to be annotated with JSR 330 annotation by using #Mapper(componentModel = "jsr330"). You can find more information in the reference documentation.
You can then bind the Mapper interface with the implementation class in your modules.
One way to bind them is to use Guice Linked Bindings:
bind(MyDtoMapper.class).to(MyDtoMapperImpl.class)
Another way to bind them is to use Instance Bindings:
bind(MyDtoMapper.class).toInstance(MyDtoMapper.INSTANCE)

Ran into issues with using Guice and the jsr330 componentModel, though I don't recall what they were exactly. My use case was a bit more complex because I needed to pass in another service to a mapper decorator as well. Should work for your simple case as well. Ended up doing provider methods in the Guice Module, like so:
public YourModule extends AbstractModule {
//With Decorator
#Provides
#Singleton
FooMapper providesFooMapper(RequiredService requiredSvc) {
FooMapper mapper = Mappers.getMapper(FooMapper.class);
((FooMapperDecorator) mapper).setRequiredService(requiredSvc);
return mapper;
}
//Simple Mapper with no dependencies
#Provides
#Singleton
BarMapper providesBarMapper() {
return Mappers.getMapper(BarMapper.class);
}
}
Works without a hitch, though I would like for the simple case to be handled by MapStruct cleanly at some point. I'll also note that I only use constructor injection; should work the same for setter injection but YMMV.

Thx #Filip. So yeah #Mapper(componentModel = "jsr330") almost made all work only thing I had to create binding for each mapper that I use directly in my code bind(MyDtoMapper.class).toInstance(MyDtoMapper.INSTANCE) and INSTANCE is declared in MyDtoMapper interface this way: MyDtoMapper INSTANCE = Mappers.getMapper( MyDtoMapper.class );

Related

Using Spring bean vs a static instance pattern for Mapstruct

I know that you can use the annotation #Mapper(componentModel = “spring”) to use Spring to manage/inject the mapper dependency. My question is, are there any advantages to this approach vs declaring an instance variable within the mapper class itself:
#Mapper
public interface SomeMapper {
SomeMapper INSTANCE = Mappers.getMapper(SomeMapper.class);
SomethingElse mapSomethingToSomethingElse(Something something);
}
...
// Clients using mapper
SomethingElse result = SomeMapper.INSTANCE.mapSomethingToSomethingElse(input);
When using Spring dependency injection to inject mappers, you will end up adding extra constructor arguments/instance fields which is desirable as it makes it more obvious that a class is starting to rely on too many dependencies and should most likely be refactored (eg. think about Sonar's rule 'Too many parameters').
Another advantage is that since you're registering the mappers as beans in the Spring context, you can leverage the framework capabilities to easily inject dependencies in your mappers, customize all mappers at runtime through the BeanFactoryPostProcessor and rely on all the other framework abstractions that seem fit.
I'd say since you're already using Spring in your application, there is pretty much no reason to not register the mappers as Spring beans and inject them the DI way rather than turning them into static utils.

Rest endpoint defined in annotation

I'm using a bunch of microservices in my project. These microservices all share one common endpoint that returns an object which has been parsed through XML.
Now I'd love to have some kind of default method defined within the Annotation like this:
#RestController
public #interface ComaModule {
Class<? extends Object> clazz();
#RequestMapping("/descriptor")
default ModuleDescriptor getDescriptor() {
ModuleXmlUnmarshaller moduleXmlUnmarshaller = new ModuleXmlUnmarshaller(clazz());
Optional<ModuleDescriptor> moduleDescriptorOptional = moduleXmlUnmarshaller.findModuleDescriptor();
return moduleDescriptorOptional.orElse(null);
}
}
That does not work since I am not able to have a method definition in my annotation. So the hard stuff is that I want to keep #RequestMapping("/descriptor") for this.
In fact I want some kind of aspect for every RestController I use. I read about AOP for Spring and Proxy but thought I might be able to achieve this with Annotations.
May be you can try adding annotation processor class, where you can write the code which have in your post and achieve what your goal.

Injecting dependency based on a value in config file

I have a class which takes a configuration interface implementation through DI.
#Inject
private PRCConfiguration prcConfig;
There are various implementations of the PRCConfiguration interface. Currently it is injecting the default implementation. I wish to create a value in a config text file which will define what particular implementation of PRCCOnfiguration to inject.
I wish the #Inject notation to verify what value is in the config file, and based on that inject the particular implementation.
I believe we can annotate different implementation through qualifiers and then inject, such as
#Inject #NewImplementation
private PRCConfiguration prcConfig;
But again i am injecting on compiletime through hard coding.
My config file would be something like
"injectconfig":"NewImplementation"
to inject the #NewImplementation implementation, subsequently if i want a different implementation to be injected. I could just change config file value as
"injectconfig":"DifferentImplementation"
and the different implementation will be injected.
Is what i require possible through CDI?
You can use producer methods to achieve something like that.
Basically you just have to create a CDI bean which a method that returns the correct configuration instance and annotate it with #Produces.
Something like this:
#ApplicationScoped
public class ConfigurationProducer {
#Produces
#ApplicationScoped
public PRCConfiguration getConfig() {
if( someCondition ) {
return new NewConfigurationImpl();
}
else {
return new OldConfigurationImpl();
}
}
}
In this case you should annotated both implementations with #Vetoed or you will get ambiguous dependencies errors. Using #Vetoed on the implementations will tell CDI that using the producer is the only way to obtain PRCConfiguration instances.

Custom object mapper for Websockets in Spring 4

I'm using Spring 4 and was following the Rossen Stoyanchev's blog post about using websockets in Spring. I was able to get everything working but I'm not sure what the best way to use a custom object mapper when sending application/json.
I'm injecting a SimpMessageSendingOperations and calling convertAndSend. I'm not positive but I'm pretty sure I'm getting a SimpMessagingTemplate (it implements SimpMessageSendingOperations) which contains a setMessageConverter. This method takes a MessageConverter and there is a MappingJackson2MessageConverter class but of course it uses it's own internal ObjectMapper which cannot be redefined.
So what it looks like I have to do is create a custom MessageConverter and define my custom ObjectMapper within it so I can pass it to an instance of SimpMessagingTemplate that I can then inject into my classes.
This seems like it would work, but also more involved than I expected. Am I overlooking something?
Looks like it is possible, but will be made easier in Spring 4.0.1
See - https://jira.springsource.org/browse/SPR-11184
Quote from the bug report above.
In the mean time, with #EnableWebSocketMessageBroker setup you can:
remove the annotation
extend WebSocketMessageBrokerConfigurationSupport instead of implementing WebSocketMessageBrokerConfigurer
override brokerMessageConverter() method and remember to keep #Bean in the overriding method
Nowadays you can do it like this:
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
#Override
public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
// Avoid creating many ObjectMappers which have the same configuration.
converter.setObjectMapper(getMyCustomObjectMapper());
messageConverters.add(converter);
// Don't add default converters.
return false;
}
...
}
Unfortunately ObjectMapper cannot be given directly to MappingJackson2MessageConverter's constructor, meaning it will first create a useless ObjectMapper.

How do I wrap instances produced by Guice, while not creating them myself but have Guice inject dependencies as needed?

I want to use Guice to produce instances (actually singletons/single instances for the module/dependency injection context), but have some of the managed instances being wrapped in a proxy.
The idea behind this is to add a synchronization layer around a few items which deal with "one at a time" resources. The only solution I've come up with is to create two Injectors.
Given the code below,
public class ApplicationContext {
private Injector injector;
public <T> T get(Class<? extends T> cls) {
return injector.getInstance(cls);
}
public ApplicationContext() {
injector = Guice.createInjector(new Module() {
binder.bind(InterfaceOne.class).to(ImplementationOne.class);
binder.bind(InterfaceTwo.class).to(ImplementationTwo.class);
binder.bind(InterfaceThree.class).to(ImplementationThree.class);
});
}
}
}
where ImplementationThree depends on InterfaceTwo, and ImplementationTwo in turn depends on InterfaceOne.
What I want now, is that after ImplementationTwo is instantiated, I want to wrap it in a Proxy before it's injected into ImplementationThree. So:
I want to use Guice to have ImplementationOne being injected into ImplementationTwo
Before ImplementationTwo is injected into ImplementationThree, I want to wrap it.
What I'd love to see, is a Guice interceptor that is invoked after the instantiation and injection of dependencies, but before it's handed over to the injector context.
I could use a Provider for ImplementationTwo, but then I don't know how to get an instance of InterfaceOne from Guice.
The Provider method can also use injection. Try
#Inject #Provides
public InterfaceTwo provideInterfaceTwo(InterfaceOne i){
return InterfaceTwoImplementation
}
Why not use plain old Guice AOP support? Something like
#SynchronizedAccess
public void foo(...){
...
}
this way you can see just by looking at the code that there is something more to the method.
If you absolutely want to wrap things in a Proxy:
If you only have a few classes to proxy, then #acerberus suggestions works fine.
To automate, you can use a #afterInjection, part of Custom Injections, and reassign the field to your proxy using reflection.
I find it a bit archaic to program using locks while we have things like akka around but YMMV.

Categories