There are different functionalities in my application. And for those multiple functionalities, different components are created.
In one of the component(which is created as jar in my war file), say Component A, i have used ServiceLocatorFactoryBean for locating services.
Now i want to use ServiceLocatorFactoryBean in another component, say Component B. On using this in different component also, i am getting :
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.kronos.payroll.aggregation.registry.PayrollServiceRegistry' available: expected at least 1 bean which qualifies as autowire candidate.
This, i am assuming occurs because there is already a ServiceLocatorFactoryBean created in Component A. Can anyone help of what can be done for this ?
In Component A,
#Configuration
public class ProductConfig {
#Bean
public FactoryBean factoryBean() {
final ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
bean.setServiceLocatorInterface(ServiceRegistry.class);
return bean;
}
}
In Component B:
#Configuration
public class PayrollProductConfig {
#Bean("payrollServiceRegistry")
public FactoryBean factoryBean() {
final ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
bean.setServiceLocatorInterface(PayrollServiceRegistry.class);
return bean;
}
}
Related
#DataJpaTest
class DataJpaVerificationTest {
#Autowired
private JdbcTemplate template;
#Test
public void testTemplate() {
assertThat(template).isNotNull();
}
}
When I run this test I get the following error:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'kafkaConfig' defined in file
[***\config\KafkaConfig.class]:
Unsatisfied dependency expressed through constructor parameter 0;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'org.springframework.boot.autoconfigure.kafka.KafkaProperties'
available: expected at least 1 bean which qualifies as autowire
candidate. Dependency annotations: {}
where KafkaConfig class is a part of my application (app read data from Kafka and saves data to DB) and looks like:
#Configuration
#RequiredArgsConstructor
public class KafkaConfig {
private final KafkaProperties kafkaProperties;
#Bean
public Properties consumerProperties() {
Properties props = new Properties();
props.putAll(this.kafkaProperties.buildConsumerProperties());
return props;
}
}
Based on information that I googled about DataJpaTest annotation:
created application context will not contain the whole context needed
for our Spring Boot application, but instead only a “slice” of it
containing the components needed to initialize any JPA-related
components like our Spring Data repository.
So the question is: why Spring tries to load to the context Kafka specific bean for DataJpaTest?
I have two classes that I want to autowire using spring
#Component
public class Restaurant {
#Autowired
#Qualifier("HighClass")
private CoffeeMaker coffeeMaker;
}
and:
public class CappuccinoMaker implements CoffeeMaker{
#Autowired
#Qualifier("HighClass")
int numOfSpoons;
}
Then injecting:
#Bean(name="HighClass")
#Scope("prototype")
public CoffeeMaker HighClassCoffeeMakerGenerator() {
return new CappuccinoMaker();
}
#Bean(name="HighClass")
public int getNumOfSpoons() {
return 3;
}
I'd like to qualify both the int and the CoffeeMaker with "HighClass". In Guice it is possible to annotate different types with the same annotation and inject them correctly.
It seems like in spring this is not allowed. When I try injecting the fields I get an error that the required bean was not found. Did I miss anything?
Bean name in Spring is unique. Use #Profile in order to pick a bean from several competing variants.
I have some java objects coming from external library which I need to inject in my spring project. Problem is the classes from library is not aware of any spring api's
If I inject the beans from library to Service using #Autowired I am getting org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type
Following is my service class
#Path("/test")
public class TestService {
#Autowired
SomeOtherClass service;
#GET
public Response get(){
return Response.ok(service.someMethod()).build();
}
}
and following is my class from library which is not aware of spring
public class SomeOtherClass {
public String someMethod(){
return "Data from library";
}
}
When I invoke my service I get exception as
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.SomeOtherClass' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Is there are way in spring to inject a plain Java Object similar to that of injection in **CDI**?
There is one option to define applicationcontext.xml and define SomeOtherClass in xml and use getBean, but I don't want to do that. Is there any other option?
Note:
Following options cannot be considered because I have100's of classes coming from library
Cannot use applicationcontext.xml
Cannot #Configuration #Bean to produce beans.
You could use the #Configuration and #Bean annotations as follows -
Create a new class:
#Configuration
public class AppConfig {
#Bean
SomeOtherClass someOtherClassBean(){ return new SomeOtherClass();}
}
Now the auto wiring shall work.
What it does, is actually creating a bean and letting Spring know about it.
Maybe try adding the beans programatically to the IoC container:
Add Bean Programmatically to Spring Web App Context
You need to find all the classes you want to instantiate and use one of the methods in the linked question.
You can use reflection to add Bean definitions programatically.
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Reflections ref = new Reflections(new ConfigurationBuilder()
.setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
.setUrls(ClasspathHelper.forPackage(PACKAGE_NAME))
.filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(PACKAGE_NAME))));
ref.getSubTypesOf(Object.class).stream()
.forEach(clazz -> {
logger.info("Defining pojo bean: {} -> {}", Introspector.decapitalize(clazz.getSimpleName()), clazz.getCanonicalName());
registry.registerBeanDefinition(Introspector.decapitalize(clazz.getSimpleName()),
BeanDefinitionBuilder.genericBeanDefinition(clazz).getBeanDefinition());
});
}
Subsequently, these beans can be #Autowired elsewhere. See Gist: https://gist.github.com/ftahmed/a7dcdbadb8bb7dba31ade463746afd04
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
I'd like to create an autowired bean in a Dao class in order to do logging opperations. My way was hitherto static final statement like this:
private static final Log log = LogFactory.getLog(LoggedClass.class);
But now I'm trying to use IoC to turn classes decoupled.
If just add configuration in pom.xml and try to do sth like
#Autowired
Log log;
I receive an error message:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'funciDaoImpl': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.apache.commons.logging.Log br.com.bb.dirco.dao.impl.FunciDaoImpl.log; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'log' defined in class path resource [com/company/project/util/PersistenceConfig.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.Class]: : No qualifying bean of type [java.lang.Class] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.Class] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
In order to get a logger, I had to provide a class to getLog method on LogFactory class and attribute it to Log instance. There's a way to do it using #Autowired Spring IoC? Thanks!
You can inject only those objects which are managed/created by Spring container. You have to register your bean (or factory method creating the bean) with container (with annotations like #Component/#Singleton/... or directly in xml)
In your case it's not very applicable since you have to have many different types (for every class) of logger objects provided by Spring and then when you inject they would have to be identified by different name/type for every class.
P.S. I don't see any problem using it the way you use it now
Where I work we have implemented support for #Autowired SLF4J Loggers using Springs BeanPostProcessor.
First you need to define an Logger placeholder bean in your application context. This bean is going to be injected by Spring into all bean with a #Autowired Logger field.
#Configuration
public class LoggerConfig {
#Bean
public Logger placeHolderLogger() {
return PlaceHolder.LOGGER;
}
#Bean
public AutowiredLoggerBeanPostProcessor loggerPostProcessor() {
return new AutowiredLoggerBeanPostProcessor();
}
}
Then you an AutowiredLoggerBeanPostProcessor which inspects all beans, indetify bean that contain Logger fields annotated with #Autowired (at this point should contain a reference to the Logger placeholder bean), create a new Logger for the partilcar bean an assigned it to the fields.
#Component
public class AutowiredLoggerBeanPostProcessor implements BeanPostProcessor, PriorityOrdered {
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
attachLogger(bean);
return bean;
}
#Override
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
attachLogger(bean);
return bean;
}
private void attachLogger(final Object bean) {
ReflectionUtils.doWithFields(bean.getClass(), new FieldCallback() {
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
if (Logger.class.isAssignableFrom(field.getType()) &&
(field.isAnnotationPresent(Autowired.class) ||
field.isAnnotationPresent(Inject.class))) {
ReflectionUtils.makeAccessible(field);
if (field.get(bean) == PlaceHolder.LOGGER) {
field.set(bean, LoggerFactory.getLogger(bean.getClass()));
}
}
}
});
}
#Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}