flynfish
flynfish

Reputation: 5867

Spring Bean Autowiring error

I am trying to implement email functionality in my app but I keep getting

No matching bean of type [org.springframework.mail.javamail.JavaMailSenderImpl] found for dependency:  expected at least 1 bean which qualifies as autowire candidate for this dependency.

Can anyone point out what I am doing incorrectly?

The xml config for the bean is:

<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"   
xsi:schemaLocation="
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<context:annotation-config/>
//...other stuff

<beans:bean id="mailSession" class="org.springframework.jndi.JndiObjectFactoryBean">
    <beans:property name="jndiName" value="EmailServer" />
</beans:bean>

<beans:bean id="emailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <beans:property name="session" ref="mailSession"/>
</beans:bean>

EmailServiceImpl class:

@Service
public class EmailServiceImpl implements EmailService {

    @Autowired
    private JavaMailSenderImpl emailSender; 

    //more code..
}

project_structure

Upvotes: 6

Views: 12765

Answers (6)

Sri Sankaran
Sri Sankaran

Reputation: 8310

I was struggling with this very problem for an email service class coded like:

@Service("emailService")
public class EmailService {
  @Autowired private JavaMailSenderImpl mailSender;
  ...
  public void send(...) {
    // send logic
  }
}

I stumbled across a solution while reading about a related topic. The key point is that JavaMailSender interface is defined in the applicationContext.xml as the Spring JavaMailSenderImpl class.

Step 1: The application context file was modified to include the following bean definition:

<bean id="mailSender" 
   class="org.springframework.mail.javamail.JavaMailSenderImpl"
  p:host="myMailserver.mycompany.com" />

Step 2: The email service class was modified to look like:

@Service("emailService")
public class EmailService {
  @Autowired private JavaMailSender mailSender;   // Observe the change in the type
  ...

Voila! Spring is happy. I would though like to hear a proper explanation of the original error.

Upvotes: 4

Ulises
Ulises

Reputation: 13419

This is how I fixed it:

I ran into this issue too, I tried to follow simple tutorials online that worked perfectly during testing by loading the app-context.xml file manually but when I tried to run my spring mvc app it kept showing this error:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.mail.javamail.JavaMailSender] 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:952)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:821)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:735)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
    ... 42 more

After trying all kinds of things, I happened to move these two lines from my JPA/DB configuration file to the bottom of my root-config file.

<context:annotation-config/>           
<context:component-scan base-package="my.app.service.layer"/>

I'm still learning Spring but I'm thinking there was an issue regarding the order in which they appear.

Edit: This question seems to clarify the issue with the order:

Difference between applicationContext.xml and spring-servlet.xml in Spring Framework

Upvotes: 1

flynfish
flynfish

Reputation: 5867

Thanks to everyone for their responses. I was unable to get the autowiring to work, but I got the overall email solution to work by doing the following:

  1. setup the mailSession in weblogic, with a jndi name of "myMailSession"

add to servlet-context.xml:

<beans:bean id="mailSession" class="org.springframework.jndi.JndiObjectFactoryBean">
    <beans:property name="jndiName" value="myMailSession" />
</beans:bean>

<beans:bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <beans:property name="session" ref="mailSession"/>
</beans:bean>

<beans:bean id="emailServiceImpl" class="com.name.here.business.EmailServiceImpl">
  <beans:property name="mailSender" ref="mailSender"/>
</beans:bean>

add to web.xml:

<resource-ref>
   <description>the email session</description>
   <res-ref-name>myMailSession</res-ref-name>
   <res-type>javax.mail.Session</res-type>
   <res-auth>Container</res-auth>
</resource-ref> 

add to weblogic.xml:

<resource-description>
  <res-ref-name>myMailSession</res-ref-name>
  <jndi-name>myMailSession</jndi-name>
</resource-description>

EmailServiceImpl:

@Service
public class EmailServiceImpl implements EmailService {

    private JavaMailSender mailSender;

    public void setMailSender(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }
    //..other code
}

Upvotes: 2

Jon Riegel
Jon Riegel

Reputation: 21

Do you have a @Service or similar annotation on your JavaMailSenderImpl class itself? This will cause Spring's component scanner to put an instance of it in the spring container, which it can then autowire onto the EmailServiceImpl.

Upvotes: 1

Dhananjay
Dhananjay

Reputation: 3975

From error message, I can conclude that autowiring is working , but its not able to find the required bean.

Make sure you load all the bean definition files.

Upvotes: 1

Travis
Travis

Reputation: 336

You need to add <context:annotation-config/> to your config file in order for Spring to autowire annotated beans.

http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-annotation-config

Upvotes: 1

Related Questions