Introduction à Bootique

Introduction à Bootique

1. Vue d'ensemble

Bootique est un framework JVMcontainer-less open source très léger visant à créer des micro-services évolutifs de nouvelle génération. Il est construit sur le serveur Jetty intégré et prend entièrement en charge les gestionnairesREST avecjax-rs.

Dans cet article, nous allons montrer comment créer une application Web simple à l'aide deBootique.

2. Dépendances Maven

Commençons à utiliserBootique en ajoutant la dépendance suivante dans lespom.xml:


    io.bootique.jersey
    bootique-jersey
    compile


    io.bootique
    bootique-test
    test

Cependant,Bootique nécessite également de déclarer quelques importations deBOM (“Bill of Material”). C'est pourquoi la section<dependencyManagement> suivante doit être ajoutée dans lespom.xml:


    
        
            io.bootique.bom
            bootique-bom
            0.23
            pom
            import
        
    

La dernière version deBootique est disponible enCentral Maven Repository.

Pour créer un fichier jar exécutable,Bootique s'appuie surmaven-shade-plugin. C’est pourquoi nous devons également ajouter la configuration ci-dessous:


    
        
            org.apache.maven.plugins
            maven-shade-plugin
        
    

3. Démarrer une application

Le moyen le plus simple de démarrer une applicationBootique est d'appeler la méthodeexec() deBootique à partir de la méthode principale:

public class App {
    public static void main(String[] args) {
        Bootique.app(args)
          .autoLoadModules()
          .exec();
    }
}

However, this won’t start the embedded server. Une fois, le code ci-dessus est exécuté, le journal suivant doit être affiché:

NAME
      com.example.bootique.App

OPTIONS
      -c yaml_location, --config=yaml_location
           Specifies YAML config location, which can be a file path
           or a URL.

      -h, --help
           Prints this message.

      -H, --help-config
           Prints information about application modules and their
           configuration options.

      -s, --server
           Starts Jetty server.

Ce ne sont rien d'autre que les arguments de programme disponibles pré-fournis avecBootique.

Les noms sont explicites; par conséquent, pour démarrer le serveur, nous devons passer l'argument–s ou–server et le serveur sera opérationnel sur lesdefault port 8080.

4. Modules

Les applicationsBootique sont faites avec des collections de «modules». Dans le termeBootique“A module is a Java library that contains some code”, cela signifie qu'il traite chaque service comme un module. Il utiliseGoogle Guice pour l'injection de dépendances.

Pour voir comment cela fonctionne, créons une interface:

public interface HelloService {
    boolean save();
}

Maintenant, nous devons créer une implémentation:

public class HelloServiceImpl implements HelloService {

    @Override
    public boolean save() {
        return true;
    }
}

Il existe deux manières de charger le module. La première consiste à utiliser l'interfaceModule deGuice et l'autre à utiliserBQModuleProvider deBootique, également connu sous le nom deauto-loading.

4.1. Module Guice

Ici, nous pouvons utiliser l'interfaceModule deGuice pour lier des instances:

public class ModuleBinder implements Module {

    @Override
    public void configure(Binder binder) {
        binder
          .bind(HelloService.class)
          .to(HelloServiceImpl.class);
    }
}

Une fois le module défini, nous devons mapper ce module personnalisé à l'instanceBootique:

Bootique
  .app(args)
    .module(module)
    .module(ModuleBinder.class)
  .autoLoadModules()
  .exec();

4.2. BQModuleProvider (chargement automatique)

Ici, tout ce que nous avons à faire est de définir le module-binder créé précédemment avecBQModuleProvider:

public class ModuleProvider implements BQModuleProvider {

    @Override
    public Module module() {
        return new ModuleBinder();
    }
}

L’avantage de cette technique est que nous n’avons pas besoin de mapper les informations de module avec l’instanceBootique.

Nous avons juste besoin de créer un fichier dans/resources/META-INF/services/io.bootique.BQModuleProvider et d'écrire le nom complet desModuleProvider avec le nom du package etBootique s'occupera du reste:

