2

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 ?

Ida Amit
  • 1,411
  • 2
  • 13
  • 27

3 Answers3

2
@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.

Ida Amit
  • 1,411
  • 2
  • 13
  • 27
2

A better way to implement qualifier is with annotations Define 2 annotations :

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Redsox {
}

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface Boston {
}

in the config file , change the following beans:

@Bean @Redsox
public Team getRedSox() {
    return new Team("RedSox");
}

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

@Bean @Scope(value="prototype",proxyMode = ScopedProxyMode.TARGET_CLASS)
public Game getGame(@Boston Team t1, @Redsox Team t2) {
    return new Game( t1, t2 );
}
Ida Amit
  • 1,411
  • 2
  • 13
  • 27
0

Another option is to define in gameController :

@Lookup
public  Game getGameBean(){
    return null;
}

The above is equivalent to context.getBean(Game.class) because you do not have application spring context. and you don't need to define proxyMode in the bean definition

Ida Amit
  • 1,411
  • 2
  • 13
  • 27