Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a bean in the application class

I'm trying something so simple and yet...

So I have an Application class:

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@SpringBootApplication
@Configuration
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public Counter getCounter() {
        return new Counter(10);
    }
}

And a simple Counter class:

package hello;

public class Counter {
    private int counter = 0;

    public Counter(int c) {
        counter = c;
    }

    public int getNext() {
        return ++counter;
    }
}

And a REST controller:

package hello;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    @RequestMapping("/count")
    public ResponseEntity greeting(Counter counter) {
        return ResponseEntity.ok(counter.getNext());
    }
}

And when I send the request, I get the following exception:

java.lang.NoSuchMethodException: hello.Counter.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_131]
    at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_131]
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:102) ~[spring-beans-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:141) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:81) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:101) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:158) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:128) ~[spring-web-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.14.jar:8.5.14]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.8.RELEASE.jar:4.3.8.RELEASE]
....

It seems to me that the Bean definition is not recognized by Spring, but I'm not sure. Does anyone know what I'm missing?

like image 676
Mehran Avatar asked Nov 24 '25 07:11

Mehran


1 Answers

The problem is that you're passing the Counter as a parameter to your controller method. Method parameters are for passing information that's specific to that request (path components, query parameters, headers), and Spring handles generic POJO parameters by creating an instance of the class (Counter in this case) and setting its parameters from the HTTP request, not by using beans.

Instead, you want the counter to belong to the controller itself (not a specific request):

@RestController
public class GreetingController {

    private final Counter counter;

    public GreetingController(Counter c) {
        this.counter = c;
    }

    @RequestMapping("/count")
    public ResponseEntity greeting() {
        return ResponseEntity.ok(counter.getNext());
    }
}

Note also that it's preferable not to initialize your counter variable to zero if every available constructor is going to set the value to something else, as it's a little clearer to someone reading your code that the value is explicitly set up somewhere.

like image 118
chrylis -cautiouslyoptimistic- Avatar answered Nov 26 '25 22:11

chrylis -cautiouslyoptimistic-



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!