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

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.

Related

When to use dependency Injection in spring mvc?

I am working on a Spring MVC project where I am dealing with different types of services,Repositories i.e classes annotated with #Service and #Repository. I am confused with a couple of questions:
When to use #AutoWired annotation?
I have seen various repositories using this:
CourseRepository crepo=new CourseRepository();
and I have seen this also
#AutoWired
private CourseRepository crepo;
Which one of the above options should be used to get an instance of
repository in Service class?
Can I use #AutoWired for classes which are not annotated with #Repository or
#Service?
I am a beginner in this java world.Any help will be highly appreciated.
Thanks
You use new for data objects, which in most modern architectures are passive (they're not "active records"). Everything else is a service object, and you should inject those. (The one place that you do use new is with an #Bean method, which is a "factory" that creates the service object; in this case you normally pass the dependencies as method parameters.)
Note that it is recommended to use constructor injection instead of field injection; it makes your code easier to test, and it eliminates the possibility of certain kinds of errors. In fact, if using constructor injection, it's not required to have any Spring annotations in your service classes at all; beans can be registered using #Import instructions or #Bean methods on a configuration class.
You should #Autowire the dependencies instead of instantiating it yourself. Doing so, service and repo layer will be loosely coupled. Moreover, a mock repository can be easily injected in service's JUnit test class if dependency is autowired. To conclude, use below:
#Autowired
private CourseRepository crepo;
A class not annotated with any of below stereotype annotations will not be in Spring's IoC (Inversion of Control) container. Hence, no point in autowiring in a class that is not annotated with any of below annotations.
#Component, #Controller, #Service, #Repository
Dependency injection means that the framework is the one who handles the classes instantiation and the object of that class is going to be injected (thanks to #Autowired annotation) in the class where you need it. In other words, you do not need to instantiate service and repository classes by yourself using new operator, you just need to tell the framework that those classes need to be injected and that's why you use #Autowired annotation.

MapStruct with Spring Boot, annotate generated classes with custom annotation

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.

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.

Does annotating a repository interface as #Component have any cons?

I have this interface:
public interface liteRepository extends CrudRepository<liteEntity, Long>, JpaSpecificationExecutor<liteEntity> {...}
It works, all is well.
However, intellij does not register this class as a spring component. If I annotate this interface with #Component, then intellij recognizes this as a spring bean and I can #Autowire this repository in my integration tests.
My code still works after annotation, but I'm not confident that I am not messing with things that I should not be messing with.
Question:
Is there any harm in adding the #Component annotation to this interface?
The only thing that #Component annotation means is that the class is eligible for becoming a Spring bean during Spring's component-scan.
So, if you want it to be a Spring bean and you did not define it as a Spring bean anywhere else, you can safely add the #Component annotation.
Of course, this will only work if you have the actual component scan configured somewhere(for, example <context:component-scan base-package="..."> in some Spring config file), which I am assuming you already heave, since the bean is properly getting autowired after you add the annotation.

Resteasy spring custom objectmapper

I'm converting my guice application to a spring based on because of issues I found with the #transaction annotation. When doing so, I came to a issue with the configuration of a custom objectmapper with spring/resteasy. I want to register the hibernate4Module (fasterxml jackson) and a custom deserializer.
I have found many solution when using spring mvc, but I'm not using spring mvc.
I'm looking at the resteasyboostrap class, since there you have control over you factory, but I don't know how to register my new SimpleModule there.
Anyone with any experience? When I'm searching the internet, it seems nobody is trying to do the same thing. Perhaps I'm looking in the wrong places?
This one was eventually an easy one to fix.
Remove the resteasy-jackson provider and write a custom class that you annotate with the spring #Component annotation. Jax-RS picks up the provider and uses the object mapper in the provider.
I was searching in the implementation, but the answer was in the jax-rs api.
#Component
#Provider
#Consumes({"application/*+json", "text/json"})
#Produces({"application/*+json", "text/json"})
public class JacksonProvider extends JacksonJsonProvider {
public JacksonProvider() {
setMapper(new CustomObjectMapper());
}
}

Categories