Search code examples
springscopeprototypeconfigqualifiers

scope prototype not working


I have the following configuration :

@Configuration
public class GameConfig {
    @Bean(name = "redsox")
    public Team getRedSox() {
        return new Team("RedSox");
    }

    @Bean(name = "boston")
    public Team getBoston() {
        return new Team("Boston");
    }

    @Bean @Scope(value="prototype") 
    public Game getGame(@Qualifier("boston") Team t1, @Qualifier("redsox") Team t2) {
        return new Game( t1, t2 );
    }

    @Bean
    GameController gameController(Game g) {
        return new GameController(g);
    }
}

@RestController
@RequestMapping("game")
public class GameController {

    Game game;

    public GameController(Game game) {
        this.game = game;
    }

    @RequestMapping(path = "play", method = RequestMethod.GET)
    public Team play() {
        return game.play();
    }

    @RequestMapping(path = "setHomeTeam", method = RequestMethod.POST)
    public void setHomeTeam(@RequestBody Team t) {
        game.setHomeTeam(t);
    }
}

public class Game {

    private Team homeTeam;
    private Team awayTeam;

    public Game (Team homeTeam, Team awayTeam){
        this.homeTeam = homeTeam;
        this.awayTeam = awayTeam;
    }

    public Team play (){
        Random randomGenerator = new Random();
        // Generate random integers in the range 0..1
        int randomInt = randomGenerator.nextInt(2);
        if (randomInt == 0 )
            return this.homeTeam;
        else
            return this.awayTeam;
    }

    public void setHomeTeam (Team t){
        this.homeTeam = t;
    }

    public void setAwayTeam (Team t){
        this.awayTeam = t;
    }
}

@Getter  @NoArgsConstructor @AllArgsConstructor
public class Team {
    private String name;
}

I would like the Game not to be singletone. but when I call POST request http://localhost:8080/game/setHomeTeam and then I call GET request http://localhost:8080/game/play it remembers the setHomeTeam.

The only solution I have found was configure gameController in another way:

@Bean  
@Scope(value="prototype")
GameController gameController(
    @Qualifier("boston") Team t1, 
    @Qualifier("redsox") Team t2
) {
    return new GameController(new Game(t1, t2));
}

but this creates the controller + Game as non Singletone. I would like to have only the Game non-Singletone. Is there any better/ efficient way ?


Solution

  • @Bean 
    @Scope(value="request",proxyMode = ScopedProxyMode.TARGET_CLASS) 
    public Game getGame(@Qualifier("boston") Team t1, @Qualifier("redsox") Team t2) {
        return new Game( t1, t2 );
    }
    

    If we had interface we would use : ScopedProxyMode.INTERFACES

    Look at http://www.baeldung.com/spring-bean-scopes section "4.1. Request Scope" Annotation @RequestScope is equivalent to

    @Scope(value="request",proxyMode = ScopedProxyMode.TARGET_CLASS)
    

    Or in short @RequestScope.

    If the class (Game) is final this solution is not available, since a proxy calss is created.