Rotzlucky Rotzlucky - 3 months ago 91
Java Question

How to inject Utility classes with Guice in Play 2.5.4

I'm trying to load sample data into my database with play 2.5.4
Originally I'm following the tutorial on https://www.playframework.com/documentation/2.2.x/JavaGuide1

But since it's written for Play 2.2 I'm try my best to adapt it and avoid the deprecated stuff.

Now, I'm still a little lost on the DI stuff.

What I have so far:

application.conf

play.modules.enabled += "GuiceConfiguration"


GuiceConfiguration.java

public class GuiceConfiguration extends AbstractModule{
@Override
protected void configure() {
bind(OnStartupService.class).asEagerSingleton();
}
}


OnStartupService.java

@Singleton
public class OnStartupService {

@Inject
private OnStartupService(Environment environment) {
if (environment.isDev()) {
if (Issue.find.findRowCount() == 0) {
System.out.println("Okay");
}
}
}
}


Above code works fine!

The following not:

@Singleton
public class OnStartupService {

@Inject
private OnStartupService(Environment environment) {
if (environment.isDev()) {
if (Issue.find.findRowCount() == 0) {
Ebean.saveAll((Collection<?>) Yaml.load("test-data.yml"));
}
}
}
}


Edit: fails with the following exception

play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:

1) Error injecting constructor, java.lang.RuntimeException: There is no started application
at OnStartupService.<init>(OnStartupService.java:1)
at GuiceConfiguration.configure(GuiceConfiguration.java:9) (via modules: com.google.inject.util.Modules$OverrideModule -> GuiceConfiguration)
while locating OnStartupService


So I guess I should somehow inject Ebean and Yaml. But I'm only using static methods from those classes.
Can someone help me understand how to do this and why.

c4k c4k
Answer

If you look at the code of Yaml.java, we can see that it uses the static Play.current() at line 20. That's why you get the error since there is no application started.

Furthermore, Yaml will be deprecated in 2.6 so I advise you to follow the migration guide. It explains you how to solve your problem :

  1. Add dependency to snakeyaml
  2. Create your own Yaml class
  3. Inject Application inside it

EDIT

Then inject your Yaml class, do not use the static way :

@Singleton
public class OnStartupService {

    @Inject
    private OnStartupService(Environment environment, Yaml yaml) {
        if (environment.isDev()) {
            if (Issue.find.findRowCount() == 0) {
                Ebean.saveAll((Collection<?>) yaml.load("test-data.yml"));
            }
        }
    }
}