{#========================================== Docs : "overview" ==========================================#}

Spincast overview

{#========================================== Section "overview / introduction" ==========================================#}

Introduction

Spincast is based on the shoulders of a giant, Guice (from Google). Other Java web frameworks may claim they support Guice, and maybe even have a section of their documentation dedicated to the topic. Spincast is one of those that is totally built on Guice, from the ground up! If you already know Guice, Spincast will be really easy to grasp for you.

Guice is not only (in our opinion) the best dependency injection library of the Java ecosystem, but also a fantastic base to build modular applications. Everything is divided into modules which are swappable and overridable. Each module can declare which dependencies it requires from other modules. In fact, Guice is so flexible that you may even find ways of using Spincast we haven't think about!

If you know another dependency injection library, like Spring, it can also help but you'll probably have to learn one of two new tricks!

Here's what using Spincast looks like at a very high level:

Users make requests to your web application. This application can have an HTML interface, built using popular tools like jQuery, React, Ember, Angular, etc. That HTML interface can be generated by Spincast (using a built-in templating engine) or can be a Single Page Application where Spincast is used as a bootstrapper and a data provider (JSON or XML) for the SPA.

Spincast is also a good platform to build REST web services or microservices, without any user interface, since it "talks" JSON and XML natively.

{#========================================== Section "architecture / architecture" ==========================================#}

Architecture

The core of a Spincast application is its Guice modules. Most of the time, your application's main Guice module will extend the default SpincastDefaultGuiceModule, so you start with a default implementation for all the required components, and not from scratch. Many components are provided by the various plugins, but your application will also bind business logic components specific to it: controllers, services, etc.

As you can see :

{#========================================== Section "architecture / request handling" ==========================================#}

Request handling

Now that we have an idea on how is structured a Spincast application, let's see how it handles requests and what are the components involved.

First, the embedded HTTP Server receives a request. This server consists of an IServer interface and an implementation. The default implementation is provided by the spincast-plugins-undertow plugin which uses the Undertow server.

If the request is for a static resource, the server serves it directly without even reaching the framework. Note that it's also possible to always generate the resource, using a standard route, so the request does enter the framework. There is even a third option which is what we call dynamic resources: if a request is made for a request which is not found, the server will pass the request to the framework. The framework can then create the resource and return it. The following requests for the same resource will use the generated resource and won't reach the framework anymore!

If the request is not for a static resource, the server passes it to the first true Spincast component: the front controller. The front controller is at the very center of Spincast! This is one of the very few components which is not provided by a plugin, but that is actually included in the spincast-core Maven artifact itself. Note that you still can extend the default Front controller and override some of its methods, though, if you need to tweak one thing or two.

The job of the front controller is to:

  • Ask the router for the appropriate route to use when a request arrives.
  • Call the route handlers of the matching route. A route can have many handlers: some filters which are run before the main handler, the main handler itself, and some filters which are run after the main handler.
  • If no matching route is returned by the router, the front controller will use a Not Found route. The Not Found route can be a custom one specified by the developer, or the default one.
  • If any exception occures during any of those steps, the front controller will use an Exception route. The Exception route can be a custom one specified by the developer, or the default one.

The job of the router (interface IRouter) is to determine the appropriate route to use, given the URL of the request, its HTTP method, etc. It will also extract the value of the dynamic path tokens, if any. For example, a route path could be /user/${userId}/tasks. If a /user/42/tasks request is made, the router will extract "42" as the value of the userId parameter and make this available to the rest of the framework.

Finally, the route handlers receive a request context reprensenting the request, and decide what to return as the response. This can be anything: Json, HTML, XML or even bytes.

{#========================================== Section "architecture / Required components and their default implementations" ==========================================#}

The required components and their default implementations

The required components are those without which a Spincast application can't run. Any code, any plugin, can assume those components are available, so they can inject them and use them! Spincast's core Guice module validates that an implementation for those components is actually bound and, if not, it throws an exception.

The default implementations for those required components are bound by the SpincastDefaultGuiceModule Guice module which is provided by the spincast-default Maven artifact.

What are those required components and what are the default implementations?

{#========================================== Section "architecture / Transitive dependencies" ==========================================#}

Transitive dependencies

The spincast-core Maven artifact only has 3 direct dependencies which are external to Spincast:

The versions used for those dependencies are defined in the spincast-parent Maven artifact's pom.xml.

Spincast core also uses some Apache commons libraries, but those are shaded, their classes have been relocated under Spincast's org.spincast.shaded package, so they won't conflit with your own dependencies.

That said, each plugin also adds some more dependencies! If you start with the spincast-default Maven artifact, a bunch of transitive dependencies will be included. If you need full control over the transitives dependencies added to your application, start with the spincast-core Maven artifact and pick, one by one, the plugins and implementations you want to use.