org.nmdp.service.epitope.dropwizard.EpitopeServiceApplication.java Source code

Java tutorial

Introduction

Here is the source code for org.nmdp.service.epitope.dropwizard.EpitopeServiceApplication.java

Source

/*
    
epitope-service  T-cell epitope group matching service for HLA-DPB1 locus.
Copyright (c) 2014-2015 National Marrow Donor Program (NMDP)
    
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 3 of the License, or (at
your option) any later version.
    
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
License for more details.
    
You should have received a copy of the GNU Lesser General Public License
along with this library;  if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA.
    
> http://www.gnu.org/licenses/lgpl.html
    
*/

package org.nmdp.service.epitope.dropwizard;

import static java.util.concurrent.TimeUnit.MILLISECONDS;

import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.log4j.Logger;
import org.nmdp.service.common.domain.ConfigurationModule;
import org.nmdp.service.common.dropwizard.CommonServiceApplication;
import org.nmdp.service.epitope.guice.ConfigurationBindings;
import org.nmdp.service.epitope.guice.ConfigurationBindings.RefreshMillis;
import org.nmdp.service.epitope.guice.LocalServiceModule;
import org.nmdp.service.epitope.resource.impl.AlleleResource;
import org.nmdp.service.epitope.resource.impl.GroupResource;
import org.nmdp.service.epitope.resource.impl.MatchResource;
import org.nmdp.service.epitope.resource.impl.ResourceModule;
import org.nmdp.service.epitope.service.EpitopeService;
import org.nmdp.service.epitope.service.FrequencyService;
import org.nmdp.service.epitope.task.AlleleCodeInitializer;
import org.nmdp.service.epitope.task.AlleleInitializer;
import org.nmdp.service.epitope.task.GGroupInitializer;
import org.nmdp.service.epitope.task.ImmuneGroupInitializer;
import org.skife.jdbi.v2.DBI;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.wordnik.swagger.config.SwaggerConfig;
import com.wordnik.swagger.model.ApiInfo;

import io.dropwizard.db.DataSourceFactory;
import io.dropwizard.flyway.FlywayBundle;
import io.dropwizard.flyway.FlywayFactory;
import io.dropwizard.jdbi.DBIFactory;
import io.dropwizard.jdbi.bundles.DBIExceptionsBundle;
import io.dropwizard.lifecycle.Managed;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;

/**
 * Dropwizard main application wrapper
 */
public class EpitopeServiceApplication extends CommonServiceApplication<EpitopeServiceConfiguration> {

    Logger log = Logger.getLogger(getClass());

    /**
     * Application main method
     */
    public static void main(String[] args) throws Exception {
        new EpitopeServiceApplication().run(args);
    }

    @Override
    public String getName() {
        return "EpitopeService";
    }

    /**
     * Dropwizard application initialization
     */
    @Override
    public void initializeService(Bootstrap<EpitopeServiceConfiguration> bootstrap) {
        bootstrap.addBundle(new FlywayMigrationBundle<EpitopeServiceConfiguration>() {
            @Override
            public DataSourceFactory getDataSourceFactory(EpitopeServiceConfiguration configuration) {
                return configuration.getDataSourceFactory();
            }
        });
        bootstrap.addBundle(new DBIExceptionsBundle());
        bootstrap.addBundle(new FlywayBundle<EpitopeServiceConfiguration>() {
            @Override
            public DataSourceFactory getDataSourceFactory(EpitopeServiceConfiguration configuration) {
                return configuration.getDataSourceFactory();
            }

            @Override
            public FlywayFactory getFlywayFactory(EpitopeServiceConfiguration configuration) {
                return configuration.getFlywayFactory();
            }
        });
    }

