MapStruct with Spring Boot, annotate generated classes with custom annotation - java

Is there possibility, to annotate class generated by MapStruct, with custom annotation? Currently Im using MapStruct with componentModel defined as "spring", like:
#Mapper(componentModel = "spring")
public interface MyMapper {}
For this interface, class is generated by MapStruct:
#Component
public class MyMapperImpl implements MyMapper {}
So I can easily inject it. What I want to do, is to annotate generated class with org.springframework.context.annotation.Profile annotation, so my generated bean will be in force only if specific profile is defined, is there possibility to inject such annotation, #Profile("dev"), to generated class somehow? I was thinking about org.mapstruct.DecoratedWith annotation, but I didn't make it working for me

This is currently not possible with the official API. This question is similar to mapstruct/mapstruct#1427.
However, there are 2 options that you can try to make it work.
Option 1 (annotate Mapper)
You can try to annotate MyMapper with the #Profile annotation, I am not sure whether Spring searches up the inheritance tree and in interface or not
Option 2 (use internal API)
MapStruct has the ModelElementProcessor that it used to add the #Component annotation. The one for Spring is SpringComponentModelElementProcessor.
You can provide your own componentModel (spring-dev for example) that would add the #Profile annotation to the generated mapper.

Related

Using Java validator for SpringBoot properties with #Value annotation

Does anybody know if it's possible to use custom ConstraintValidator for SpringBoot properties with #Value annotation?
Something like this:
#Component
#Validated
public class TestClass {
#Value("${test.property}")
#ValidValue(className=ValidValueValidator.class)
private String testProperty;
}
what's your mean how to make #Validated Take effect?
u can register a BeanValidationPostProcessor bean
or if your want use custom ConstraintValidator
see Majutharan Majutharan comment

Is it ok to use #Component for any utitliy class?

I have got a Class that converts Entity to DTO, class is mainly Mapper ConfigurableMapper from Orika packages. I have annotated the mapper class with #Component and Autowired it any class to convert from DTO to Mapper. This can be achieved without #Component and Autowiring.
Please enlighten me.
Consider using a ConverterFactory for Conversion
Baeldung wrote an article about it under:
spring-type-conversions
For some Reference:
docs.spring.io
An even more specific Implementation also from Baeldung:
Entity To DTO Conversion for a Spring REST API
I'm not sure if it is necessary to annotate #Component to helper/utility classes. As long as they don't need to be instantiated from spring as a bean you can delete the annotation.

How can i combine Guice and Mapstruct?

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 );

Using repository annotation when implementing JpaRepostiory in Spring

I'm not sure if I understand it correctly so want to clarify.
If I want to create a repository for my entity eg.:
public interface BookRepository extends JpaRepository<Book, Id> {}
Should I annotate it with #Repository? According to this question #Repository annotation translates exceptions from SQL to persistence ones but doesn't JpaRepostiory already do that? What's the best practice - to annotate or not?
While using JpaRepository you don't need to annotate the interface with #Repository
It is just an interface and the concrete implementation is created dynamically as a proxy object by Spring and the JDBC Exceptions are handled there.
You need to use #Repository when you create a Custom DAO, so that spring creates a bean and handles the exception properly.
You need to annotate it with #Repository so spring knows it should instantiate that class as a bean. The #Component, #Service and #Repository annotations all serve the same purpose in that regard. #Repository narrows the scope to a service that specifically deals with obtaining and storing data.

Customised annotation in spring

I have seen few examples where customized annotations were used. example
#SimpleAnnotation
class SampleBean {
#SimpleAnnotation
public String getName() {
return "AAA";
}
public void setName(String name) {
}
public int getHeight() {
return 201;
}
}
#Target( { ElementType.METHOD, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#interface SimpleAnnotation {
}
Can anyone tell why we use this?
Spring supports for many Annotation the concept of "meta-annotation". (I am not sure if it is for all.)
This mean that you can build your own annotation and annotate the annotation with one of springs "core" annotations.
For example:
#Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Service
public #interface MyService {
}
Then you can use this annotation instead of #Service. (Btw: #Service, #Repository, #Controller use the same technique to "inherit" from #Component)
One example that make heavy use of this is "inherit" from #Qualifier.
For an example and some explanation have a look at Spring Reference Chapter: 3.9.3 Fine-tuning annotation-based autowiring with qualifiers (The Example with #Genre is at the end of the chapter.)
One very usefull construct that can be done with that technique is, that it enables you to combine several Annotations to a (in your use case) more meaning full. So instead of writing at every class of some type allways the same two annotations, for example: #Service and #Qualifiyer("someting") (the org.springframework.beans.factory.annotation.Qualifier). You can create your custom annotation that is annotated with this two annotations, and then use in your beans only this one custom annotation. (#See Avoid Spring Annotation Code Smell Use Spring 3 Custom Annotations)
If you want to see how powerfull this technique can be use, you can have a look at Context and Dependency Injection Framework.
Question from the comment:
The #interface also has some variables defined inside it, what does that signify?
The Annotations (defined by #Interface) work a bit like beans. This Fields are the properties that can/must be define if you use the annotations. The values can be later on be read via reflection API.
For example the #Controller Annotation in Spring:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Controller {
String value() default "";
}
The field with name value is that field that can be used without explicit name it: (#Controller("myUrl") is the same #Controller(value="myUrl"))
You can create your own meta-annotations that collect several other Spring annotations to reduce meta-boilerplate in your code:
#Service
#Scope(value = "prototype")
#Transactional(readOnly = true, rollbackFor = RuntimeException.class)
public #interface ReadOnlyService {}
And then you can simply write:
#ReadOnlyService
public class RoleService {
}
Spring will find the #ReadOnlyService and semantically replace it with:
#Service
#Scope(value = "prototype")
#Transactional(readOnly = true, rollbackFor = RuntimeException.class)
public class RoleService {
}
Of course having custom annotations pays of when you have tons of services annotated with the same set of Spring annotations that can be replaced with one, well named annotation.
Examples taken from: Avoid Spring Annotation Code Smell: Use Spring 3 Custom Annotations
Custom annotations do not do anything on their own. They are simple markers in code. Their real power comes from tools that look for specific annotations. Like some of the other answers mention, Spring has several uses for annotations and now mechanisms for defining your own component types. Pretty neat. Another example, a few weeks ago I used AOP and a few custom annotations to provide simple method level result caching. Now that I have the caching engine in place, and the appropriate AOP hooks defined, if I want to cache a method, I simply add that annotation. Some people simply use the annotations as fancy metadata to improve readability.
At the end of the day, they are a fairly simple tool that you can use for a great number of things.
The best part of using custom annotations is that you don't have to make any configuration, Spring will auto detect that these beans are service components and everything will work fine. Custom Annotations are a very small feature added in Spring but are very useful.For details take a look at this
http://java.dzone.com/articles/avoid-spring-annotation-code-smell-use-spring3-custom-annotations
Two options:
you need the #Component annotation on your custom annotation. That way you can use your custom annotation to mark classes as beans. In addition, you can add a default scope and other meta-information
qualifiers - you can use qualifier annotations (annotated with the #Qualifier meta-annotation) to distinguish between implementations of the same interface.
A common pattern is also to use annotations in AOP pointcuts. Not specifically Spring, but often employed when making use of Spring AOP.

Categories