com.example.bootique.module.ModuleProvider

Maintenant, nous pouvons utiliser l'annotation@Inject pour utiliser les instances de service au moment de l'exécution:

@Inject
HelloService helloService;

Une chose importante à noter ici est que puisque nous utilisons le mécanisme DI deBootique, nous n'avons pas besoin d'utiliser l'annotationGuice @ImplementedBy pour lier les instances de service.

5. Point de terminaison REST

Il est simple de créer des points de terminaison REST à l’aide de l’API JAX-RS:

@Path("/")
public class IndexController {

    @GET
    public String index() {
        return "Hello, example!";
    }

    @POST
    public String save() {
        return "Data Saved!";
    }
}

Pour mapper les points de terminaison dans l'instance deJersey deBootique, nous devons définir unJerseyModule:

Module module = binder -> JerseyModule
  .extend(binder)
  .addResource(IndexController.class);

6. Configuration

Nous pouvons fournir des informations de configuration intégrées ou personnalisées dans un fichier de propriétés basé sur YAML.

Par exemple, si nous souhaitons démarrer l’application sur un port personnalisé et ajouter un contexte URI par défaut, «Bonjour», nous pouvons utiliser la configuration YAML suivante:

jetty:
    context: /hello
    connector:
        port: 10001

Maintenant, lors du démarrage de l'application, nous devons fournir l'emplacement de ce fichier dans le paramètre de configuration:

--config=/home/example/bootique/config.yml

7. Enregistrement

LeBootique prêt à l'emploi est livré avec un modulebootique-logback. Pour utiliser ce module, nous devons ajouter la dépendance suivante dans lespom.xml:


    io.bootique.logback
    bootique-logback

Ce module est livré avec une interfaceBootLogger avec nous pouvons remplacer pour implémenter la journalisation personnalisée:

Bootique.app(args)
  .module(module)
  .module(ModuleBinder.class)
    .bootLogger( new BootLogger() {
      @Override
      public void trace( Supplier args ) {
          // ...
      }
      @Override
      public void stdout( String args ) {
          // ...
      }
      @Override
      public void stderr( String args, Throwable thw ) {
          // ...
      }
      @Override
      public void stderr( String args ) {
          // ...
      }
}).autoLoadModules().exec();

De plus, nous pouvons définir les informations de configuration de journalisation dans le fichierconfig.yaml:

log:
    level: warn
    appenders:
    - type: file
      logFormat: '%c{20}: %m%n'
      file: /path/to/logging/dir/logger.log

8. Essai

Pour les tests,Bootique est fourni avec le modulebootique-test. Il y a deux façons de tester une applicationBootique.

La première approche est l'approche‘foreground' qui fait que tous les cas de test s'exécutent sur le thread de test principal.

L'autre est l'approche‘background' qui fait exécuter les cas de test sur un pool de threads isolé.

L'environnement «de premier plan» peut être initialisé à l'aide deBQTestFactory:

@Rule
public BQTestFactory bqTestFactory = new BQTestFactory();

L'environnement «d'arrière-plan» peut être initialisé à l'aide deBQDaemonTestFactory:

@Rule
public BQDaemonTestFactory bqDaemonTestFactory = new BQDaemonTestFactory();

Une fois que l'usine d'environnement est prête, nous pouvons écrire des cas de test simples pour tester les services:

@Test
public void givenService_expectBoolen() {
    BQRuntime runtime = bqTestFactory
      .app("--server").autoLoadModules()
      .createRuntime();
    HelloService service = runtime.getInstance( HelloService.class );

    assertEquals( true, service.save() );
}

9. Conclusion

Dans cet article, nous avons montré comment créer une application à l'aide des modules principaux deBootique. Il existe plusieurs autres modulesBootique disponibles commebootique-jooq,bootique-kotlin,bootique-job, etc. La liste complète des modules disponibles est disponiblehere.

Comme toujours, le code source complet est disponibleover on GitHub.