    /**
     * Dropwizard service runner.  Application resources are registered here.
     */
    @Override
    public void runService(final EpitopeServiceConfiguration configuration, final Environment environment)
            throws Exception {

        Injector injector = Guice.createInjector(
                new ConfigurationModule(ConfigurationBindings.class, configuration), new LocalServiceModule(),
                new ResourceModule(), new AbstractModule() {
                    @Override
                    protected void configure() {
                        DBI dbi = new DBIFactory().build(environment, configuration.getDataSourceFactory(),
                                "sqlite");
                        bind(DBI.class).toInstance(dbi);
                    }
                });

        environment.getObjectMapper().enable(SerializationFeature.INDENT_OUTPUT)
                .setSerializationInclusion(Include.NON_NULL)
                .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

        // todo: generalize dependency graph (latches?)
        //Runnable initializers = serial(
        //       parallel(
        //          () -> injector.getInstance(GGroupInitializer.class).loadGGroups(),
        //          () -> injector.getInstance(AlleleCodeInitializer.class).loadAlleleCodes(),
        //          serial(
        //             () -> injector.getInstance(AlleleInitializer.class).loadAlleles()),
        //             () -> injector.getInstance(ImgtImmuneGroupInitializer.class).loadAlleleScores()),
        //       parallel(
        //          () -> injector.getInstance(EpitopeService.class).buildMaps(),
        //          () -> injector.getInstance(FrequencyService.class).buildFrequencyMap(),
        //          () -> injector.getInstance(DbiAlleleCodeResolver.class).buildAlleleCodeMap()));

        Runnable initializers = serial(() -> injector.getInstance(GGroupInitializer.class).loadGGroups(),
                () -> injector.getInstance(AlleleCodeInitializer.class).loadAlleleCodes(),
                () -> injector.getInstance(AlleleInitializer.class).loadAlleles(),
                () -> injector.getInstance(ImmuneGroupInitializer.class).loadImmuneGroups(),
                () -> injector.getInstance(EpitopeService.class).buildAlleleGroupMaps(),
                () -> injector.getInstance(FrequencyService.class).buildFrequencyMap());
        //                 () -> injector.getInstance(DbiAlleleCodeResolver.class).buildAlleleCodeMap());

        long refreshMillis = injector.getInstance(Key.get(Long.class, RefreshMillis.class));

        environment.lifecycle().manage(new Managed() {
            ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, r -> {
                Thread t = new Thread(r, "InitializerThread");
                t.setDaemon(true);
                return t;
            });

            @Override
            public void stop() throws Exception {
                scheduler.shutdownNow();
            }

            @Override
            public void start() throws Exception {
                Future<?> init = scheduler.submit(initializers);
                init.get();
                scheduler.scheduleAtFixedRate(initializers, refreshMillis, refreshMillis, MILLISECONDS);
            }
        });

        final AlleleResource alleleResource = injector.getInstance(AlleleResource.class);
        environment.jersey().register(alleleResource);

        final GroupResource groupResource = injector.getInstance(GroupResource.class);
        environment.jersey().register(groupResource);

        final MatchResource matchResource = injector.getInstance(MatchResource.class);
        environment.jersey().register(matchResource);

        environment.jersey().register(new org.nmdp.service.epitope.resource.impl.ExceptionMapper());

        // eriktodo: multibinder for health checks
        final GlClientHealthCheck glClientHealthCheck = injector.getInstance(GlClientHealthCheck.class);
        environment.healthChecks().register("glClient", glClientHealthCheck);
    }
    //   Managed() {
    //    @Override public void stop() throws Exception {}
    //    @Override public void start() throws Exception {
    //    }

    public Runnable serial(Runnable... hooks) {
        return () -> {
            Arrays.stream(hooks).forEachOrdered(hook -> {
                try {
                    log.debug("running hook (in serial): " + hook.getClass().getSimpleName());
                    hook.run();
                } catch (Exception e) {
                    log.error("hook failed", e);
                }
            });
        };
    }

    public Runnable parallel(Runnable... hooks) {
        return () -> {
            Arrays.stream(hooks).parallel().forEach(hook -> {
                try {
                    log.debug("running hook (in parallel): " + hook.getClass().getSimpleName());
                    hook.run();
                } catch (Exception e) {
                    log.error("hook failed", e);
                }
            });
        };
    }

    @Override
    public void configureSwagger(SwaggerConfig config) {
        config.setApiVersion("1.0");
        config.setApiInfo(new ApiInfo("Epitope Service",
                "This service reports on alleles and their associated immunogenicity groups and provides matching functions.",
                null, // terms of service url 
                "epearson@nmdp.org", // contact
                null, // license
                null)); // license url
    }
}