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).
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 have read the TCP-Server-Client and try to run my example but I am getting the following error:
2017-03-27 15:13:08 ERROR ContextLoader:331 - Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorldController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.example.myapp.integration.SimpleGateway com.example.myapp.controller.HelloWorldContr oller.gw; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.myapp.integration.SimpleGateway] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Aut owired(required=true)}
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1210)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:303)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:299)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.example.myapp.integration.SimpleGateway com.example.myapp.controller.Hell oWorldController.gw; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.myapp.integration.SimpleGat eway] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.ann otation.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)
... 26 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.myapp.integration.SimpleGateway] found for dependency: ex pected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=tru e)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 28 more
My Controller:
#Controller
public class HelloWorldController {
#Autowired
SimpleGateway gw;
#RequestMapping(value = { "/", "/home", "/frontend" }, method = RequestMethod.GET)
public String homePage(Locale locale, ModelMap model) {
gw.send("test");
return "frontend";
}
}
My xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
<context:property-placeholder />
<!-- Client side -->
<int:gateway id="gw"
service-interface="com.example.myapp.integration.SimpleGateway"
default-request-channel="input"/>
<!-- Create a connection for the client gateway that uses the same Stx-Etx deserializer to turn the stream
into the appropriate content (it looks for the Stx byte, extracts anything between it and the Etx byte). We
don't specify the serializer (although we could) because the unit test explicitly shows how the content
to be sent is wrapped by the Stx and Etx bytes. -->
<int-ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="50001"
single-use="true"
so-timeout="10000"
deserializer="connectionSerializeDeserialize"/>
<int:channel id="input" />
<int-ip:tcp-outbound-gateway id="outGateway"
request-channel="input"
reply-channel="clientBytes2StringChannel"
connection-factory="client"
request-timeout="10000"
reply-timeout="10000"/>
<int:channel id="clientBytes2StringChannel"/>
<int:object-to-string-transformer id="clientBytes2String"
input-channel="clientBytes2StringChannel" />
<!-- Server side -->
<!-- When creating the socket factory on the server side, we specify both the serializer and deserializer
which deals with both accepting a stream formatted with the Stx-Etx bytes as well as sending a stream
formatted with the Stx-Etx bytes. -->
<int-ip:tcp-connection-factory id="serverConnectionFactory"
type="server"
port="65535"
serializer="connectionSerializeDeserialize"
deserializer="connectionSerializeDeserialize"/>
<bean id="connectionSerializeDeserialize" class="org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer"/>
<int-ip:tcp-inbound-gateway id="gatewayCrLf"
connection-factory="serverConnectionFactory"
request-channel="incomingServerChannel"
error-channel="errorChannel"/>
<!-- We leave a message listener off of this channel on purpose because we hook
one up before the test actually runs (see the unit test associated with this
context file) -->
<int:channel id="incomingServerChannel" />
</beans>
I have not figured out, if is needed any other additional configuration file.
Edit 1:
My configuration file:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.example.myapp")
public class HelloWorldConfiguration extends WebMvcConfigurerAdapter {
...
}
You need to import the XML configuration.
Add #ImportResource("foo.xml") to your #Configuration class.
Or, add the Spring Integration configuration using #Beans instead of XML.
It seems like you haven't specified the component scan location. Try adding the below tag to XML.
<context:component-scan base-package="<package-to-scan-under-spring-servlet>" />
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!
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.