14

I have the following Spring controller:

package hello;

import java.util.concurrent.atomic.AtomicLong;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    private final AtomicLong counter = new AtomicLong();

    @RequestMapping("/test")
    public String test() {
        long val = counter.incrementAndGet();
        return String.valueOf(val);
    }
}

Each time I access the REST API, it returns an incremented value. I am just learning Java and I am wondering why it does not always return 1 as a new instance of AtomicLong must have been created each time the request comes.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
Babu James
  • 2,740
  • 4
  • 33
  • 50

2 Answers2

17

No, the TestController bean is actually a singleton. @RestController annotation declares a Spring @Component whose scope is by default SINGLETON. This is documented in the @Scope annotation:

Defaults to an empty string ("") which implies SCOPE_SINGLETON.

This means that it will be the same instance of TestController that will handle every requests. Since counter is an instance variable, it will be same for every request.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
  • Is it a good practice to keep it singleton or set the scope to so-called `prototype`? – Babu James Oct 15 '15 at 07:32
  • 1
    @BabuJames For a `Controller`, I would say it is better to keep it a singleton. `Controller`s are not typically stateful so it makes sense to make them singleton. – Tunaki Oct 15 '15 at 07:34
4

A @RestController is not created for each request, it remains the same for every request. So your counter keeps its value and is incremented each time.

Gaël J
  • 11,274
  • 4
  • 17
  • 32