Redpipe is a Web Framework that unites the power and versatility of Eclipse Vert.x, the conciseness of
JAX-RS (with Resteasy),
and the non-blocking reactive composition of RxJava.
The main idea is that with Redpipe you write your endpoints in JAX-RS, using RxJava composition if you want, and underneath
it all, Vert.x is running the show and you can always access it if you need it.
Redpipe is opinionated, favors convention over configuration, and lets you combine the following technologies easily to
write reactive web applications:
Typically, instead of making a blocking call, asynchronous APIs will let you register a callback to invoke when
the action is done. But callbacks are error-prone and do not compose well.
The Promise model was introduced to
abstract over callbacks and asynchronous computations, where a Promise represents a producer of a value that
you can listen for, and be notified when the value is produced (we call that resolving a Promise).
RxJava is an implementation of the Promise model with support for single-value Promises
multiple-value Promise streams (Observable).
The idea of Redpipe is that you can either return normal values from your methods (if your code does not
need to block), or RxJava promises (if it does), which Redpipe will register on, and be notified when the
promises resolve and forward the resolved values to the client.
Out of the box, we support RxJava’s Single
and Observable, Completable and Maybe types for both RxJava 1 and 2,
although use of RxJava 2 is recommended because RxJava 1 is deprecated.
If your resource returns a Single<T>, the T will be sent to your client asynchronously as if you
returned it directly. In particular, standard and custom
apply as soon as the Single is resolved, as do
If your resource returns an Observable<T>:
By default, every item will be collected, and once complete, assembled in a List<T> and treated
as if your method had returned it directly (standard and custom body writers and interceptors apply
If you annotate your method with @Stream (from org.jboss.resteasy.annotations), then every item
will be sent to the client as soon as it is produced (again, via standard and custom body writers).
This is mostly useful for streaming bytes, buffers, or strings, which can be split up and buffered.
If you annotate your method with @Produces(MediaType.SERVER_SENT_EVENTS), then every item will
be sent to the client over
(SSE). As always, standard and custom body writers
are called to serialise your entities to events.
If your resource returns a Completable, an HTTP Response with status code 204 will be returned once the completable
If your resource returns a Maybe<T>, then the following response will be sent asynchronously once the maybe is
If the maybe is empty: an empty HTTP response using HTTP status code 404 indicating the resource has not been found
If the maybe has been fulfilled with an object of type T: an HTTP response with status code 200,
using the proper MessageBodyWriter<T>
RxJava 2 support
You need to import the following module in order to use RxJava 2:
And your reactive resource should look like that:
The optional module redpipe-fibers allows you to write your reactive code in fibers, which are
light-weight threads, also known as coroutines, while interacting seamlessly with RxJava.
Consider the following traditional RxJava code to forward the result of two web service invocations:
Rather than composing sequential Single values, you can write a fiber that can
await those values in what now looks like sequential code:
A fiber, here, is also a Single which can be integrated with the rest of your RxJava
operations, and it can await RxJava Single values to obtain their resolved value.
You can call await from any fiber body, or from any method annotated with @Suspendable.
You need to import the following module in order to use fibers:
And also the following Maven build plug-in to set-up your fibers at compile-time:
In order to get URIs that map to resource methods, you can use the redpipe routing module:
With this module, you can simply get a URI for a resource method HelloResource.hello by calling
the Router.getURI() method and passing it a reference to your resource method and any required
Within templates you can use the context.route method which takes a string literal pointing to your
resource method, and any required parameters:
You can either declare your JAX-RS resources and providers when instantiating the Server (as shown
above), or you can use two options to scan your packages to discover them.
If you include this dependency, fast-classpath-scanner
will be used to scan your classpath for resources and providers:
Configure Redpipe using defaults for DEV or PROD use.
Jdbc Url to use for connections to the database.
Jdbc driver class.
Maximum pool size for database connections.
Http port to bind to.
Http host to bind to.
0.0.0.0 (all interfaces)
For the redpipe-fast-classpath-scanner module
List of packages to scan for JAX-RS resources and providers.
You can access the current configuration in your application via the AppGlobals.getConfig() method.
On top of optional CDI support, JAX-RS supports injection of certain resources via the @Context annotation
on method parameters and members. Besides the regular JAX-RS resources, the following resources can be
Injectable global resources
The Vert.x instance (Also available as RxJava 1 & core).
A global context object.
Injectable per-request resources
The Vert.x Web RoutingContext (Also available as RxJava 1 & core).
The Vert.x request (Also available as RxJava 1 & core).
The Vert.x response (Also available as RxJava 1 & core).
The Vert.x AuthProvider instance, if any (defaults to null) (Also available as RxJava 1 & core).
The Vert.x User, if any (defaults to null) (Also available as RxJava 1 & core).
The Vert.x Web Session instance, if any (defaults to null) (Also available as RxJava 1 & core).
An SQLConnection (Also available as RxJava 1 & core).
True if there is a current user and he has that permission.
We support the following plugable template engines, which you just have to add a dependency on:
In order to declare templates, simply place them in the src/main/resources/templates folder. For
example, here’s our src/main/resources/templates/Controller/index.html.ftl template:
In order to return a rendered template, just return them from your resource, directly or as a Single:
Template files and negociation
Templates are located by convention in the templates folder and looked up from your classpath. If you
do not specify any template name to the Template constructor, the template will default to <Class name>/<method name>
by using the current JAX-RS resource class and method names.
You can override the template file by passing it in the constructor, to specify, for example, MyFolder/myindex.
When looking up a template file, Redpipe will look for any file that begins with the template name, followed by a . (dot)
with an extension. There should be at least one extension, which will be the template format extension (for example, .ftl for
freemarker). If there is another extension before the template extension, it will be used as the file format extension (for example
.txt for plain text).
If there are more than one file format extension, one will be selected based on the
HTTP content type negociation, such as the Accept request header.
The file format extension defines the MIME type returned to the client in the Content-Type response header. If there
is no file format extension, application/octet-stream is used.
For example, if you have two files foo.html.ftl and foo.txt.ftl and specify a template name foo, Redpipe will
select either of the two files depending on the client’s preferred representation.
You can write your own template renderer by declaring a META-INF/services/net.redpipe.engine.template.TemplateRenderer file in your
src/main/resources folder, containing the name of the class that extends the
You can send emails with the Mail class, which is a sort of Template:
This will use regular template look-up rules and look for templates/mail.txt.<template extension> and
templates/mail.html.<template extension>, and send the email asynchronously. Beware that unless you
subscribe to the Email.send() return value (type Completable), there is no guarantee that your email
will be sent before the response is sent.
Note that only the two file format variants .txt and .html will be looked-up.
Testing email delivery
In DEV mode, emails will be delivered to a mock mailer of type MockMailer which you can obtain from
AppGlobals, in order to test email delivery:
In PROD mode, you can configure the following settings:
Injectable global resources
The SMTP host name.
The SMTP port.
The SMTP username.
The SMTP password.
Whether to keep the SMTP connection open.
Whether to trust every SMTP connection.
Whether to start a TLS connection (supports DISABLED, OPTIONAL, REQUIRED).
Serving static files
If you want to serve static files you can place them in src/main/resources/webroot and declare the
Your files will then be accessible from the /webroot/ path prefix.
You can declare and inject service records using the following optional module:
Use the @ServiceName annotation to declare a service:
The same annotation can be used to look up services:
By default, if running on Kubernetes, Kubernetes services will be imported and available.
Note that services declared using @ServiceName will not be exported to Kubernetes, but
you can declare them in your build using Fabric8.
You can write plugins by declaring a META-INF/services/net.redpipe.engine.spi.Plugin file in your
src/main/resources folder, containing the name of the class that extends the
From there you can hook into various parts of the application (start-up, requests…).
And then configure your pom.xml so that it creates a fat-jar with the proper merging of
META-INF/services files, and pointing to your Main class:
Then, just follow the official guidelines by
pushing your code to GitHub and starting an image with it. You can even try our sample app at
https://github.com/FroMage/redpipe-openshift-helloworld.git (no context dir).
Alternately, you can use Fabric8 to build and deploy your module by adding this to your
Declaring services with Fabric8
You can declare Kubernetes services, labels and annotations with this configuration:
Run your WebApp with Maven
This is a pom.xml sample to easily run your project. Just run mvn install exec:java