Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Bootique: A Minimally Opinionated Platform for Modern Java Apps

DZone's Guide to

Bootique: A Minimally Opinionated Platform for Modern Java Apps

Here's a look at Bootique, a platform built on the prior art of container-less app launchers. It allows you to write Java apps that look like commands and are made of modules.

· Java Zone
Free Resource

Build vs Buy a Data Quality Solution: Which is Best for You? Gain insights on a hybrid approach. Download white paper now!

We created Bootique for developers who want to reclaim their main() method and liberate their apps from the Java container. Bootique is a great fit for microservices as well as traditional larger multi-functional apps. Both kinds will look like simple UNIX commands at the end.

Bootique core provides just a few simple services: processing command line, reading application config YAML, and dispatching control to a Command. There are a few built-in commands, so even an app that doesn’t have much code and does not import any modules can be executed. E.g. try running this one-liner:

public class Application {
   public static void main(String[] args) {
      Bootique.app(args).run();
   }
}

It will print the following:

NAME
      my.jar

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

      --help
           Prints this message.

Note that I omitted dependencies and directions for building a runnable .jar. The Getting Started article in the Bootique docs provides step-by-step instructions for a typical app.

Hello, World!

Now let's write our own command, pretending it does something useful:

public class HelloCommand implements Command {
   @Override
   public CommandOutcome run(Cli cli) {
      System.out.println("Hello, world!");
      return CommandOutcome.succeeded();
   }
}

How do you add this command to Bootique? A Bootique is composed of Guice Modules, so let's turn our app into a Module and add it to Bootique:

public class Application implements Module {
   public static void main(String[] args) {
      Bootique.app(args).module(Application.class).run();
   }
   @Override
   public void configure(Binder binder) {
     // BQCoreModule provides access to 
     // Guice Multibinder for commands
     BQCoreModule.contributeCommands(binder)
                 .addBinding()
                 .to(HelloCommand.class);
   }
}

Now rerun the app and check that a new option appeared on the list:

NAME
      my.jar

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

      --hello

      --help
           Prints this message.

As you may have guessed, now you can run the app with "dash dash hello", and will see our command executed:

java -jar my.jar --hello
Hello, world!

There’s actually another way to add commands to Bootique via Commands class, but let's not overload our basic example with too many APIs.

Hello, YAML!

How do you write more complex commands? Two words: injection and configuration. I'll show the examples of both. By default configuration is read from YAML (you’ve seen "config" option printed when you ran the app above). Pieces of configuration can be turned into custom Java beans. Let’s create such a bean:

public class MyConfig {
   private String property1;
   private String property2;
   // setters/getters follow 
   // ... 
}

And now create "my.yml" with compatible config (using "my" prefix to distinguish our "subconfig" from other configurations that may be present in this file):

my:
    property1: p1
    property2: p2

Now let's read the config. For this we need to inject ConfigurationFactory into the command class:

public class HelloCommand implements Command { 
   // injecting configFactory as Guice Provider
   // ensures lazy initialization
   @Inject
   private Provider<ConfigurationFactory> configFactory;
   @Override
   public CommandOutcome run(Cli cli) {
      MyConfig config = configFactory.get()
          .config(MyConfig.class, "my");
      String message = String.format("I was started with (%s, %s)", 
           config.getProperty1(),
           config.getProperty2());

      System.out.println(message);
      return CommandOutcome.succeeded();
   }
}

Rerunning the app with config file:

java -jar my.jar --hello --config=my.yml
I was started with (p1, p2)

This way, we can put all our configuration in one place in an expressive format, and the file can be easily substituted for each application run.

Modules

Very likely you won't need to write most of the commands yourself. You can use any of the existing standard Modules (listed on the site), and use their commands. The easiest way to do it is to declare needed modules as your project dependencies, and turn on auto-loading:

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

This way, you can quickly and declaratively build REST apps, servlet apps, job runners, migration scripts, database apps, and what not.

Do I Have an Opinion?

I have many (often strong) opinions on how things should be programmed. But Bootique's philosophy is to allow you to have your own. The only requirement for it is Guice. This part is not possible to swap out. The rest of Bootique is completely open to extension and customization. This includes command-line style, dispatch strategy, configuration format, etc.

Each module, on the other hand, is "opinionated." E.g. bootique-jetty works with Jetty and will not work with Tomcat. But it doesn’t have to. If you want to embed Tomcat, you create a Tomcat integration module instead and do not use Jetty.

This is the main advantage of the Bootique platform — its combination of an extensible core with ready-to-use modules. It allows you to get started quickly and with a minimal amount of code by using standard modules, yet doesn’t limit what kind of app you can build or what technology you can use. It encourages scalable, modular design and supports full customization of the stack. Even the logging framework is your choice!

Come Together

Bootique is still a young technology, though already used in production for complex enterprise services. We are currently working on a new project site at bootique.io and writing documentation. The framework and extensions are open source under the liberal Apache license and we encourage anyone interested in container-less Java to show up on GitHub and take part in Bootique's trial and improvement.

Build vs Buy a Data Quality Solution: Which is Best for You? Maintaining high quality data is essential for operational efficiency, meaningful analytics and good long-term customer relationships. But, when dealing with multiple sources of data, data quality becomes complex, so you need to know when you should build a custom data quality tools effort over canned solutions. Download our whitepaper for more insights into a hybrid approach.

Topics:
java ,application development ,platform ,bootique

Published at DZone with permission of Andrus Adamchik, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}