Ikaso
Ikaso

Reputation: 2268

Using Guice to inject values that are generated at runtime

I have a Context class that is a key value pair that is populated gradually at runtime.

I would like to create instances of objects that require some values from the context.

For example:

public interface Task
{
    void execute();
}

public interface UiService
{
    void moveToHomePage();
}

public class UiServiceImpl implements UiService
{
    public UiService(@ContexParam("username") String username, @ContexParam("username") String password)
    {
        login(username, password);
    }

    public void navigateToHomePage() {}

    private void login(String username, String password) 
    {
        //do login
    }
}

public class GetUserDetailsTask implements Task
{
    private ContextService context;

    @Inject
    public GetUserDetailsTask(ContextService context)
    {
        this.context = context;
    }

    public void execute()
    {
        Console c = System.console();
        String username = c.readLine("Please enter your username: ");
        String password = c.readLine("Please enter your password: ");
        context.add("username", username);
        context.add("password", password);
    }
}

public class UseUiServiceTask implements Task
{
    private UiService ui;

    @Inject
    public UseUiServiceTask(UiService uiService)

    public void execute()
    {
        ui.moveToHomePage();
    }
}

I want to be able to create an instance of UseUiServiceTask using Guice. How do I achieve that?

Upvotes: 3

Views: 510

Answers (1)

Olivier Grégoire
Olivier Grégoire

Reputation: 35477

Your data are just that: data. Don't inject data unless it's defined before you get your modules and it's constant for the rest of the application.

public static void main(String[] args) {
  Console c = System.console();
  String username = c.readLine("Please enter your username: ");
  String password = c.readLine("Please enter your password: ");

  Guice.createInjector(new LoginModule(username, password));
}

If you want your data to be retrieved after the injection has started, you should not try to inject it at all. What you should do then is injecting your ContextService everywhere you need it, and/or call callbacks, but I prefer callbacks for not having to maintain the data centrally.

public class LoginRequestor {
  String username, password;
  public void requestCredentials() {
    Console c = System.console();
    username = c.readLine("Please enter your username: ");
    password = c.readLine("Please enter your password: ");
  }
}

public class UiServiceImpl implements UiService {
  @Inject LoginRequestor login;
  boolean loggedIn;

  public void navigateToHomePage() {
    checkLoggedIn();
  }
  private void checkLoggedIn() {
    if (loggedIn) {
      return;
    }
    login.requestCredentials();
    String username = login.getUsername();
    String password = login.getPassword();
    // Do login
    loggedIn = ...;
  }
}

Upvotes: 3

Related Questions