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.
Related
I have a Spring 4.3 application which works fine.
I'm trying to use JUnit 4.11 but the context doesn't load.
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
'caesb.websupport.service.BatchSolicitacaoService' available: expected
at least 1 bean which qualifies as autowire candidate. Dependency
annotations: {#javax.inject.Inject()}
base-spring-application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
....
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" />
<context:annotation-config />
<context:component-scan base-package="caesb">
</context:component-scan>
</beans>
test-spring-application.xml
It has only datasource configuration.
BatchSolicitacaoService.java
#Service
public class BatchSolicitacaoService extends BaseEntityService<BatchSolicitacao>
{
...
}
PriorizacaoHidrometroDWService.java
#Service
public class PriorizacaoHidrometroDWService extends BaseEntityService<PriorizacaoHidrometroDW>
{
...
#Inject
private BatchSolicitacaoService batchSolicitacaoService;
}
BasicTest.java
#RunWith(SpringJUnit4ClassRunner.class)
#TestExecutionListeners( { DependencyInjectionTestExecutionListener.class})
#ContextConfiguration({"classpath*:/base-spring-application.xml","classpath*:/test-spring-application.xml"})
#Transactional
public class BasicTest
{
#Test
public void test() {
System.out.println("teste teste");
}
}
I have added #TestExecutionListeners, but without success.
I removed #Transaction, but also without success.
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'd like to inject JMock mock beans from Spring XML Configuration.
I have the following test
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "/application-context-test.xml")
public class CorporateInfoServiceImplTest
{
#Autowired
private Mockery mockery;
#Autowired
private CorporateInfoServiceImpl corporateInfoService;
#Test
public void createCorporateInfo() {...}
}
And such XML configuration:
<bean id="mockery" class="org.jmock.Mockery">
<property name="imposteriser">
<util:constant static-field="org.jmock.lib.legacy.ClassImposteriser.INSTANCE"/>
</property>
</bean>
<bean id="createCorporateInfoOperation" class="com.acme.corp.ws.operation.CreateCorporateInfoOperation" factory-bean="mockery" factory-method="mock">
<constructor-arg value="com.acme.corp.ws.operation.CreateCorporateInfoOperation" type="java.lang.Class" />
</bean>
<bean id="corporateInfoService" class="com.acme.corp.ws.CorporateInfoServiceImpl">
<property name="createCorporateInfoOperation" ref="createCorporateInfoOperation" />
</bean>
CorporateInfoServiceImpl and CreateCorporateInfoOperation are kind of:
public class CorporateInfoServiceImpl implements CorporateServiceInterface
{
#Autowired
CreateCorporateInfoOperation createCorporateInfoOperation;
...
}
#Component
public class CreateCorporateInfoOperation
{
#Autowired
CorporateInfoDao corporateInfoDao;
...
}
When trying to autowire the CorporateInfoServiceImpl I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.acme.corp.dao.CorporateInfoDao] 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)}
The problem is that CreateCorporateInfoOperation tries to autowire dao even when created form factory-method. How can I disable such autowiring?
Other variants of injecting mock beans in JMock are appreciated.
Thanks in advance
I have problem injecting a value to a bean using Spring MVC.
Here's my partial configuration of Spring:
<beans>
<!-- Enable Annotation based configuration -->
<context:annotation-config />
<!-- MailGun.org Authentication -->
<bean class="com.example.something.util.MailSender">
<property name="smtpHost" value="smtp.mailgun.org" />
<property name="smtpUsername" value="USERNAME_HERE" />
<property name="smtpPassWord" value="PASSWORD_HERE" />
</bean>
</beans>
And here's the bean to inject:
package com.example.something.util;
#Component
public class MailSender {
public void sendMail(String recipient, String subject, String text) {
System.out.println(smtpHost);
}
#Autowired
private String smtpHost;
}
To test this, I create a test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:test-spring-context.xml"})
public class MailSenderTest {
#Test
public void testSendMail() {
MailSender sender = new MailSender();
sender.sendMail("zjhzxhz#gmail.com", "Mail From MailGun", "This is a test mail");
}
}
When I run this test case, I got an exception:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.example.something.util.MailSender.smtpHost; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] 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$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 41 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [java.lang.String] 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:1308)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1054)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:949)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 43 more
What's wrong with it? Please help me. Thx!
You don't need #Autowired on smtpHost, it should be already populated if you get the MailSender bean from the Spring context. Which you don't, because instantiating it with new MailSender() bypasses Spring altogether. Instead you should use context.getBean(MailSender.class).
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.