3

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?

Ikaso
  • 2,268
  • 19
  • 26
  • 1
    Have you tried with a Provider ? – Benoît Oct 21 '15 at 08:43
  • If I get it right provider does not work in my case. Can you elaborate? – Ikaso Oct 21 '15 at 09:05
  • I was thinking of things like in http://stackoverflow.com/a/15493413/4462333 If it doesn't workout, I might have misunderstood something in your question. Could you edit it to add more code/information related to your problem ? – Benoît Oct 21 '15 at 09:23
  • My Context is not related to web development. Think about it as a hash table that will grow when my application is running. I will update my question to clarify. – Ikaso Oct 21 '15 at 10:09
  • What should happen when Foo is created but Bar does not exist at that point? – Michael Lloyd Lee mlk Oct 21 '15 at 10:24
  • @mlk - imagine that I run my program for some time. Some component will add "bar" to the context. Only after that I will run: injector.getInstance() – Ikaso Oct 21 '15 at 10:29
  • In that case a Provider where you only call "Provider.get" in " `doSomethingWithBar`" would make the most sense to me. Else you will have to do some funky wrapping. – Michael Lloyd Lee mlk Oct 21 '15 at 10:34
  • @mlk - but a provider will do if I had only 1 class like Foo. Imagine I have many with this requirement. – Ikaso Oct 21 '15 at 10:36
  • Provide us with your real use-case: your question is way too broad (lots of "if", "imagine", etc.) and unclear at this moment (`Context` is both a concrete class and an annotation in yout question). – Olivier Grégoire Oct 21 '15 at 11:25
  • @OlivierGrégoire - I added a concrete example. – Ikaso Oct 21 '15 at 12:17

1 Answers1

3

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 = ...;
  }
}
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137