Skip to content
This repository has been archived by the owner on Oct 25, 2022. It is now read-only.

swookiee/swookiee.github.io

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

62 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

What is swookiee*

This is how a shaved wookiee could look like:

shaved wookiee

Swookiee basically is a JVM Runtime for REST Services. It is lightweight (~17 MB, yeah... "lightweight") and includes libraries like guava, joda-time, metrics, etc. It also supports service implementation written in Groovy and Scala (+7MB each). It uses a JAX-RS 2 (Jersey), Jetty, Jackson stack on top of the Equinox OSGi runtime to serve REST Services. swookiee also provides multiple REST APIs to deploy and control services and components via REST.

Our main goals are:

  • simplify exposing REST Services in the JVM
  • JVM-Polyglot: Solve problems in best fit language
  • reduce mandatory infrastructure and architectural knowledge from developers
  • define boundaries and APIs
  • enable deployment on artifact level (very simple OSGi RFC-182 implementation)
  • increase transparency through direct metrics, graphite and JSON logging support

Build & start

Build & Start

cd com.swookiee.runtime
mvn clean install

cd com.swookiee.runtime
mvn exec:exec

Web Console

When swookiee is up and running the Web Console can be accessed via http://localhost:8080/system/console. The default credentials are admin:admin123.

REST Services

To expose a REST service in swookiee you can describe the REST API with a simple interface:

@Path("/hello")
@Produces(APPLICATION_JSON)
public interface HelloWorld {
    @GET
    String hello();
}

Through using the given @Component annotation the implementation of the interface will be exposed.

@Component
public class HelloWorldService implements HelloWorld {
    @Override
    public String hello() {
        return "Hola!";
    }
}

A REST service will be exposed using the OSGi - JAX-RS Connector. Thus, every JAX-RS component which is an available OSGi service will also be published via Jersey. You will find a deteiles Jersey user guide here.

Filters, Exception Mapping, ...

In addition to provide services you might need to register Filter (e.g. for CORS). This can be done via ContainerResponseFilter and ContainerRequestFilter implementations:

@Component
@Provider
public class MyFilter implements ContainerResponseFilter {

    @Override
    public void filter(final ContainerRequestContext requestContext, final ContainerResponseContext responseContext) {
    }
}
@Component
@Provider
public class MyFilter implements ContainerRequestFilter {

    @Override
    public void filter(final ContainerRequestContext requestContext) {
    }
}

In order to register an exception mapper you have to implement the ExceptionMapper interface:

@Component
@Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {

    @Override
    public Response toResponse(final MyException exception) {
        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
    }
}

JSON logging output

In case you want to use logstash and kibana to analyze your logs you might want to use JSON as an output format. This can be achieved through setting the property productionLogging to true. To change the output folder configure loggingDirectory with your desired path. The output filename will be osgi-json.log.

Deployment and runtime management via REST

RFC-182

Configuration

The Swookiee Runtime can be configured programmatically and via the UI of the Web Console.

Programmatic Configuration

The programmatic configuration can be done via an API on top of the OSGi Configuration Admin. The full sample can be found here

Define a POJO with the components you want to configure. In this case we want to change the admin user credentials and the graphite reporter configuration:

public class Configuration {
    public AdminUserConfiguration adminUserConfiguration;
    public GraphiteReporterConfiguration graphiteReporterConfiguration;
}

Define a YAML file which matches the attributes of your POJO. Additionally set the desired parameter values:

adminUserConfiguration:
  username: "admin"
  password: "admin42"
    
graphiteReporterConfiguration:
  graphiteHost: localhost
  graphitePort: 2003
  reportingIntervalInSeconds : 42
  reportingEnabled: true
  reportingPrefix: "configDemo"

In order to set your configuration values to the addressed components you can create a Declarative Service Component which is then using ConfigurationUtils to set your configuration parameters

@Component
public class ConfigurationProviderSample {

    private ConfigurationAdmin configAdmin;

    @Activate
    public void activate(final BundleContext bundleContext) {

        final URL configurationFile = bundleContext.getBundle().getResource("Configuration.yaml");
        ConfigurationUtils.applyConfiguration(Configuration.class, configurationFile, configAdmin);

    }

    @Reference
    public void setConfigurationAdmin(final ConfigurationAdmin configurationAdmin) {
        this.configAdmin = configurationAdmin;
    }

    public void unsetConfigurationAdmin(final ConfigurationAdmin configurationAdmin) {
        this.configAdmin = null;
    }
}

UI

Most configuration parameters can be controlled via the Web Console: http://localhost:8080/system/console/configMgr

Pushing metrics to graphite

Every published REST interface will be monitored via metrics. In addition basic JVM statistics will be collected. In order to configure the graphite reporter you can configure various settings:

graphiteReporterConfiguration:
  graphiteHost: localhost
  graphitePort: 2003
  reportingIntervalInSeconds : 42
  reportingEnabled: true
  reportingPrefix: "configDemo"

Example Screenshot of some made up traffic: graphite

Swagger

The above described REST Resource can be enriched using swagger-annotations. A full sample can be found here.

We could add the @Api and @ApiOperation annotations to our sample service:

@Path(Status.PATH)
@Produces(APPLICATION_JSON)
@Api(value = Status.PATH, description = "Returns a status")
public interface Status {

    final static String PATH = "/status";

    @GET
    @ApiOperation(value = "Ping the Status API to receive a StatusObject", response = StatusObject.class)
    public StatusObject ping();
}

The following steps are important to let swookiee deliver you swagger api documentation:

  1. Make sure you have the maven-swagger-plugin configured properly and you are able to see generated swagger json files? Also make sure that the <basePath>/services</basePath> is set according to your configuration. Otherwise you won’t be able to test you API.
  2. Is the generated json part of your bundle/artefact/.jar? Is the folder accessable from within the Bundle? Set the the Bundle-Classpath to include the documentation folder.
  3. Add the X-Swagger-Documentation header in you MANIFEST.MF or your maven-bundle-plugin configuration to point to the documentation folder inside the jar, such as: X-Swagger-Documentation: /swagger.

After installing the bundle you will find the swagger-ui under http://localhost:8080/swagger/index.html. Click on the small swookiee icon to see your documentation and test your API.

Screenshot of the sample: swagger

Archetype(s) & Tooling & Samples

Samples & Archetype

Eclipse

Netbeans

Todos

  • provide rpm, deb and other packages
  • more JVM languages? (see clojure branch)
  • Running swookiee programatically
  • Integration Test Tooling

Thanks

Many thanks to Intuit Data Engineering & Analytics for the support!

IDEA

License

The code is published under the terms of the Eclipse Public License, version 1.0.

* derived from "shaved wookiee"

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published