The Tribe Blog

CREST: Boost Your CLI!

1432
No Comments

Reminder about CREST

CREST is a library that allows you to write a command line interface program using a declarative API like JAX-RS for HTTP.

Its key features are:

  • 100% Annotation based
  • Ability to use bean validation on method
  • Fully Java integrated
  • Supports complex parameter binding as parameter

Often used as an example, for what it’s worth, here is a “Hello, World!” example using CREST:

public class Hello {
    @Command
    public static String hello(@Option("name") String name) {
        return "Hello " + name;
    }
}

One more step

The latest release of CREST boosted its features, which gives you more power for enterprise tooling needs.

Interception

The @Command annotation now contains an interceptedBy method allowing you to specify some interceptors.

To write a CREST interceptor, just decorate a method with @CrestInterceptor by taking a CrestContext as a parameter and returning an Object:

public class InComplex {
    @CrestInterceptor
    public static Object intercept(final CrestContext crestContext) {
        return crestContext.proceed();
    }
}

It does not reuse javax.interceptor semantic because it adds several metadata, which are adapted to the CLI environment, into the CrestContext. This is similar to the metadata on the parameter of the command method.

Having interceptors allows you to create several interesting features; like asking the user for missing parameter (provided inInteractiveMissingParameters interceptor), adding security on top of commands for checking your enterprise LDAP or even changing the commands completely if you want.

Maven integration

Writing a CLI is not exactly the smoothest process, especially with the registration of commands and now interceptors. The nicest approach is to rely on running scans which is not always a good idea. But now there is a Maven plugin for dumping in a file with classes to scan at build-time; making the runtime really smooth.

Usage is as simple as declaring this plugin in your POM:

<plugin>
  <groupId>org.tomitribe</groupId>
  <version>${crest.version}</version>
  <artifactId>crest-maven-plugin</artifactId>
    <executions>
      <execution>
        <goals>
          <goal>descriptor</goal>
        </goals>
      </execution>
    </executions>
</plugin>

Stream injections

Sometimes you not only need input parameters to return a value, but you also need to work with input and output streams.

This is now made easy with @In Inpustream, @Out PrintStream and @Err PrintStream parameter injection support. This opens the door to a lot of advanced commands. A simple but very powerful example is being able to work on super huge files!

CLI module

A big enhancement is to provide out of the box a CLI module! What does it mean? That writing an interactive CLI is now very simple.

This super easy module brings:

  • Command history
  • Alias support
  • Basic pipping support (mycommand | mypipecommand)

The central point to access the CLI module is through the CrestCli. It provides a Main method but you can extend it to provide history persistency in a custom file or a file with aliases for your commands.

Service support

A common need for writing CLI is to be able to reuse classes across commands. This is possible by giving a set of services to the environment. Then these services will be reusable across commands (i.e. when instances are shared). When mixed with interceptors, it allows you to retrieve a service using contextual environment value.

Finally, Environment itself or its subclasses are usable as service directly. It means you can get it injected like this:

public class MyCommand {
    public static void myCommands(Environment env, MyService service) {
        // ...
    }
}

More to come

There are still room for much more enhancements. Some that quickly comes to mind includes support of interceptor binding like CDI, a smoother API for CLI based on annotations (for history persistence), or scanning of services using a @Service annotation, etc…

The future of CREST depends on your needs and innovations. If you want to join the project and be part of the its future, simply fork CREST on Github and add the features you are thinking about! A bonus is that you will appear on the awesome Tomitribe Open Source website. :)


Romain

About the author

Romain Manni-Bucau

Senior Software Engineer
http://rmannibucau.wordpress.com
Follow Romain Manni-Bucau
Romain is a contributor of the Apache TomEE project since July 2010 and a Senior Software Engineer at Tomitribe. In his plethora of Apache projects, he’s involved in OpenEJB, OpenWebBeans, Geronimo, CFX, BVal and DeltaSpike. Romain is a founding member of the Sirona and BatchEE project and brought JCache implementation to the Apache Commons JCS project. He regularly speaks at JUG and conferences to spread the word about all the Apache goodness. Since Java EE 6, he is convinced that REST architectures and design are the future of Java EE and not only for web technologies. Romain started as a Java EE expert at Atos transversal unit. He later joined Swissquote Bank as a backend developer. Today he is a part of the Tomitribe adventure and continues his mission with all the Apache projects, especially TomEE. Romain likes "coding on the edge," always proposing solutions of tomorrow and that's why he joined the Tribe!