/vertx-spring

Vert.x Spring Tools

Primary LanguageJavaMIT LicenseMIT

Vert.x Spring Tools

This small library helps with embedding Vert.x inside a Spring Boot or classic Spring application.

Quickstart

Import the library as a dependency in your build tool of choice:

build.gradle
dependencies {
    implementation 'org.unbroken-dome.vertx-spring:vertx-spring:0.2.3'
}

Vertx-spring is available from the JCenter repository.

To use Vert.x inside your application, simply put the @EnableVertx annotation on one of your @Configuration classes:

@Configuration
@EnableVertx
public class MyConfiguration {

    // Verticle beans will be auto-deployed once Vertx has started up
    @Bean
    public MyVerticle myVerticle() { return new MyVerticle(); }
}

Auto-configuration for Spring Boot applications is available as well, simply by putting this library on the classpath.

The Vertx instance is created, started and shut down as part of the Spring Lifecycle. Spring beans of type Verticle will be detected and deployed automatically.

Under the covers, using the @EnableVertx annotation will import some Spring configurations and ultimately register a SpringVertx bean. It serves as the container for a Vertx instance and adapts it to the Spring lifecycle.

Configuring the Vertx instance

For additional configuration, you can make any of your beans (or @Configuration classes) implement the VertxConfigurer interface. It has one method, configure, that can be used to set the VertxOptions or register verticles for deployment once the Vertx instance has been started.

@Configuration
@EnableVertx
public class MyConfiguration implements VertxConfigurer {

    @Override
    public void configure(SpringVertx.Builder builder) {
        builder
            // Register a custom Verticle for deployment
            .verticle(new MyVerticle())
            // Modify the VertxOptions
            .options(opt -> opt.setClustered(true));
    }
}

When multiple VertxConfigurer beans are present, their ordering can be specified by annotating them with @Order.

When using Spring Boot, it is also possible to specify most of the VertxOptions settings via the application properties (see below).

Using the Vertx instance

Vert.x does not separate between creation and startup of a Vertx instance. Since it is created as a result of the Spring lifecycle (not on Application context refresh), it is not available when the application context is initialized, so it cannot be injected into other beans directly.

The recommended way to use Vert.x with this library is to register Verticle beans (see below for more details). Verticles will have their lifecycle managed by Vert.x, and will be initialized with the Vert.x instance with which they can work.

If you really need to use the Vertx instance from outside a Verticle, you can have any bean implement the VertxListener interface, and it will be notified about the Vertx instance starting and stopping (passing the Vertx object as a parameter):

@Component
public class MyVertxComponent implements VertxListener {

    @Override
    public void vertxStarted(Vertx vertx, VertxOptions options) {
        // Work with the Vertx instance
    }
}

The events that the listener supports (Vertx started/stopped, verticle deployed/undeployed) are also published as Spring ApplicationEvent`s, so you can subscribe to them using an `ApplicationListener:

@Component
public class MyVertxComponent implements ApplicationListener<VertxStartedEvent> {

    @Override
    public void onApplicationEvent(VertxStartedEvent event) {
        Vertx vertx = event.getVertx();
        // Work with the Vertx instance
    }
}

Using Verticles

Verticles are the conventional unit of modularization in Vert.x. If you add a Spring bean to your application context whose type is Verticle (or an implementing class), it will be picked up and deployed automatically once the Vertx instance has started.

If you do not like this auto-deployment behavior, you can disable it using the deployVerticles parameter of the @EnableVertx annotation (by default it is true):

@Configuration
@EnableVertx(deployVerticles = false)
public class MyConfiguration {

    // This verticle will *not* be deployed automatically
    @Bean
    public Verticle myVerticle() { return new MyVerticle(); }
}

You can also disable auto-deployment per bean, using the @VerticleDeployment annotation:

@Configuration
@EnableVertx
public class MyConfiguration {

    // This verticle will be deployed automatically...
    @Bean
    public AutoVerticle autoVerticle() { return new AutoVerticle(); }

    // ...but this one will not
    @Bean
    @VerticleDeployment(false)
    public ManualVerticle manualVerticle() { return new ManualVerticle(); }
}

Customizing Verticle Deployment Options

There are several methods to fine-tune the verticle deployment process (which is equivalent of providing a DeploymentOptions instance when calling Vertx.deployVerticle() directly).

First, most of the settings from DeploymentOptions have a corresponding attribute in the @VerticleDeployment annotation:

@Configuration
@EnableVertx
public class MyConfiguration {

    @Bean
    @VerticleDeployment(ha = true, instances = 4)
    public Verticle myVerticle() { return new MyVerticle(); }
}

Another approach is to wrap the verticle inside a VerticleRegistrationBean that contains the verticle as well as the deployment options (be careful not to make the Verticle itself a @Bean in this case, or it will be deployed twice):

@Configuration
@EnableVertx
public class MyConfiguration {

