I am facing an issue with Spring-DM and #Autowired with Osgi Services.
I have defined a Spring bean + OSGI Service as following:
<bean id="my.sessionFactoryBean"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource">
<ref local="my.dataSource" />
</property>
...
</bean>
<osgi:service ref="my.sessionFactoryBean"
id="my.sessionFactory" interface="org.hibernate.SessionFactory" />
I can reference, from another bundle, this service without any problem in an xml bean definiton like following:
<beans>
...
<osgi:reference id="my.sessionFactory"
interface="org.hibernate.SessionFactory" />
..
<bean id="my.databaseItemReader"
class="my.MyReader">
<property name="sessionFactory" ref="my.sessionFactory" />
...
</beans>
My problem relies on using the #Autowired anotation like following:
public abstract class AbstractHibernateDao {
#Autowired
#Qualifier(value="my.sessionFactory")
private SessionFactory sessionFactory;
...
I am getting the classic error:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.hibernate.Sess
ionFactory my.AbstractHibernateDao.sessionFactory; nested exception is org.springfr
amework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.hibernate.SessionFactory] found for d
ependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {
#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qu
alifier(value=my.sessionFactory)}
If I remove the #Qualifier, I get this error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: [my.sessionFactoryBean, my.sessionFactory]
Which makes me think that I do have my OSGI-Service in the Spring bean registry ...
Any ideas what I am doing wrong?
FYI, I have also tried to inject OSGI-services with #ServiceReference on the setter, but Spring-DM never injects it (have some nullpointerexception)
Just a guess but when you use #Autowire, you must be doing "context:component-scan" and this in turn might be finding the additional bean that is showing up (my.sessionFactoryBean). When injected using XML, perhaps the component scan is not enabled and hence the OSGi service is properly getting resolved.
Related
I am getting below message while deploying spring MVC application into Weblogic (12.2.1.3.0)
NoSuchBeanDefinitionException:No qualifying bean of type [weblogic.messaging.saf.internal.SAFServerService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.inject.Inject(), #javax.inject.Named(value=SAFServerService)
Please help.
Spring can automatically detect classes and register beans. see details at Classpath scanning and managed components.
Adding inside to skip the concerned Java packages related to com.oracle and IBM, which are not used or referenced directly by the application, should prevent the errors from happening during deployment.
In the involved war file, the application has used Spring application-context.xml at /WEB-INF/classes/../../ for allowing the search for classes annotated with #Component, #Repository, #Service, and #Controller in Spring classpath.
Example of the application-context.xml :-
<context:component-scan base-package="com,test" scoped-proxy="no">
<context:exclude-filter type="regex" expression="com\.oracle.*" />
<context:exclude-filter type="regex" expression="com\.ibm.*" />
</context:component-scan>
I'm new to Spring (& boot) and I'm facing the following problem. I have some Beans defined in an XML file. I can retrieve these beans using ApplicationContext.getBean(), instead I would like to Autowire them, or use them in classes which do not have access to 'ApplicationContext'
A simplified version of my project:
beans.xml:
<bean id="PartnerDao" name="PartnerDao" class="partner.dao.PartnerDAOImpl">
<constructor-arg index="0" value="${integration.username}"/>
<constructor-arg index="1" value="${integration.password}"/>
</bean>
applicationContext.xml:
<beans>
<import resource="classpath:beans.xml" />
<context:annotation-config/>
<cache:annotation-driven/>
<task:annotation-driven/>
</beans>
Application.java:
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
PartnerService.java:
#Service
public class PartnerService {
#Autowired
#Qualifier("PartnerDao")
PartnerDAO partnerDao;
}
When I build I hit the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'partner.dao.PartnerDAO' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=PartnerDao)}
As I mentioned, I'm new to Spring, and have been using Spring Boot's annotations to maneuver, but my supervisor constructed this beans.xml in order to integrate with other services and I'm not sure how to autowire it.
I can always do:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
PartnerDAO partnerDao = context.getBean(partner.dao.PartnerDAOImpl.class);
But I'd rather just autowire it.
Is there any other viable solution?
Thank you.
Bean wiring corresponds to providing the dependencies a bean might need to complete it’s job. In Spring, beans can be wired together in two ways : Manually and Autowiring.
Manual wiring : using ref attribute in property or constructor tag
<bean id="PartnerDao" name="PartnerDao" class="partner.dao.PartnerDAOImpl">
<constructor-arg index="0" value="${integration.username}">
<ref bean="PartnerDao" />
<constructor-arg/>
<constructor-arg index="1" value="${integration.password}"/>
</bean>
I am not sure whether this will work or not but atleast you can try.
I'm using spring-data-couchbase 2.1.2, I want add methods to a single repository.
In implementation class:
public class MyRepositoryImpl implements MyRepositoryCustom {
#Autowired
RepositoryOperationsMapping templateProvider;
....
}
I added the RepositoryOperationsMapping but the object is not injected, I have the error below:
[org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException
For spring configuration I used the spring.xml file, how add in xml file the RepositoryOperationsMapping reference?
Thanks. Bye.
I solved the issue, below a snippet my spring.xml file
<couchbase:clusterInfo login="${cluster.username}" password="${cluster.password}" id="clusterInfo" />
<couchbase:bucket bucketName="${bucket.name}" bucketPassword="${bucket.password}" id="bucket"/>
<!-- template is just using default parameters and references as well -->
<couchbase:template translation-service-ref="myCustomTranslationService" />
<bean id="myCustomTranslationService"
class="org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService"/>
<bean id="couchbaseTemplate" class="org.springframework.data.couchbase.core.CouchbaseTemplate">
<constructor-arg ref="clusterInfo"/>
<constructor-arg ref="bucket" />
<constructor-arg ref="myCustomTranslationService" />
</bean>
<bean id="repositoryOperationsMapping" class="org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping">
<constructor-arg ref="couchbaseTemplate"/>
</bean>
I'm developing a spring application using JavaFX (I'm NOT using Spring MVC) and I have standard separation of concerns with controllers - services - DAOs. I'm using JdbcTemplate. I'm willing to write down jUnit tests for one of my services (I have already did it for some of them). The specific thing is that the service is autowiring two DAOs(one of which uses transactions itself) and furthermore it has one method, which is #Transactional. This is how my test exactly looks:
package org.impactvolunteers.management.service.impl;
imports ...;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:testContext.xml" })
#DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class RegisterVolunteerServiceImplTest extends
AbstractRegisterVolunteerServiceTest {
#Autowired
private RegisterVolunteerService registerVolunteerService;
#Before
public void setUp() {
setRegisterVolunteerService(registerVolunteerService);
}
}
And my Service implementation:
package org.impactvolunteers.management.service.impl;
imports ...;
public class RegisterVolunteerServiceImpl implements RegisterVolunteerService {
#Autowired
private VolunteerDao volunteerDao;
#Autowired
private UserDao userDao;
#Transactional(rollbackFor = { ServiceException.class,
ValidationException.class })
public Volunteer registerVolunteer(User user, Volunteer volunteer)
throws ServiceException, ValidationException {
UserValidator.validateData(user);
VolunteerValidator.validateData(volunteer);
try {
User ret = userDao.create(user);
volunteer.setUser(ret);
return volunteerDao.create(volunteer);
} catch (PersistenceException e) {
throw new ServiceException(e.getMessage(), e);
}
}
}
And in application-Context:
<context:component-scan base-package="org.impactvolunteers.management"/>
<!-- enable the configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<!-- Transaction Manager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
...
<bean id="registerVolunteerService" class="org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImpl" >
</bean>
Here is the error message:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name
'org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImplTest':
Injection of autowired dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: private
org.impactvolunteers.management.service.RegisterVolunteerService
org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImplTest.registerVolunteerService;
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[org.impactvolunteers.management.service.RegisterVolunteerService]
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)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
............
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[org.impactvolunteers.management.service.RegisterVolunteerService]
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)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:988)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:486)
... 28 more
And my test-Context.xml:
<context:annotation-config/>
<context:component-scan base-package="org.impactvolunteers.management"/>
<bean id="jdbc" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Spring JDBC Utility for in-memory database -->
<jdbc:embedded-database id="dataSource" type="HSQL"/>
Two strange things I noticed:
I have no problem starting the application as Java application and the service works as intended. I have only problems testing the service as jUnit test.
A service with the exact same context (and the same context for the test as the test showed here) and bean definition is being successfully tested with the only difference that it does not contain #Transactional annotations, where some of the DAOs under it do (VolunteerDaoImpl which implements VolunteerDao does contain a #Transactional annotation).
The class RegisterVolunteerServiceImpl must be annotated as service.
If the class is not annotated as a service it will not befound by the component-scan. So the bean with the name is not instanciated and can not be autowired.
In your main application-context you add the bean without component-scan
<bean id="registerVolunteerService" class="org.impactvolunteers.management.service.impl.RegisterVolunteerServiceImpl" >
</bean>
That testContext.xml doesn't import your general-purpose application context, and it also doesn't define that registerVolunteerService bean.
I try to using spring integration in different jars.
In the A.jar si-context.xml:
<context:annotation-config />
<int:annotation-config />
<int:channel id="upperServiceChannel">
<int:priority-queue />
</int:channel>
<int:gateway id="upperGateway" default-request-timeout="5000"
default-reply-timeout="5000" default-request-channel="upperServiceChannel"
service-interface="com.company.proj.gw.IUpperStringConversation">
<int:method name="toUpperCase" />
</int:gateway>
<bean id="toUpperCaseService" class="com.company.proj.service.ToUpperCaseService" />
<int:service-activator id="serviceActivatorToUpperCase"
input-channel="upperServiceChannel" method="toUpperCase" ref="toUpperCaseService" />
<int:poller id="poller" default="true" fixed-delay="1000" />
<context:component-scan base-package="com.company"/>
In a bean I'm using this gateway:
#Component(value = "upper")
public class UpperAdapter extends AAdapter<Message<String>> {
#Autowired
IUpperStringConversation gw;
It's working. The problem is, if I try to using my UpperAdapter from an other project (B.jar).
b-context.xml:
<import resource="classpath*:/*si-context.xml" />
<context:annotation-config />
<int:annotation-config />
#Component(value="router")
public class Router {
#Autowired
private Map<String, AAdapter<?>> adapters;
And here I get:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'upper': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.company.proj.gw.IUpperStringConversation com.company.proj.adapter.UpperAdapter.gw; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.company.proj.gw.IUpperStringConversation] 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)}
After I set the spring log level to debug, get this information:
DEBUG o.s.c.a.ClassPathBeanDefinitionScanner - Ignored because not a concrete top-level class: URL [jar:file:/home/tomto/Documents/workspace-sts/integration-fw/src/main/resources/META-INF/lib/integration-fw-module-string-0.0.1-SNAPSHOT.jar!/com/company/proj/gw/IUpperStringConversation.class]
Of course, it's true, becouse (maybe I'm wrong ;)) it would be at runtime generated gateway by spring.
The IUpperStringConversation:
public interface IUpperStringConversation {
public String toUpperCase(String text);
}
What I missed?
Thx!
We had a similar issue, our gateways were not getting injected into our service object:
Project structure:
----------------
-parent/
-common/
--gateways defined here
-module-a/
-module-b/
The exception message received in module-b was:
org.springframework.beans.factory.BeanCreationException: ... Injection of autowired dependencies failed
...
IllegalArgumentException: Class must not be null
Apparently the issue was being caused by conflicting dependencies we had on the module-b classpath. After we cleaned up the Spring dependencies in pom.xml it worked!