Spring annation for service - spring

I am trying to use Spring annotation to define controller, service and dao, but failed.
the error message is
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.abs.absbase.ABSService] is defined: Unsatisfied dependency of type [interface com.abs.absbase.ABSService]: expected at least 1 matching bean
but I do define the service.
Another question is, how to define a sessionfactory to overwrite the HibernateDaoSupport in the ABSDaoImpl ?
Thanks
Source code is
#Controller
#RequestMapping("/abs.do")
public class ABSController {
#Autowired
#Qualifier("ABSService")
ABSService service;
...
}
#Service(value="ABSService")
public class ABSServiceImpl implements ABSService {
#Autowired
#Qualifier("ABSDao")
ABSDao dao;
}
#Repository(value="ABSDao")
public class ABSDaoImpl extends HibernateDaoSupport implements ABSDao {
...
}

According to me you just need to remove the #Qualifier annotation you have defined above the declaration of ABSService object in the controller. And also remove the (value="ABSService") from the #Service annotation on the service.
Hope this helps you.
Cheers.

Related

spring boot 2.1.3 onward throws circular reference

public abstract class CommonBillService implements BillService {
#Autowired
#Qualifier("onlineProfitServiceImpl")
private ProfitService profitService;
....
}
#Service
public class OnlineProfitServiceImpl implements ProfitService {
#Autowired
#Qualifier("aBillServiceImpl")
private BillService aBillService;
}
#Service
public class ABillServiceImpl extends CommonBillService implements Move {
....//inject other services or dao here with #Autowired,
//there is no OnlineProfitService here explicitly, but its parent CommonBillService inject OnlineProfitService by autowired
}
this code works under spring boot 2.1.2, but failed with circular reference under 2.1.3:
Error creating bean with name 'aBillServiceImpl':
Bean with name 'aBillServiceImpl' has been injected into other beans [onlineProfitServiceImpl]
in its raw version as part of a circular reference, but has eventually been wrapped.
This means that said other beans do not use the final version of the bean.
but my code has no constructor injection, i just use #Autowired to inject, so it is not possible to throw circular reference, right?

Autowire Spring bean implementing two interfaces

Is it possible to have a Spring Bean implement 2 interfaces and be able to autowire that bean using either interface?
I have the following two interfaces:
public interface ServiceA {}
public interface ServiceB {}
Two controllers which use constructor auto-wiring to inject a different service:
#RestController
public class ControllerA {
public ControllerA(ServiceA service) {}
}
#RestController
public class ControllerB {
public ControllerB(ServiceB service) {}
}
One class that implements both the services
#Service
public class ServiceImpl implements ServiceA, ServiceB { }
I am getting a NoSuchBeanDefinitionException:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ServiceB] found for dependency [ServiceB]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
I'm using Spring Boot version 1.4.0
Yes it is possible, but
it is important, to create the service bean of type ServiceImpl and not as one of the service interfaces :
#Bean
ServiceImpl service() {
return new Serviceimpl();
}
Spring uses reflection on the declared bean type to find out which interfaces it implements and not on bean.getClass().
Even if this answer was voted dowen, you can be asured : it works . If it does not work for you #scarba05, your problem must be somewhere else...
You could use the #Qualifier annotation. It can be applied alongside #Autowired or #Inject at the point of injection to specify which bean you want to be injected:
#Autowired
#Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
Source: Spring in Action 4th edition.
Let me answer your questions one by one:
Yes you can implement more than one interface in any spring bean.
Yes you can autowire with interface too as you did by constructor.
Your shared code working fine just check your SpringBootConfiguration class I think you are not scanning you service package or your service class is not in child package of SpringBootConfiguration class.
That's why you are facing:
NoSuchBeanDefinitionException

Spring Autowired annotation with service implementation

I have few doubts in the scenario below.
Having one interface and two implementation classes:
Interface:
interface ServiceInt
{
public void save();
}
First implementation class:
Public class ServiceIntImpOne implements ServiceInt
{
public void save()
{
// I am first service implementation
}
}
Second implementation class:
Public class ServiceIntImpTwo implements ServiceInt
{
public void save()
{
// I am Second service implementation
}
}
Main class calling the save method of an implementation class:
Public class controller
{
#Autowired ServiceInt;
public void save()
{
ServiceInt.save()
}
}
My Questions:
ServiceInt.save() – which save method of service class implementation will it invoke?
How we can use the save method implementation of the ServiceIntImpTwo class?
How does autowired work?
ServiceInt.save() – which save method of service class implementation
will it invoke?
If you have two beans of the same type (beans defined via annotations or via xml) when you autowire that beans it will fail (throw exception), because Spring don't know what bean to inject.
caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [ServiceInt] is defined:
How we can use the save method implementation of the ServiceIntImpTwo
class?
If you defined your bean in a xml file, then you can use the id property
<bean id="beanTwo" class="ServiceIntImpTwo" />
then you can autowire using Qualifier annotation
#Autowired
#Qualifier("beanTwo")
ServiceInt myServiceTwo;
if you are using annotations instead.
#Component
Class ServiceIntImpTwo impl...{}
Then you can autowire
#Autowired
#Qualifier("serviceIntImpTwo ")
ServiceInt myServiceTwo;
How does autowired work?
This you can read it on Internet.
http://memorynotfound.com/handling-multiple-autowire-dependencies-with-spring-qualifier/
https://www.mkyong.com/spring/spring-autowiring-qualifier-example/
https://www.tutorialspoint.com/spring/spring_qualifier_annotation.htm
If you have two implementation to one interface you will need to provide spring hint which one to use:
you can use #Qaulifier annotation
you can use #Profile and choose the active profile.

