Application

In our main Application class, we can implement additional features, such as a custom Service implementation, metrics, or authorization. See the chapter on Authorization and Security for further information.

public class MyApplication extends Application<Configuration> {
  private MyServiceInjector serviceInjector;
  
  public MyApplication() {
    // register the rest classes
    register("de.whitefrog.frogr.example.rest");
    // register repositories and models
    serviceInjector().service().register("de.whitefrog.frogr.example");
  }

  // override to pass our own ServiceInjector implementation
  @Override
  public ServiceInjector serviceInjector() {
    if(serviceInjector == null) {
      serviceInjector = new MyServiceInjector();
    }
    return serviceInjector;
  }

  @Override
  public void run(Configuration configuration, Environment environment) throws Exception {
    super.run(configuration, environment);

    // bind the custom ServiceInjector to our Service implementation, described below
    environment.jersey().register(new AbstractBinder() {
      @Override
      protected void configure() {
        bindFactory(serviceInjector()).to(MyService.class);
      }
    });

    // register metrics
    environment.jersey().register(new InstrumentedResourceMethodApplicationListener(RestService.metrics));

    // add a console reporter for the metrics
    final ConsoleReporter reporter = ConsoleReporter.forRegistry(RestService.metrics)
      .convertRatesTo(TimeUnit.SECONDS)
      .convertDurationsTo(TimeUnit.MILLISECONDS)
      .build();
    // report every 30 minutes
    reporter.start(30, TimeUnit.MINUTES);

    // add a logger reporter for the metrics
    final Slf4jReporter slf4j = Slf4jReporter.forRegistry(RestService.metrics)
      .outputTo(LoggerFactory.getLogger("com.example.metrics"))
      .convertRatesTo(TimeUnit.SECONDS)
      .convertDurationsTo(TimeUnit.MILLISECONDS)
      .build();
    // report every 30 minutes
    slf4j.start(30, TimeUnit.MINUTES);
  }

  @Override
  public String getName() {
    return "example-rest";
  }

  public static void main(String[] args) throws Exception {
    new MyApplication().run("server", "config/example.yml");
  }
}

Service Injector

We can also write our own ServiceInjector, in case we want to override the base Service.

public class MyServiceInjector extends ServiceInjector {
  private MyService service;

  public MyServiceInjector() {
    service = new MyService();
  }

  @Override
  public Service service() {
    return service;
  }

  @Override
  public Service provide() {
    if(!service.isConnected()) service.connect();
    return service;
  }

  @Override
  public void dispose(de.whitefrog.frogr.Service service) {
    service.shutdown();
  }
}

In that case, Service is our own implementation and should extend de.whitefrog.frogr.Service.

Service

For instance if we want to provide a common configuration accessible from any Repository or Service:

public class MyService extends Service {
  private static final Logger logger = LoggerFactory.getLogger(MyService.class);
  private static final String appConfig = "config/myapp.properties";

  private Configuration config;

  @Override
  public void connect() {
    try {
      config = new PropertiesConfiguration(appConfig);
      super.connect();
    } catch(ConfigurationException e) {
      logger.error(e.getMessage(), e);
      throw new RuntimeException(e);
    }
  }

  public Configuration config() { return config; }
}