How to inject Spring's Validator implementation? - spring

I started with generating my application using JHipster v.3.5.1.
After some time, I needed to create validator to perform some business logic validation on my entity, when it is created with POST. So I made:
#Component
public class MyValidator implements Validator
Then, I tried to inject it into my controller (annotated with #RestController), but no matter which way I tried, it always resulted in something like that:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.my.app.service.domain.MyValidator] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Ways I tried to create bean and inject it
#Autowired
private MyValidator myValidator;
#Inject
private MyValidator myValidator;
#Autowired
#Qualifier("myValidator")
private MyValidator myValidator; (with #Component("myValidator") on class)
#Inject
#Qualifier("myValidator")
private MyValidator myValidator; (with #Component("myValidator") on class)
//Below was inserted in class annotated with #Configuration
#Bean
public MyValidator myValidator() {
return new MyValidator();
}
However I tried it - it failed. I always got NoSuchBeanDefinitionException or field value was set to null.
I've also checked class location in project structure. To be 100% percent sure it's well placed, I've put it in package the with #Services, which are scanned and work well. No effect.
I know that it seems to be pretty easy task and I know this injection is possible (I've seen it done in project in my work), but somehow I'm not able to make it work in my project.
Maybe I'm missing something in configuration? Thanks for any help :)

I believe your issue is that when you use #Autowired inside a class annotated with #Configuration you are just referencing to a bean that is defined in a separate configuration file, that is it has to be declared in another file also with the #Configuration annotation.
If you want to refer refer to another implicit bean such as your validator annotated with #Component you will need to do it in another implicit bean also annotated to with implicit notation such as #Component, #Service, #Controller, etc
The #Autowired alone should work unless you have more than one class implementing the same interface. That is when you will need to use the #Qualifier.

Related

Spring Boot - Override bean from controller

I have two controllers (ControllerA and ControllerB)
Both controllers call to a service (MyService).
MyService calls to an interface called MyRepository which has two implementations (FirstRepository and SecondRepository).
How is possible to use FirstRepository when the service (MyService) is called from ControllerA and use SecondRepository when the call comes from ControllerB?
This way I can reuse MyService and which repository is used comes from Spring Configuration.
I can see two possible solutions here.
1. In you MyService class autowire both implementations with #Qualifier annotation (you can also autowire List.
Then MyService method would have a parameter saying which MyRepository implementation should be called. I would not recommend this solution.
2. Define two implementations of MyService (FirstService, SecondService). Then FirstService would autowire FirstRepository and SecondService would autowire SecondRepository (use #Qualifier annotation again. Now you can easily inject FirstService to ControllerA and SecondService to ControllerB.
But first I would think about architecture. Maybe you don't need separate controllers?
Have you checked #Primary or #Resource or #Qualifier annotations? Based on your requirement you can choose out of them.
Something similar has been discussed here.
I ended up creating two controllers and defining two #Configuration classes, one for each #Controller.
And using the #Qualifier annotations defined two sets of beans, and then in each controller let Spring know which #Qualified bean I want injected.
#RestController
#RequestMapping("/v1/inapp/purchases")
class AController(
#Qualifier("appStore") private val redeemPurchaseService: RedeemPurchaseService
) : RedeemPurchaseApiDocumentation { // More code }
And the other controller
#RestController
#RequestMapping("/v1/inapp/purchases")
class GPlayRedeemPurchaseController(
#Qualifier("gplay") private val redeemPurchaseService: RedeemPurchaseService
) : RedeemPurchaseApiDocumentation { // More code }
And two #Configuration files, one per controller.

Spring Bean and Autowire to datasource

Noob to Spring. I have 2 files:
foo-servlet.xml which has the following statement:
<bean id:"DAO" class="a.b.data.MyDAO"/>
fooController.java has the following:
#Controller
public class FooController{
#Autowired
private FooDAO fooDAO;
public void setFooDAO (FooDAO fooDAO){ this.fooDAO = fooDAO;}
My question: Is Spring actually replacing / injecting the definition of DAO in the servlet into my FooDAO? I'm trying to understand the 'tie-in' between the bean and how Spring know to substitute that file for my FooDAO in the controller.
Oh, and there is no mention of #Repository or #Component anywhere in this example code...
The XML looks kind of corrupted. I think it needs to be id=DAO
As far as i know: Autowiring is either done via the type or the name and the type.
So when MyDAO implements FooDao your bean will be considered for Autowiring.
But this is just a guess. The code of the Daos and the rest of the configuration would be helpful to give a correct answer to this question.
Understanding Spring #Autowired usage
This might answer your question as well.

How do I autowire an instance of a java class?

I have a class that starts like this:
import javax.mail.Session;
//... more imports
#Component("eMailUtility")
public class MailUtility {
#Autowired
Session mailSession;
//...
}
My IDE tells me "Could not autowire. No beans of 'Session' type found."
This message doesn't surprise me, but I'm not sure how to fix it. Session is a final class with factory methods but no public constructors. I can easily instantiate a Session somewhere, but I don't know what I need to do to make it recognizable as a target of an autowired injection. All the examples I've found on the internet show how to autowire an instance of a class that I wrote, which doesn't help me here.
(A detailed explanation of exactly how autowire works, which doesn't gloss over anything, would be very helpful, but I can't seem to find one. If you know of a good link, that would be helpful.)
You'd have to create a method in a class that is annotated with #Configuration that returns a Session object and annotate that method with #Bean. In your case something like this:
#Bean
public Session session() {
return <instance>;
}
If it was one of your own classes you could also annotate it with #Component, or other annotations that are itself annotated with #Component. Spring would then find the class with this annotation and automatically create the bean for you.
For an explanation about #Autowired you can look at this answer: Understanding Spring #Autowired usage

What are possible causes for Spring #ComponentScan being unable to auto create a class anotated by #Repository

I came across a tutorial which seemed to be fitting my usecase and tried implementing it. I failed but wasn't sure why. So I tried to find another example with similar code and looked at the book "Spring in Action, Fourth Edition by Craig Walls"
The books describes at page 300 the same basic approach. Define a JdbcTemplate Bean first.
#Bean
NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) {
return new NamedParameterJdbcTemplate(dataSource);
}
Then a Repository implementing an Interface
#Repository
public class CustomRepositoryImpl implements CustomRepository {
private final NamedParameterJdbcOperations jdbcOperations;
private static final String TEST_STRING = "";
#Autowired
public CustomRepositoryImpl(NamedParameterJdbcOperations jdbcOperations) {
this.jdbcOperations = jdbcOperations;
}
So I did like the example in the book suggests, wrote a test but got the error message
Error creating bean with name 'de.myproject.config.SpringJPAPerformanceConfigTest': Unsatisfied dependency expressed through field 'abc'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'de.myproject.CustomRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
To my understanding as book and tutorial describe, the Repository should be recognized as a Bean definition by the component scan.
To test this I created an context and asked for all registered Beans.
AnnotationConfigApplicationContext
context = new AnnotationConfigApplicationContext();
context.getBeanDefinitionNames()
As assumed my Repository wasn't among them. So I increased, for test purposes only, scope of the search in my project, and set it to the base package. Every other Bean was shown, except the Repository.
As an alternative to component scanning and autowiring, the books describes the possibility to simply declare the Repository as a Bean, which I did.
#Bean
public CustomRepository(NamedParameterJdbcOperations jdbcOperations) {
return new CustomRepositoryImpl(jdbcOperations);
}
After that Spring was able to wire the Repository. I looked at the github code of the book in hope for a better understanding, but unfortunately only the Bean solution, which runs, is implemented there.
So here are my questions:
1.) what possible reasons are there for a Bean definition, is a scenario like this one, not to be recognized by the component scan?
2.) this project already uses Spring JPA Data Repositories, are there any reasons not to use both approaches at the same time?
The problem is naming of your classes. There are many things to understand here.
You define a repository Interface #Repository is optional provided it extends CRUDRepository or one of the repositories provided by spring-data. In this class you can declare methods(find By....). And spring-data will formulate the query based on the underlying database. You can also specify your query using #Query.
Suppose you have a method which involves complex query or something which spring-data cannot do out of the box, in such case we can use the underlying template class for example JdbcTemplate or MongoTemplate..
The procedure to do this is to create another interface and a Impl class. The naming of this interface should be exactly like Custom and your Impl class should be named Impl.. And all should be in same package.
For example if your Repository name is AbcRepository then Your custom repository should be named AbcRepositoryCustom and the implementation should be named AbcRepositoryImpl.. AbcRepository extends AbcRepositoryCustom(and also other spring-data Repositories). And AbcRepositoryImpl implements AbcRepositoryCustom
I was able to "solve" the problem myself.
As we also have a front end class annotated with the same basePackage for the #ComponentScan
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = {"de.myproject.*"})
so there were actually two identical #ComponentScans annotations which I wasn't aware off and this did lead to a conflict. It seams the ordering how the whole application had to be loaded had changed, but thats only me guessing.
I simply moved my Repository and its Impl to a subpackage, and changed the
#ComponentScan(basePackages = {"de.myproject.subpackage.*"})
and now everything works fine. Though it escapes me, what the exact reason behind this behavior is.

Spring No unique bean of type

i have a little trouble in Spring with two component of a service.
I have this component:
#Component
public class SmartCardWrapper
and this one:
#Component
public class DummySmartCardWrapper extends SmartCardWrapper
The service autowire both but spring fails due this expection:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.cinebot.smartcard.SmartCardWrapper] is defined: expected single matching bean but found 2: [dummySmartCardWrapper, smartCardWrapper]
Why it doesn't use class names?
That's one of the most basic concepts of Spring - Inversion of Control.
You don't need to declare your dependencies using their implementation types (to avoid coupling with implementation). You can declare them using interfaces or superclasses instead, and make Spring find the proper implementation class in the context.
In other words, bean are not distinguished by their implementation classes, because you may want to change implementation class of a bean without changing the beans that depend on it. If you want to distinguish between different beans of the same type, use logical bean names instead:
#Autowired #Qualifier("smartCardWrapper")
private SmartCardWrapper smardCardWrapper;
#Autowired #Qualifier("dummySmartCardWrapper")
private SmartCardWrapper dummySmardCardWrapper;

Resources