1

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!

mariusz
  • 157
  • 2
  • 16
  • Your Player constructor calls parameters do not match those of the actual constructors. pass the parameters the constructor requires, and you'll be just fine – Stultuske Jun 05 '18 at 08:36
  • I previously tried to add constructors Player(String name), Player(String name, boolean isDealer), but it didn't help. – mariusz Jun 05 '18 at 08:43

1 Answers1

1

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)
);
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • I received another error that the class need only one constructor with `@Inject` – mariusz Jun 05 '18 at 09:48
  • @mariusz Sorry, I messed up my annotations. I should have used `@AssistedInject` instead of `@Inject`. I fixed my code accordingly. – Olivier Grégoire Jun 05 '18 at 09:53
  • Don't worry. Unfortunately your solution doesn't work. Still got the same error this time for BlackjackPlayer class. – mariusz Jun 05 '18 at 10:03
  • @mariusz This works for me. Make sure you totally clean up the previous classes as you need to write it exactly as above. – Olivier Grégoire Jun 05 '18 at 10:33
  • I think it's almost the same. Anyway, if you want you can take a look at the whole code: https://github.com/mmaciula/Blackjack/tree/master/src/main/java/com/github/blackjack – mariusz Jun 05 '18 at 10:50
  • @mariusz In your code repository, you do not have the `@Assisted` annotations on the parameters of the `BlackjackPlayer` constructors. Look exactly at how I wrote the constructors in `BlackjackPlayer`: some parameters have `@Assisted` before them: you must make sure the parameters that are in the `PlayerFactory` are annotated with `@Assisted` in `BlackjackPlayer`. – Olivier Grégoire Jun 05 '18 at 10:53
  • But the `@Assisted` annotations caused `No implementation for com.github.blackjack.model.Player annotated with @com.google.inject.assistedinject.Assisted(value=dealer) was bound.` – mariusz Jun 05 '18 at 10:58
  • You're trying to get too big. Try smaller. Each module one at a time. Your player factory is working fine. It's your game factory that has issues now. So to fix them: 1. Annotate `@AssistedInject` to `Game` constructor. 2. Method of `GameFactory`should be: `Game createGame(@Assisted("player") Player player, @Assisted("dealer") Player dealer, @Assisted Deck blackcjackDeck);` – Olivier Grégoire Jun 05 '18 at 11:16
  • Oh yes, and keep the annotations of my previous comment on `BlackjackPlayer`'s constructors. – Olivier Grégoire Jun 05 '18 at 11:17
  • Also, make sure to read the WHOLE exception! In Guice, the exception text is VERY precise and clear about where your issue most likely is. In this case, it was always right – Olivier Grégoire Jun 05 '18 at 11:19