Search code examples
javaguiceassisted-inject

Guice AssistedInject can not find matching constructor


I just started learning Guice, but I've already encountered a problem. I have an interface PlayerFactory with one implementation BlackjackPlayer

PlayerFactory.java

public interface PlayerFactory {
    Player createPlayer(String name);
    Player createPlayer(String name, boolean isDealer);
}

BlackjackPlayer.java

public class BlackjackPlayer implements PlayerFactory {
    private PointsCalculator pointsCalculator;

    public BlackjackPlayer(){
        pointsCalculator = new BlackjackPointsCalculator();
    }

    @Override
    public Player createPlayer(String name) {
        return new Player(pointsCalculator, name);
    }

    @Override
    public Player createPlayer(String name, boolean isDealer) {
        return new Player(pointsCalculator, name, isDealer);
    }
}

Player.class

public class Player{
    private PointsCalculator pointsCalculator;
    private List<Card> cardsInHand;
    private Integer points;
    private String name;
    private boolean isDealer;
    private boolean endedTurn;

    @AssistedInject
    public Player(PointsCalculator blackjackPointsCalculator, String name){
        pointsCalculator = blackjackPointsCalculator;
        cardsInHand = new ArrayList<>();
        points = 0;
        this.name = name;
        isDealer = false;
        endedTurn = false;
    }

    @AssistedInject
    public Player(PointsCalculator blackjackPointsCalculator, String name, boolean isDealer){
        pointsCalculator = blackjackPointsCalculator;
        cardsInHand = new ArrayList<>();
        points = 0;
        this.name = name;
        this.isDealer = isDealer;
        endedTurn = false;
    }

    public void addCardToHand(Card card) {
        cardsInHand.add(card);
        updatePoints();
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Player)) return false;
        Player player = (Player) o;
        return getPoints() == player.getPoints() &&
            isDealer() == player.isDealer() &&
            isEndedTurn() == player.isEndedTurn() &&
            Objects.equals(pointsCalculator, player.pointsCalculator) &&
            Objects.equals(getCardsInHand(), player.getCardsInHand()) &&
            Objects.equals(getName(), player.getName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(pointsCalculator, getCardsInHand(), getPoints(), getName(), isDealer(), isEndedTurn());
    }

    public void updatePoints() {
        points = pointsCalculator.calculatePoints(cardsInHand);
    }

    public List<Card> getCardsInHand(){
        return cardsInHand;
    }

    public Integer getPoints(){
        return points;
    }

    public String getName(){
        return name;
    }

    public boolean isDealer() {
        return isDealer;
    }

    public boolean isEndedTurn() {
        return endedTurn;
    }

    public void setName(String name){
        this.name = name;
    }

    public void setDealer(boolean isDealer){
        this.isDealer = isDealer;
    }

    public void setEndedTurn(boolean endedTurn){
        this.endedTurn = endedTurn;
    }
}

I want to use Guice assisted inject to create Player. Previously I did it as follows:

install(new FactoryModuleBuilder().build(PlayerFactory.class));

which I know is wrong way, because I receive error message:

1) com.github.blackjack.model.Player has @AssistedInject constructors, but none of them match the parameters in method com.github.blackjack.factory.PlayerFactory.createPlayer().  Unable to create AssistedInject factory.
while locating com.github.blackjack.model.Player
at com.github.blackjack.factory.PlayerFactory.createPlayer(PlayerFactory.java:1)

2) com.github.blackjack.model.Player has @AssistedInject constructors, but none of them match the parameters in method com.github.blackjack.factory.PlayerFactory.createPlayer().  Unable to create AssistedInject factory.
while locating com.github.blackjack.model.Player
at com.github.blackjack.factory.PlayerFactory.createPlayer(PlayerFactory.java:1)

I tried to add constructors Player(String name), Player(String name, boolean isDealer) but it didn't help. Does someone know what should I do to fix the problem?

Thanks in advance!


Solution

  • You need to use the @Assisted annotation on the injectee parameters:

    PlayerFactory.java

    public interface PlayerFactory {
      Player createPlayer(String name);
      Player createPlayer(String name, boolean isDealer);
    }
    

    BlackjackPlayer.java (Change it from a factory to the actual player)

    public class BlackjackPlayer implements Player {
      private final PointCalculator pointsCalculator;
      private final String name;
      private final boolean isDealer;
      @AssistedInject BlackjackPlayer(PointCalculator pointsCalculator, @Assisted String name) {
        this.pointsCalculator = pointsCalculator;
        this.name = name;
        this.isDealer = false;
      }
      @AssistedInject BlackjackPlayer(PointCalculator pointsCalculator, @Assisted String name, @Assisted boolean isDealer) {
        this.pointsCalculator = pointsCalculator;
        this.name = name;
        this.isDealer = isDealer;
      }
    }
    

    And use the module as the following:

    install(new FactoryModuleBuilder()
     .implement(Player.class, BlackjackPlayer.class)
     .build(PlayerFactory.class)
    );