Failed to instantiate [..]: No default constructor found;

I'm getting:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.mz.server.rest.braintree.webhooks.SubscriptionWebhook]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.mz.server.rest.braintree.webhooks.SubscriptionWebhook.<init>()
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)
... 22 more
Even though I have defined this constructor in my applicatioContext-restapi.xml file:
<bean id="subscriptionWebhook" class="com.mz.server.rest.braintree.webhooks.SubscriptionWebhook">
<constructor-arg ref="dslContext" />
</bean>
Any idea why?
#RestController
public class SubscriptionWebhook {
private final static Logger LOGGER = Logger.getLogger(SubscriptionWebhook.class.getName());
private AdminService adminService;
public SubscriptionWebhook(DSLContext ctx) {
this.adminService = new AdminService(ctx);
}
}
Since Spring 3(ish) you can configure your container by applying #Component annotations to classes. #Controller annotation is defined as follows:
#Target(value=TYPE)
#Retention(value=RUNTIME)
#Documented
#Component
public #interface Controller
Which means classes annotated by it are going to get picked up, too. And RestController is just Controller and ResponseBody put together.
Anyway as you admitted in the comments you have enabled component scanning, and the configuration in xml is not going to get picked up in this case.
What you could do is convert the xml configuration to annotation-based injection, like that:
#RestController
public class SubscriptionWebhook {
private final static Logger LOGGER = Logger.getLogger(SubscriptionWebhook.class.getName());
private AdminService adminService;
public SubscriptionWebhook(#Qualifier("dslContext") DSLContext ctx) {
this.adminService = new AdminService(ctx);
}
}
Qualifier annotation is going to look in the container for a bean with name/id dslContext and inject it in the constructor. Alternatively you can use the javax.inject Named annotation, or if this is the only bean with that type, Spring's #Autowired or JSR-330's #Inject.
Annotation #RestController is autodetected by spring. Spring will create a bean for you so you shouldn't add bean definition in the xml, because it would create a second bean. If you want to inject another bean into the controller just use #Autowired. So the solution in your case is:
Remove "subscriptionWebhook" bean definition from the xml
Add #Autowired on SubscriptionWebhook constructor

Spring expected at least 1 bean which qualifies as autowire candidate for this dependency

I have a trouble with this Autowire:
#Controller
public class ChiusuraController {
#Autowired
private ChiusuraProvider chiusuraProvider;
}
with this bean:
#Service #Transactional
public class ChiusuraProvider extends ThreadProvider {
public void run() {}
}
that extends
public abstract class ThreadProvider extends Thread implements InitializingBean, Runnable, DisposableBean {
...
}
I get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'chiusuraController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.cinebot.service.ChiusuraProvider com.cinebot.web.controller.ChiusuraController.chiusuraProvider; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.cinebot.service.ChiusuraProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I saw that I did not get this error if I remove extends ThreadProvider of autowired class, but I really need ThreadProvider abstract class.
If there is an interface anywhere in the ThreadProvider hierarchy try putting the name of the Interface as the type of your service provider, eg. if you have say this structure:
public class ThreadProvider implements CustomInterface{
...
}
Then in your controller try this:
#Controller
public class ChiusuraController {
#Autowired
private CustomInterface chiusuraProvider;
}
The reason why this is happening is, in your first case when you DID NOT have ChiusuraProvider extend ThreadProvider Spring probably was underlying creating a CGLIB based proxy for you(to handle the #Transaction).
When you DID extend from ThreadProvider assuming that ThreadProvider extends some interface, Spring in that case creates a Java Dynamic Proxy based Proxy, which would appear to be an implementation of that interface instead of being of ChisuraProvider type.
If you absolutely need to use ChisuraProvider you can try AspectJ as an alternative or force CGLIB based proxy in the case with ThreadProvider also this way:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Here is some more reference on this from the Spring Reference site: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/classic-aop-spring.html#classic-aop-pfb
You should put this line in your application context:
<context:component-scan base-package="com.cinebot.service" />
Read more about Automatically detecting classes and registering bean definitions in documentation.

Resources