DZone
Java Zone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
  • Refcardz
  • Trend Reports
  • Webinars
  • Zones
  • |
    • Agile
    • AI
    • Big Data
    • Cloud
    • Database
    • DevOps
    • Integration
    • IoT
    • Java
    • Microservices
    • Open Source
    • Performance
    • Security
    • Web Dev
DZone > Java Zone > Spring component scan for beans with no no-args constructor

Spring component scan for beans with no no-args constructor

Fahim Farook user avatar by
Fahim Farook
·
Nov. 23, 14 · Java Zone · Tutorial
Like (1)
Save
Tweet
40.04K Views

Join the DZone community and get the full member experience.

Join For Free

Suppose you have the following spring set-up 

  • component scan enabled
  • a class (MailServer) with
    • some constructors (no no-args constructor)
    • annotated with @Component (or @Service / @Named)
  • declaration of above class in the spring-config
    • (Even though you have component-scan enabled, suppose you need to configure the default mail server with a name "defaultMailServer" )
  • injecting the above "defaultMailServer" to a property of another class (i.e. MailSender)


Spring Configuration

 <bean id="defaultMailServer" class="me.fahimfarook.mail.MailServer"  scope="singleton">  
     <constructor-arg name="host" value="smtp.gmail.com" />  
     <constructor-arg name="port" value="587" />  
     <constructor-arg name="protocol" value="smtp" />  
 </bean>  
 <context:component-scan base-package="me.fahimfarook.mail" />  


MailServer.java

 @Component  
 public class MailServer {  
    private String host;   
    private int port;   
    private String protocol;  

    public MailServer(final String host, final int port, final String protocol) {  
       this.host = host;  
       this.port = port;  
       this.protocol = protocol;  
    }  

    //getters  
 }  


MailSender.java

@Service  
 public class MailSenderImpl implements MailSender {  

    @Autowired  
    @Qualifier("defaultMailServer")  
    private MailServer mailServer;  

    @Override  
    public void send() {  
      // TODO  
    }  
 }  


Main.java

public class Main {  
    private static final String CONFIG_PATH = "classpath*:application-config.xml";  

    public static void main(final String[] args) {  
       final ApplicationContext context = new ClassPathXmlApplicationContext(CONFIG_PATH);  
       final MailSender mailSender = context.getBean(MailSenderImpl.class);  
       mailSender.send();  
    }  
 }  


Nothing looks wrong. But when you execute the program you will get the following exception.

org.springframework.beans.BeanInstantiationException: 
Could not instantiate bean class [me.fahimfarook.mail.MailServer]: No default constructor found;  


This error message is misleading because we are not accessing MailServer with default constructor anywhere in our code. We have injected "defaultMailServer" which is properly defined with constructor-args.

However, if you add a no-args constructor to MailServer this exception will go away. That means spring context is trying to create a MailServer object using no-args constructor somewhere even though we have defined a MailServer with constructor-args. But we have defined a MailServer bean with constructor-args and accessing that bean only?

The reason for that is - we have defined a bean explicitly in the spring config xml while we have enabled component scanning. Spring will create the "defaultMailServer" bean successfully since constructor-args have been defined in the spring config xml. However, since component scanning has been enabled, spring will try to automatically discover and register another MailServer bean. However, this will fail because spring can't create an object using the defined constructor as we have not auto-wired the constructor / parameters in the constructor. As the second step, spring will try to create a MailServer with no-args constructor.

Therefore you need to have auto-wired the constructor which you defined in the spring-config file in order to get rid of this error.

MailServer.java - Fixed

@Component  
 public class MailServer {  
      private String host;  
      private int port;  
      private String protocol;

      @Autowired  
      public MailServer(@Value("")final String host, @Value("#{new Integer(-1)}")final int port, @Value("")final String protocol) {   
           this.host = host;  
           this.port = port;  
           this.protocol = protocol;  
      }  
 }  


Now that you have auto-wired the constructor which is defined with "defaultMailServer", spring can create this bean and it will not demand a default constructor. However, if spring had thrown BeanInstantiationException with a message like "Constructor for defaultMailServer could not be found" instead of "No default constructor found", the exact issue with the code could have been identified easily.


In summary:

  • If component scanning is enabled, spring will try to create a bean even though a bean of that class has already been defined in the spring config xml.
  • However if the bean defined in the spring config file and the auto-discovered bean have the same name, spring will not to create a new bean while it does component scanning.
  • If a bean does not have a no-args constructor, at-least one of the constructors must be auto-wired.
  • If no constructor is auto-wired, spring will try to create an object using default no-args constructor.
Original post here 
Spring Framework

Published at DZone with permission of Fahim Farook. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Testing Under the Hood Or Behind the Wheel
  • How to Upload/Download a File To and From the Server
  • Debugging the Java Message Service (JMS) API Using Lightrun
  • How to Test JavaScript Code in a Browser

Comments

Java Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • MVB Program
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends:

DZone.com is powered by 

AnswerHub logo