Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is default constructor required in Spring injection?

I'm trying to inject a constructor that takes some arguments. After compiling Spring complains it couldn't find a default constructor (I haven't defined it) and throws BeanInstatiationException and NoSuchMethodException.

After defining a default constructor the exceptions don't appear anymore, however my object is never initialized with the argument constructor, only the default one is called. Does Spring really require a default constructor in this case? And if yes, how can I make it use the argument constructor instead of the default one?

This is how I wire everything:

public class Servlet {

  @Autowired
  private Module module;

  (code that uses module...)
}

@Component
public class Module {

  public Module(String arg) {}
  ...
}

Bean configuration:

<beans>
  <bean id="module" class="com.client.Module">
    <constructor-arg type="java.lang.String" index="0">
    <value>Text</value>
    </constructor-arg>
  </bean>

  ...
</beans>

Stack trace:

WARNING: Could not get url for /javax/servlet/resources/j2ee_web_services_1_1.xsd
ERROR  initWebApplicationContext, Context initialization failed
[tomcat:launch] org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'module' defined in URL [...]: Instantiation of bean failed;  
nested exception is org.springframework.beans.BeanInstantiationException: Could not 
instantiate bean class [com.client.Module]: No default constructor found; nested 
exception is java.lang.NoSuchMethodException: com.client.Module.<init>()
like image 897
agerrr Avatar asked Aug 06 '13 00:08

agerrr


People also ask

Is it mandatory to have default constructor?

The compiler doesn't ever enforce the existence of a default constructor. You can have any kind of constructor as you wish. For some libraries or frameworks it might be necessary for a class to have a default constructor, but that is not enforced by the compiler.

Do we need to define constructor for field injection?

Field Injection: Consumer uses no-argument constructor. There is no valid way to set state of the object. Only option is to use Reflection to set the private fields.

Does JPA need default constructor?

Default or No-Arg Constructor. The JPA specification requires that all persistent classes have a no-arg constructor. This constructor may be public or protected.

Is default constructor mandatory in Java?

Java doesn't require a constructor when we create a class. However, it's important to know what happens under the hood when no constructors are explicitly defined. The compiler automatically provides a public no-argument constructor for any class without constructors. This is called the default constructor.


3 Answers

Spring only "requires" a default constructor if you plan on instantiating it without any arguments.

for example, if your class is like this;

public class MyClass {

  private String something; 

  public MyClass(String something) {
    this.something = something;
  }

  public void setSomething(String something) {
    this.something = something;
  }

}

and you set it up in Spring like this;

<bean id="myClass" class="foo.bar.MyClass">
  <property name="something" value="hello"/>
</bean>

you're going to get an error. the reason is that Spring instantiates your class new MyClass() then tries to set call setSomething(..).

so instead, the Spring xml should look like this;

<bean id="myClass" class="foo.bar.MyClass">
  <constructor-arg value="hello"/>
</bean>

so have a look at your com.client.Module and see how its configured in your Spring xml

like image 200
incomplete-co.de Avatar answered Nov 13 '22 18:11

incomplete-co.de


Most probably you are using component-scanning and since you define annotation @Component for class Module it tries to instantiate the bean. You do not need @Component annotation if You are using XML for bean definition.

like image 38
ikettu Avatar answered Nov 13 '22 17:11

ikettu


Just faced the same problem, i guess till now you might have solved the problem.
Below is what you could have changed your bean configuration to,

<bean id="module" class="com.client.Module">
        <constructor-arg value="Text"/>
</bean>
like image 29
DineshM Avatar answered Nov 13 '22 17:11

DineshM