I am bit puzzled by the way spring instantiates and Autowires the services.
Basically, I am looking to find a solution to the below problem which is blocking my app to start.
Field titleService1 in com.scorpio.spring.security.oauth2.controller.TitleController required a single bean, but 2 were found:
- genderServiceImpl: defined in file [\spring\authorities\target\classes\com\spring\security\service\GenderServiceImpl.class]
- titleServiceImpl: defined in file [\spring\authorities\target\classes\com\spring\security\service\TitleServiceImpl.class]
I have two Rest controllers namely TitleController and CompanyController with each controller referencing one or multiple services. The services are the implementation of BaseService<T>
TitleController.java
#RestController
#RequestMapping("/secured/title")
public class TitleController {
#Autowired
private BaseService<Title> titleService;
}
CompanyController.java
#RestController
#RequestMapping("/secured/company")
public class CompanyController {
#Autowired
private BaseService<Title> titleService;
#Autowired
private BaseService<Gender> genderService;
}
BaseService.java
public interface BaseService<T> {
T get(Integer id);
T get(String t);
List<T> getAll();
void create(T t);
T update(T t);
void delete(Integer id);
void delete(T t);
}
Looking at the error required a single bean, but 2 were found and since there are two different implementation of BaseService, I do understand that Spring is unable to decide which Bean to Autowire as none of the implementation is annotated with #Qualifer, #Primary etc.
But what is more confusing is that, when I comment out the titleService from TitleController and re run my app, it just works. My question is how spring is able to Autowire the appropriate services in CompanyController and why if I try to Autowire in TitleController, it doesn't work ?
Many thanks.
Use qualifier annotation along with autowired. Qualifier is used to specify which implementation of interface to use.
#Autowired
#Qualifier("Audi")
private Car car;
Related
I have a classA which implements an interfaceA, with a methodA, then I have a classB in which I call classA with an #Autowired to be able to use methodA, but it gives me a warning that I must create a method for classA. Why is this happening? Doesn't #Autowired work like this in this case? Should I just instantiate classA? Thank you very much for your answers.
ClassA
#RequiredArgsConstructor
public class RepositoryImpl implements IRepository {
#Autowired
private final TransactionDataMapper transactionDataMapper;
#Autowired
private SpringDataColminvoice springDataColminvoice;
#Override
public <S extends TransactionDto> S save(S s) {
Colm colm = transactionDataMapper.toEntity(s);
//methodA
springDataColminvoice.save(colm);
return null;
}
}
InterfaceA
public interface IRepository extends IRepository<TransactionDto, Integer> {}
ClassB
#Service
#RequiredArgsConstructor
public class ServiceImpl implements IInvoiceService {
#Autowired
private RepositoryImpl repositoryImpl;
#Override
public void save(CMessage cMessage) throws HandlerException {
try {
TransactionDto transactionDto = cMessage.getTransaction();
// methodA
repositoryImpl.save(transactionDto);
} catch (Exception e) {
throw new HandlerException(e.getMessage());
}
}
}
Exception
Action:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field RepositoryImpl in com.st.ms.yyu.d.binvoce.infraestructure.rest.spring.services.impl.InvoiceServiceImpl required a bean of type 'com.st.ms.yyu.d.binvoce.infraestructure.db.springdata.repository.impl.ServiceImpl' that could not be found.
The injection point has the following annotations:
- #org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.st.ms.yyu.d.binvoce.infraestructure.db.springdata.repository.impl.RepositoryImpl' in your configuration.
(posting this as an answer since I do not have enough reputation to comment)
As others have pointed out already, a code sample would help tremendously.
That being said, though, it sounds like you're missing implementation for "ClassA".
If you have an interface that "ClassA" implements, you have to implement the interface's methods in "ClassA" before you can use them.
I assume your code currently looks somewhat like this?
public interface InterfaceA {
void methodA();
}
public class ClassA implements InterfaceA {
}
public class ClassB {
#Autowired
ClassA classA; // Cannot use {#link InterfaceA#methodA} because the class does not implement the function
}
If this is your code, make sure you add an implementation for your "methodA()" function in "ClassA". Somewhat like so:
public class ClassA implements InterfaceA {
#Override
public void methodA() {
}
}
Additionally, in order to autowire in Spring (Boot), you need to ensure that the class you'd like to autowire is marked as such. You can autowire beans.
To make "ClassA" in the example eligible for autowiring, make sure to instantiate it either as:
A bean (using the #Bean annotation).
A component (using the #Component annotation).
A service (using the #Service annotation).
Any of the other annotations that may match your use case the best.
In our example, this would look somewhat like this:
#Component // Or #Service / whatever you may need
public class ClassA implements InterfaceA {
#Override
public void methodA() {
}
}
Hope you've found any of this helpful. All the best!
-T
As what I have understood, #Autowire means injecting the value/instance of the specific property where you put the annotation #Autowire. In this case, #Autowire only happens when there is defined/created Bean within your basePackage of your Spring Boot project that can match it, i.e. where your #Autowire referred to (meaning there is no conflict issue like ambiguity, etc. and the DataType(Class) can be implicitly casted). In your example, first you treat the IRepository and/or RepositoryImpl as Repository without using the #Repository annotation to inform the Spring Boot default configuration that this is a Repository bean. As you didn't put the POM.xml or posted the related code, I presumed you are creating your own repository class. I think it's much better to post your dependencies here.
But as what others pointed out. You need to create a bean that can match the #Autowired you've put on TransactDataManager & SpringDataColminvoice. You need also to inform the Spring Boot or register it that your class A is a Bean by annotating
#Bean - defining a regular bean,
#Component - a Component in the Project,
#Service - a Service in the Project,
#Repository - a Repository (if you're using Spring JPA), etc.
#<Other Annotations depending of what other Spring Project/Dependencies your using>
Since newer versions of Spring is moving to annotation based from XML mapping, we need to put proper annotation for each class/object that we want to be auto injected/instantiated from #Autowired using the above sample annotations depending on the role/purpose of your class/object is.
I suggest if you're not sure. Then create a typical bean using common annotation #Bean. So your class A might be
#Component //Insert proper Annotation for your class if necessary. This is just a sample
#RequiredArgsConstructor
public class RepositoryImpl implements IRepository {
#Autowired
private final TransactionDataMapper transactionDataMapper;
#Autowired
private SpringDataColminvoice
springDataColminvoice;//segunda
#Override
public <S extends TransactionDto> S save(S s) {
//Some implementation
}
#Bean
private TransactionDataMapper getTransactionDataMapper(<Some parameters if needed>){
return <an instance for TransactionDataManager>;
}
#Bean
private SpringDataColminvoice getSpringDataColmInvoice(<Some parameters if needed>){
return <an instance for SpringDataColminvoice>;
}
}
Note that 2 beans definition are optional if there are already a Beans define on outside class or if it was marked by other annotation like #Service, #Component or other proper annotations and the other one bean is just a reference parameter for the other bean in order to properly instantiated.
In your class B is the following:
public class ClassB {
#Autowired
ClassA classA;
/*Note: ignore this Bean definition if Class A is annotated with #Component,
#Service, or other proper #Annotation for Class A.
*/
#Bean
private ClassA getClassA(<Some Parameters if Needed>){
return <Instance of Class A>
}
}
Take note that, you don't need to put a Bean definition inside the Class B if you put a proper annotation for your Class A like #Component, #Service, etc.
I have a question that I can't answer myself - at least not well.
Imagine following code:
#Service
public class ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
#Service
public class ServiceB {
#Autowired
ServiceA serviceA;
public void doService() {
serviceA.doService();
}
}
It works, but is it considered bad practice? If you want to decouple these classes or test them, you have no way to ever manually set the dependencies.
Also, how exactly is Spring handling it? Is there created a proxy class with an added constructor for the property?
If it is a bad practice or not depends for the era in which you write this code. In the era of EJB it is a best practice, the container provide you all the feature of the lifecycle and even in Spring it is good even if some time even in Spring this is quite rigid model java config or xml is a more flexible solution.
However in the 20xx era especially in a TDD and Agile model, I can say that it is a real BAD PRACTICE. Those beans are not testable out of the Spring container and the annotation couple you at Spring even in compile time. a more best solution may be a code like below
class ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
class ServiceB {
private final ServiceA serviceA;
ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
}
public void doService() {
serviceA.doService();
}
}
#Configuration
class ServiceConfig{
#Bean
public ServiceA serviceA(){
return new ServiceA();
}
#Bean
public ServiceB serviceB(ServiceA serviceA){
return new ServiceB(serviceA);
}
}
In this way ServiceA and ServiceB classes are two totally Spring free bean and especially for the business logic it is a best practice, the bean are testable because the our dependencies are explicit.
Imagine of provide a test of the ServiceB class writing the code in this way you can stub or mock the serviceA dependency and the ServiceB bean can be tested in isolation.
For the proxy story do not worry about it since that we provide a configuration class ServiceA and ServiceB are two beans like the annotated class, Spring manage a java config bean like an annotated bean. The difference is that now we can benefit of an explicit composition and we can provide a more flexible configuration scenario. we can benefit again of the magic aop of Spring because like said before an Spring bean configured in Java config is totally equivalent respect to an annotated bean.
I suggest you to use java config like the example.
I hope that it can help you
update:
to reply to:
Also, how exactly is Spring handling it? Is there created a proxy class with an added constructor for the property?
I can say: with the component-scan feature let's say #ComponentScan, spring find all the bean that are annotated with a sterotype annotation like #Component, #Service, #Repository and so on some of this annotation are useful because trigger some feature, for example #Repository if we implement a JPA repository and register a PersistanceExceptionTraslatorPostProcessor that translate the SQL native exception in an Exception of DataAccessException hierarchy, but other annotation are just a way for register a spring bean with annotation #Component, #Service are example.
Spring by relfection create the bean and inject the field annotated with #Autowired, if you use #Autowired on field by reflection set directly the field otherwise use the setter, in xml for instance the setter or the constructor are required.
In case of two constructor for you it is transparent, Spring will use the empty constructor and then will provide the #Autowired property by reflection, you can even do like below:
#Service
class ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
#Service
class ServiceB {
private ServiceA serviceA;
public ServiceB() {
}
#Autowired
public ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
}
public void doService() {
serviceA.doService();
}
}
In this case spring recognize that it have use the annotated constructor with #Autowired in order to create the bean and provide the dependency. In any case the best practice is definitely the first snippet of code in my answer. It is explicit in the dependencies, clean and Spring Free in your business code base
If you dont like autowired (me either). You can used Constructor Dependency Injection.
You should not used depencendy for class byt for interface and spring will server correct implementation (decoupling)
public interface ServiceA {
public void doService();
}
#Service
public class ServiceAImpl implement ServiceA {
public void doService() {
System.out.println("Doing ServiceA");
}
}
#Service
public class ServiceBImpl implements ServiceB {
private final ServiceA serviceA;
public ServiceBImpl(ServiceA serviceA) {
this.serviceA = serviceA;
}
public void doService() {
serviceA.doService();
}
}
I'm working on a Spring Boot v1.4.2.RELEASE application with JPA.
I defined repository interfaces and implementations
ARepository
#Repository
public interface ARepository extends CrudRepository<A, String>, ARepositoryCustom, JpaSpecificationExecutor<A> {
}
ARepositoryCustom
#Repository
public interface ARepositoryCustom {
Page<A> findA(findAForm form, Pageable pageable);
}
ARepositoryImpl
#Repository
public class ARepositoryImpl implements ARepositoryCustom {
#Autowired
private ARepository aRepository;
#Override
public Page<A> findA(findAForm form, Pageable pageable) {
return aRepository.findAll(
where(ASpecs.codeLike(form.getCode()))
.and(ASpecs.labelLike(form.getLabel()))
.and(ASpecs.isActive()),
pageable);
}
}
And a service
AServiceImpl
#Service
public class AServiceImpl implements AService {
private ARepository aRepository;
public AServiceImpl(ARepository aRepository) {
super();
this.aRepository = aRepository;
}
...
}
My application won't start with the message :
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
| aRepositoryImpl
└─────┘
I followed all steps discribed in http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.single-repository-behaviour
Please help !
Laurent
Use #Lazy
A simple way to break the cycle is by asking Spring to initialize one of the beans lazily. That is: instead of fully initializing the bean, it will create a proxy to inject it into the other bean. The injected bean will only be fully created when it’s first needed.
#Service
public class AServiceImpl implements AService {
private final ARepository aRepository;
public AServiceImpl(#Lazy ARepository aRepository) {
super();
this.aRepository = aRepository;
}
...
}
source: https://www.baeldung.com/circular-dependencies-in-spring
Use #Lazy annotation it will be resolved
#Component
public class Bean1 {
#Lazy
#Autowired
private Bean2 bean2;
}
There's a simple fix for your original problem:
Just remove #Repository from ARepositoryCustom and from ARepositoryImpl.
Keep all the naming and interface/class hierarchies. They are all OK.
I've tested your source code, and found something tricky.
First, with your source code, I got the following error:
There is a circular dependency between 1 beans in the application context:
- ARepositoryImpl (field private test.ARepository test.ARepositoryImpl.aRepository)
- aRepositoryImpl
Then, I guess Spring 'confused' between ARepository (JPA repository) and ARepositoryImpl (Custom repository).
So, I would suggest you rename ARepository to something else, such as BRepository. It worked if I renamed the class name.
According to offcial documentation of Spring Data (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/) :
These classes need to follow the naming convention of appending the namespace element’s attribute repository-impl-postfix to the found repository interface name. This postfix defaults to Impl
add this in your pom.xml file. It works for me
spring.main.allow-circular-references:true
In my case:
I added
spring:
main:
allow-circular-references: true
in the application.yml
Or you can add
spring.main.allow-circular-references=true
in the application.properties
Both application.yml and application.properties files in the below directory:
import org.springframework.context.annotation.Lazy;
Add #Lazy on one dependency injection to make it lazy load.
I'm trying to inject a service-annotated class into a configuration class in a Spring Boot application, but it doesn't get injected (is set to null), which I assume is due to the Spring lifeycle.
Also, this service has an overloaded constructor that uses constructor injection, and I guess this is also a problem, as autowiring acts upon a default constructor. However, the service needs to be Spring-configured, so I don't think one can create a new instance in a Bean annotated method.
How can one solve this?
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private SessionService sessionService;
#Bean
public SessionService sessionService() {
return sessionService;
}
}
public interface SessionService extends BaseCacheService<Session> {
void extendExpiration(String key);
String getSessionId(String key);
}
#Service
public class SessionServiceImpl implements SessionService {
private Environment environment;
private UserService userService;
#Autowired
public SessionServiceImpl(Environment environment, UserService userService) {
this.environment = environment;
this.userService = userService;
}
}
If I exclude the #Bean method, then I get a compilation error:
Your error is the following (you are returning a null value):
#Bean
public SessionService sessionService() {
return sessionService;
}
Solution
Since your SessionServiceImpl is annotated with #Service, you can just remove the #Bean method and let spring create it. Spring already makes it available for you.
Or, If your SessionServiceImpl wasn't annotated with #Service, you would need the following :
#Bean
public SessionService sessionService() {
return new SessionService();
}
If this doesn't work, it may just be that your SessionServiceImpl is in a package not being scanned by spring (as suggested by #Miloš Milivojević)
You may add #ComponentScan to your Configuration class
#Configuration
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
#ComponentScan("com.package.to.sessionServiceImpl-or-higher")
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
Expanding on #Alex's answer, when you annotate a method with #Bean, it tells Spring that this method will produce that type. So, you essentially told Spring to give you the null reference you already had for all Beans of type SessionService.
If you are using Annotation-based context configuration, you can Autowire any #Component Bean (not just #Service) that can be constructed without runtime parameters (e.g. has a default constructor or an Autowired Constructor). If you need to do something to create the bean (e.g. runtime configuration required), you would either create a method as #Alex suggested, or you can use getBean and pass in the Type and Constructor arguments. The former is generally preferred.
I was facing similar issue while writing an integration test class for a spring boot application. RestTemplate class and CounterService of metrics API are autowired in my service class. I could use #ContextConfiguration(Classes={RestTemplate.class}) for injecting RestTemplate to my service, but adding CounterService.class to above annotation does not help, maybe because CounterService is an interface not a concrete class, Hence I was getting "No bean of type CounterService found" issue.
Thanks to answer by Milos, I included #EnableAutoConfiguration to my integration test class, issue was resolved!
If Alex's answer does not work (removing the #Bean method), you're probably not using #EnableAutoConfiguration or your Application is not in the root-hierarchy package so it's not scanning the whole classpath. Try adding #ComponentScan("service.class.package") to your configuration (in addition to removing the sessionService method) and see if it helps.
I am attempting to get a reference to my repository interface (UserRepository) that extends CrudRepository within my custom implementation (UserRepositoryExtensionImpl) in order to gain access to all the methods provided by Spring JPA.
Crud Extension:
#Repository
public interface UserRepository extends CrudRepository<User, String>, UserRepositoryExtension<RosterUser> {
...any custom spring JPA methods...
}
Extension Interface:
#Repository
public interface UserRepositoryExtension <T> {
public T put(T entity);
}
Custom Implementation:
public class UserRepositoryExtensionImpl implements UserRepositoryExtension<User> {
UserRepository userRepository;
#Autowired
public UserRepositoryExtensionImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public User put(User user) {
System.out.println(user + "was put");
// ...put logic here
return null;
}...
}
However, I am unable to inject UserRepository since a circular dependency exists (given that UserRepository extends the interface implemented by my UserRepositoryImpl). I am getting the following error:
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ' userRepositoryImpl': Requested bean is currently in creation: Is there an unresolvable circular reference?
A possible, but less than ideal solution would be to inject and EntityManager into UserRepositoryImp, but in that case, I do not have access to any of the Spring JPA methods provided by CrudRepository, or any additional methods that I might have created in UserRepository.
Any suggestions on how to get around this?
Any help would be greatly appreciated.
EDIT: As mentioned in #shelley's answer, I was able to solve this by making 3 changes:
Removing the #Repository from UserRepositoryExtensionImpl
Renaming UserRepositoryExtensionImpl to UserRepositoryImpl. Apparently this makes Spring aware of the implementation's existence. See Spring Doc
Removing my constructor and moving the #Autowired to the userRepository field
SUCCESS!
A couple small things need to be changed in order for this to work:
Remove the #Repository annotation from the custom repository interface (UserRepositoryExtension).
The custom repository implementation should actually be named "<StandardRepository>Impl" rather than "<CustomRepository>Impl". In your code example, this should be UserRepositoryImpl instead of UserRepositoryExtensionImpl.
As shelley pointed out, the naming is really important to make the autowire work. In the example below, I follow the right naming standard for my custom interface and its implementation. But my interface that extended the JpaRepository was named “ItemDao” instead of “ItemRepository”, this resulted in that spring ignored my custom implementation altogether...
OBS!!! Should be "ItemRepository"
#Repository
public interface ItemDao extends JpaRepository<Item, Long>, ItemRepositoryCustom {}
my interface
interface ItemRepositoryCustom {...}
my implementation class
class ItemRepositoryImpl implements ItemRepositoryCustom {...}
If anyone have similar problems, start by following the naming standard that is used in the spring documentation at the link below.
http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.custom-implementations
There is a well defined way to create custom repository implementations in Spring Data JPA which you should follow. Basically you need to extend CrudRepository so you don't have to inject an instance of it in your custom implementation.
I have solved problem by injecting ApplicationContext and getting bean in lazy way using applicationContext.getBean(UserRepository.class).
It works this way.
I found I way of how to do it without the need for #Autowire:
public interface UserRepository extends
UserRepositoryBasic,
UserRepositoryExtension
{
}
public interface UserRepositoryBasic extends
JpaRepository<User, String>
{
// standard Spring Data methods, like findByLogin
}
public interface UserRepositoryExtension
{
public void customMethod();
}
public class UserRepositoryExtensionImpl implements
UserRepositoryExtension
{
private final UserRepositoryBasic userRepositoryBasic;
// constructor-based injection
public UserRepositoryExtensionImpl(
UserRepositoryBasic userRepositoryBasic)
{
this.userRepositoryBasic = userRepositoryBasic;
}
public void customMethod()
{
// we can call all basic Spring Data methods using
// userRepositoryBasic
}
}
Well in this case I suggest to use the #Lazy annotation.
public class MyCustomRepositoryImpl implements MyCustomRepository {
#Lazy
#Autowired
private MyRepository myRepository;
#Override
public boolean customMethod() {
return myRepository.count() > 0;
}
}
With constructor parameter Spring tries to create the "basic" repository class which require you custom repository which requires you "basic" repository - the typical case with circular dependency.
Without #Lazy but with only the #Autowired it also won't work (there will be problem with factory bean for the basic repo).
I think in this case the #Lazy is the most elegant solution.