    @Bean
    public VerticleRegistrationBean myVerticle() {
        DeploymentOptions options = new DeploymentOptions()
            .setHa(true)
            .setInstances(4);
        return new VerticleRegistrationBean(new MyVerticle())
            .setDeploymentOptions(options);
    }
}

The verticle can also be "self-describing" its desired deployment options, by implementing the DeployableVerticle interface:

@Component
public class MyVerticle extends AbstractVerticle implements DeployableVerticle {

    @Override
    public DeploymentOptions getDeploymentOptions() {
        return new DeploymentOptions()
            .setHa(true)
            .setInstances(4);
    }
}

Customizing Verticle Deployment Order

The standard Spring mechanisms @Order and Ordered are recognized and will be used for ordering verticle deployment. All verticles with a lower order value are guaranteed to be deployed before verticles with a higher value, while all verticles with the same value are deployed simultaneously.

Again, there are several ways to specify the order:

  • using the @Order annotation on the bean method or a @Component class

  • as a property on the VerticleRegistrationBean

  • by having the Verticle class itself implement Ordered

Deploying multiple instances of Verticle beans

Vert.x core allows the number of verticle instances to be specified in the DeploymentOptions, for example when distribution of loads across multiple processor cores is desired. However, this obviously doesn’t work if the Verticle instance has already been created as a singleton.

To use multiple-instance deployment, declare your verticles either as prototype-scoped (with @Scope("prototype")), or use a FactoryBean that creates prototypes.

@Configuration
public class MyConfiguration {

    @Bean
    @Scope("prototype")
    @VerticleDeployment(instances = 4)
    public PrototypeVerticle prototypeVerticle() {
        return new PrototypeVerticle();
    }

    @Bean
    @VerticleDeployment(instances = 3)
    public SomeVerticleFactoryBean factoryCreatedVerticle() {
        return new SomeVerticleFactoryBean();
    }
}

The Spring Verticle Factory

For Vert.x to create Verticle instances in a multi-instance deployment, it needs a VerticleFactory that creates verticles by name. This library contains a VerticleFactory implementation that resolves verticle names to prototype Spring beans from the application context. It is registered with the spring: prefix by default. You can change the prefix using the verticleFactoryPrefix method on SpringVertx.Builder.

The spring: prefix can also be used to deploy additional verticles after startup.

Configuring the ClusterManager

If the application context contains a bean of type io.vertx.core.spi.cluster.ClusterManager, it will be used by the SpringVertx instance as the cluster manager. Otherwise, the detection/creation of a suitable ClusterManager will work as described in the Vert.x core documentation.

Spring Boot Auto-Configuration

When using Spring Boot, Vertx will be auto-configured by having this library on the classpath. Most settings from VertxOptions can be configured as properties from any Spring PropertySource. Most commonly, you can configure these settings in your application.yml or application.properties:

application.yml
vertx:
  clustered: true
  event-bus:
    host: localhost
    port: 42042

ClusterManager Auto-Configuration

If one of the 4 official Vert.x cluster manager implementations ( Hazelcast, Ignite, Infinispan or Zookeeper) is used, it can be configured automatically by being on the classpath.

If (for whatever reason) more than one of these ClusterManager implementations is available on the classpath, one has to be chosen explicitly by setting the vertx.cluster-manager.type property, e.g.

application.yml
vertx.cluster-manager.type: hazelcast

Hazelcast

If io.vertx:vertx-hazelcast is on the classpath, a HazelcastClusterManager bean will be created automatically.

vertx-spring will piggy-back on the Hazelcast auto-configuration that is already offered by Spring Boot. Use either of the following three options:

  • Set the spring.hazelcast.config property to the location of a configuration resource;

  • create a com.hazelcast.config.Config bean in your application context

  • create a bean of type com.hazelcast.core.HazelcastInstance directly.

The HazelcastInstance will be picked up and used to create a HazelcastClusterManager.

Ignite

If io.vertx:vertx-ignite is on the classpath, an IgniteClusterManager bean will be created automatically. It will be configured from a ignite.xml resource on the classpath, or the default-ignite.xml from the library (as described in the documentation).

Infinispan

If io.vertx:vertx-infinispan is on the classpath, an InfinispanClusterManager bean will be created automatically. It will be configured from a infinispan.xml resource on the classpath (as described in the documentation).

Zookeeper

If io.vertx:vertx-zookeeper is on the classpath, a ZookeeperClusterManager bean will be created automatically.

You can configure your Zookeeper client using environment properties:

application.yml
vertx.cluster-manager.zookeeper:
  hosts: 127.0.0.1
  session-timeout: 20000
  connect-timeout: 3000
  root-path: io.vertx
  retry:
    initial-sleep-time: 100
    interval-times: 10000
    max-times: 5

Alternatively, you can set the vertx.cluster-manager.zookeeper.config property to the location of a JSON configuration resource, as described in the cluster manager documentation:

application.yml
vertx.cluster-manager.zookeeper.config: classpath:zookeeper.json