SkillAgentSearch skills...

Irked

Controller framework for Vert.x-web with automatic configuration and dynamic discovery.

Install / Use

/learn @GreenfieldTech/Irked
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Irked Vert.x Web Framework 5.x

Irked is a very opinionated framework for configuring Vert.x-web routing and call dispatch.

It allows you to write your REST API code without writing routing boiler plate by leveraging annotations, auto-discovery through reflection and optionally (if you're into that as well) dependency injection.

This version supports Vert.x 5. To use with earlier Vert.x versions, try Irked 4 for Vert.x 4 support, Irked 2 for Vert.x 3.9 support or Irked 1 for earlier versions (Vert.x 3.9 has changed its API in a non-backward compatible way - method return types were changed - which required that 1 + 2 split).

Other than different backward compatibility, Irked versions are essentially the same with bug fixes ported to all releases.

Installation

Irked is available from the Maven Central Repository.

If using Maven, add Irked as a dependency in your pom.xml file:

<dependency>
    <groupId>tech.greenfield</groupId>
    <artifactId>irked-vertx</artifactId>
    <version>5.0.6</version>
</dependency>

For other build tools, see the Maven Central website for the syntax, but it generally boils down to just using tech.greenfield:irked-vertx:5.0.6 as the dependency string.

Quick Start

You may want to take a look at the example application at src/example/java/tech/greenfield/vertx/irked/example/App.java which shows how to create a new Vert.x Verticle using an Irked Router and a few very simple APIs. Then you may want to read the rest of this document for explanations, rationale and more complex API examples.

To run the example application, after compiling (for example, using mvn compile) run it with your full Vert.x 5.0.6 installation:

vertx run -cp target/classes/ tech.greenfield.vertx.irked.example.App

Or, alternatively, using the Vert.x JAR dependencies in the Irked maven project:

mvn exec:exec -Dexec.executable=java -Dexec.args="-cp %classpath io.vertx.core.Launcher run tech.greenfield.vertx.irked.example.App"

Usage

Under Irked we use the concept of a "Controller" - a class whose fields and methods are used as handlers for routes and that will handle incoming HTTP requests from Vert.x-web.

A "master controller" is created to define the root of the URI hierarchy - all configured routes on that controller will be parsed relative to the root of the host.

Setup and Simple Routing

To publish routes to the server's "Request Handler", create your controller class by extending the irked Controller class, define fields or methods to handle HTTP requests and annotate them with the route matching logic that you want Irked to configure for each handler.

  • Most often you'd want to just match on HTTP method and URI, for which Irked offers annotations of the form @Method("/path"), such as @Get("/foo").
  • You can also use the annotation @Endpoint("/path") to match on all methods (this very is useful to mount sub-controllers, as detailed below).
  • The path argument for the both method-specific and @Endpoint annotations is optional and omitting it will match requests for all URIs.

An Example Controller

package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.status.*;
import tech.greenfield.vertx.irked.annotations.*;

class Root extends Controller {

    @Get("/")
    Handler<RoutingContext> index = r -> {
        // classic Vert.x RoutingContext usage
        r.response().setStatusCode(200).end("Hello World!");
    };

    @Post("/")
    void create(Request r) {
        // the irked Request object offers some useful helper methods over the
        // standard Vert.x RoutingContext
        r.send(new BadRequest("Creating resources is not yet implemented"));
    }
    
    @Put("/update")
    String update(Request r) {
        return "Updated completed";
    }
}

Initializing

After creating your set of Controller implementations, deploy them to Vert.x by setting up a Verticle like you would do for a Vert.x-web Router, but use Irked to create a router from your root controller - and set that as the request handler.

A Vert.x Web HTTP Server Example

Router router = Irked.router(vertx).with(new com.example.api.Root());
vertx.createHttpServer().requestHandler(router).listen(8080);

Configuration Errors

Sometimes humans make mistakes, it happens. When Irked is asked to setup your controllers (when calling with() or one of the other setup methods), it scans your configuration (the controller classes annotations) and if it detects a configuration that cannot be executed - for example, handlers with too few or too many parameters - it will throw an InvalidRouteConfiguration exception with as much details as appropriate. This happens during the Vert.x setup stage and before the HTTP server request handler is set up. We make every attempt to not cause exceptions to be thrown during actual request processing, and any such generated by the Irked implementation will be considered bugs and will be fixed.

Sub Controllers

Complex routing topologies can be implemented by "mounting" sub-controllers under the main controller - by setting fields to additional Controller implementations and annotating them with the @Endpoint annotation with the URI set to the endpoint you want your sub-controller to be accessible under.

Main and Sub Controllers Example

package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.annotations.*;

class Root extends Controller {

    @Endpoint("/blocks") // the block API handles all requests that start with "/blocks/"
    BlockApi blocks = new BlockApi();

}
package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.annotations.*;

class BlockApi extends Controller {

    @Get("/:id") // handle requests like "GET /blocks/identifier"
    Handler<Request> retrieve = r -> {
        // irked supports Vert.x-web path parameters 
        r.send(loadBlock(r.pathParam("id")));
    };
}

Request Context Re-programming

As hinted above, irked supports path parameters using Vert.x-web, but unlike Vert.x-web's sub-router, irked controllers support path parameters everywhere, including as base paths for mounting sub-controllers.

As a result, a sub-controller might be interested in reading data from a path parameter defined in a parent controller, such that the sub-controller has no control over the definition. To promote object oriented programming with good encapsulation, irked allows parent controllers to provide access to parameter (and other) data by "re-programming" the routing context that is passed to sub-controllers.

A parent controller can define path parameters and then extract the data and hand it down to local handlers and sub-controllers through a well defined API, by overriding the Controller.getRequestContext() method.

This functionality is also just useful to DRY repeatable data access pattern by encapsulating them in a request context type.

Request Context Re-programming Example

package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.annotations.*;

class MyRequest extends Request {

    String id;

    public MyRequest(Request req) {
        super(req);
        id = req.pathParam("id");
    }

    public String getId() {
        return id;
    }

}
package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.status.*;
import tech.greenfield.vertx.irked.annotations.*; 

class Root extends Controller {

    @Get("/:id")
    void report(MyRequest r) {
        r.response(new OK()).end(createReport(r.getId()));
    }

    @Endpoint("/:id/blocks") // ":id" is read by the MyRequest class
    BlockApi blocks = new BlockApi();

    @Override
    protected MyRequest getRequestContext(Request req) {
        return new MyRequest(req);
    }
}
package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.annotations.*;

class BlockApi extends Controller {

    @Get("/")
    Handler<MyRequest> retrieve = r -> {
        r.send(getAllBlocksFor(r.getId())); // read the identifier field defined by Root and MyRequest
    };
}

Handler-specific Request Context Re-Programming

By having a controller implement getRequestContext() it can create a specific Request sub-type to be used by all handlers in that controller or controllers mounted under it. Handlers can also require additional specialization of the request context, on a per-handler basis. That allows different handlers to use different specializations - if it makes sense. Irked will automatically construct such specializations using one of two methods:

  1. If the specialization can be trivially constructed from the current request context - either Request or a controller-level specialization created by a custom getRequestContext() - i.e. the specialized Request sub-type class has a constructor that takes a single such parameter.
  2. If the current controller class provides a creator method that accepts a Request instance (not a sub-type) and returns the needed type.

Both methods are demonstrated in the following examples:

Trivially Constructed Request Context Specialization Example
package com.example.api;

import tech.greenfield.vertx.irked.*;
import tech.greenfield.vertx.irked.status.*;
import tech.greenfield.vertx.irked.annotations.*;
import com.example.api.Hasher;

class Api extends Controller {

    publi
View on GitHub
GitHub Stars36
CategoryDevelopment
Updated2d ago
Forks2

Languages

Java

Security Score

90/100

Audited on Apr 4, 2026

No findings