30
votes

I am working with Spring MVC controller project. Below is my Controller and I have a constructor declared which I am specifically using for testing purpose.

@Controller
public class TestController {

    private static KeeperClient testClient = null;

    static {

    // some code here

    }

    /**
     * Added specifically for unit testing purpose.
     * 
     * @param testClient
     */
    public TestController(KeeperClient testClient) {
        TestController.testClient = testClient;
    }

    // some method here

}

Whenever I am starting the server, I am getting below exception -

No default constructor found; nested exception is java.lang.NoSuchMethodException:

But if I remove TestController constructor then it works fine without any problem. What wrong I am doing here?

But if I add this default constructor then it starts working fine -

    public TestController() {

    }
5
You need to add a no-args constructor to have @Controller work. public TestController() {} .When you remove your custom constructor, the default constructor (no args) becomes available, but in the presence of a constructor with args, a no-args constructor is not implicitly present. - TJ-
@TJ yes it works fine after adding that but before I didn't have any default constructor, just now I added the constructor with parameters then it started failing. - john
Add another constructor with no-args. You can have multiple constructors. Polymorphism. A default no-args constructor is implicit in the absence of explicitly defined constructors. - TJ-
This is simple Java: if you do not have any constructors, then a default no-argument constructor will be created for you. Once you created your own constructor, it's your responsibility to create a default one (if needed). Since Java Bean requires a default constructor you get your error. - PM 77-1

5 Answers

47
votes

Spring cannot instantiate your TestController because its only constructor requires a parameter. You can add a no-arg constructor or you add @Autowired annotation to the constructor:

@Autowired
public TestController(KeeperClient testClient) {
    TestController.testClient = testClient;
}

In this case, you are explicitly telling Spring to search the application context for a KeeperClient bean and inject it when instantiating the TestControlller.

25
votes

You must have to define no-args or default constructor if you are creating your own constructor.

You can read why default or no argument constructor is required.

why-default-or-no-argument-constructor-java-class.html

12
votes

In my case, spring threw this because i forgot to make an inner class static.

When you found that it doesnt help even adding a no-arg constructor, please check your modifier.

7
votes

In my case I forgot to add @RequestBody annotation to the method argument:

public TestController(@RequestBody KeeperClient testClient) {
        TestController.testClient = testClient;
    }
0
votes

If your environment is using both Guice and Spring and using the constructor @Inject, for example, with Play Framework, you will also run into this issue if you have mistakenly auto-completed the import with an incorrect choice of:

import com.google.inject.Inject;

Then you get the same missing default constructor error even though the rest of your source with @Inject looks exactly the same way as other working components in your project and compile without an error.

Correct that with:

import javax.inject.Inject;

Do not write a default constructor with construction time injection.