Vert.x Web API Service helps you routing the API requests incoming from a Vert.x Web Router built with Vert.x Web API Contract Router Factory to event bus. It’s based on Vert.x service proxies

Using Vert.x API Service

To use Vert.x API Service, add the following dependency to the dependencies section of your build descriptor:

  • Maven (in your pom.xml):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-web-api-service</artifactId>
 <version>3.6.0.CR1</version>
</dependency>
  • Gradle (in your build.gradle file):

dependencies {
 compile 'io.vertx:vertx-web-api-codegen:3.6.0.CR1'
}

Recap on Vert.x Web API Contract

Vert.x Web API Contract helps you to build a Vert.x Web router compliant to an OpenAPI spec, for example:

routerFactory.addHandlerByOperationId("operationId", routingContext -> {
  RequestParameters parameters = routingContext.get("parsedParameters");
  // Process the request
});

With Vert.x Web API Service you can define an event bus service that connects automatically to the router factory, allowing automatic request routing to Vert.x Event Bus.

We encourage you to read Service Proxy documentation before going further

Define your Service

First you need to define your service interface. Let’s start with this OpenAPI operation definition:

/api/transactions:
 get:
   operationId: getTransactionsList
   parameters:
     - name: from
       in: query
       style: form
       explode: false
       required: false
       schema:
         type: string
     - name: to
       in: query
       style: form
       explode: false
       required: false
       schema:
         type: string
   responses: ...
 put:
   operationId: putTransaction
   requestBody:
     required: true
     content:
       application/json:
         schema:
           type: object
           properties:
             from:
               type: string
               format: email
             to:
               type: string
               format: email
             value:
               type: number
               format: double
           additionalProperties: false
           required:
             - from
             - to
             - value
   responses: ...

Now we can build the interface that specifies a TransactionService that handles getTransactionsList and putTransaction operations. For each operation you need to write a method with name corresponding to operation id with following parameters:

  • Last parameter must be a Handler<AsyncResult<OperationResponse>>

  • Second to last parameter must be a OperationRequest

  • All parameters from first to second to last (excluded) are extracted from RequestParameter with specified type automatically, but they need to respect service proxy restrictions

For example:

@WebApiServiceGen
interface TransactionService {
 void getTransactionsList(String from, String to, OperationRequest context, Handler<AsyncResult<OperationResponse>> resultHandler);
 void putTransaction(JsonObject body, OperationRequest context, Handler<AsyncResult<OperationResponse>> resultHandler);
}

When you receive a request at TransactionService.getTransactionsList() the generated service handler will automatically extract from and to parameter (if present) from OperationRequest. In putTransaction() we use the body parameter name to extract the json body.

The service handler is also capable to translate JsonObject to Vert.x data objects automatically, for example if you have a Transaction data object that matches the json schema above, you can rewrite the putTransaction() signature as:

void putTransaction(Transaction body, OperationRequest context, Handler<AsyncResult<OperationResponse>> resultHandler);

Note that generated service handler matches method parameters with spec’s parameter name and not with the location of parameter, so avoid duplicated parameter names in your spec

We also encourage to extract with RequestParameter parameters that uses json schema allOf/anyOf/oneOf/not keywords because the extraction can produce undefined behaviours

Implement your service

Now you can implement your service. The OperationRequest object contains headers and parameters maps.

To write the request you must call the resultHandler with an OperationResponse. To construct the OperationResponse you can use some handy methods like OperationResponse.completedWithJson or OperationResponse.completedWithPlainText

For example:

resultHandler.handle(
  Future.succeededFuture(
    OperationResponse.completedWithPlainText(Buffer.buffer("Hello world!"))
  )
);

Mount to Router Factory and run the service

Now that your service is ready you need to mount it to OpenAPI3RouterFactory. When you use one of the methods below, the router factory mounts an handler that routes the request through the event bus to the service at the address specified. Pay attention to specify the correct address to event bus endpoint.

You have four methods to match the service with router operation handlers:

The x-vertx-event-bus must be one of these two formats:

  • A string containing the address of service

  • An object containing the field address and the field method that specifies the interface method name

For example if I want to route getTransactionsList to TransactionService mounted at event bus address transaction_service.my_application:

/api/transactions:
 get:
   operationId: getTransactionsList
   parameters: ...
   responses: ...
   x-vertx-event-bus: transaction_service.my_application

Or

/api/transactions:
 get:
   operationId: getTransactionsList
   parameters: ...
   responses: ...
   x-vertx-event-bus:
     address: transaction_service.my_application
     method: getTransactionsList

Then you can call mountServicesFromExtensions that scans entire spec and mounts the handlers that route to your service the requests

Now you can register your service to event bus:

TransactionService service = new TransactionServiceImpl();
final ServiceBinder serviceBinder = new ServiceBinder(vertx).setAddress("address");
MessageConsumer<JsonObject> serviceConsumer = serviceBinder.register(TransactionService.class, service);