Search code examples
javathymeleafvert.xvertx-verticle

Using Thymeleaf TemplateEngine with Vert.x 3.9


I am new to Vertx. I am trying to create thymeleaf template engine in my application but it raises this error

java: incompatible types: io.vertx.core.Vertx cannot be converted to io.vertx.reactivex.core.Vertx

and if I cast vertx to io.vertx.reactive.core.Vertx then I get this error

java.lang.ClassCastException: io.vertx.core.impl.VertxImpl cannot be cast to io.vertx.reactivex.core.Vertx

Apart from that database connection is successful and if I remove TemplateEngine line code runs smoothly.

package com.firstapp.main;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.mysqlclient.MySQLConnectOptions;
import io.vertx.mysqlclient.MySQLPool;
import io.vertx.reactivex.core.Vertx;
import io.vertx.reactivex.ext.web.common.template.TemplateEngine;
import io.vertx.reactivex.ext.web.handler.TemplateHandler;
import io.vertx.reactivex.ext.web.templ.thymeleaf.ThymeleafTemplateEngine;
import io.vertx.sqlclient.PoolOptions;
import io.vertx.sqlclient.SqlConnection;

public class MainVerticle extends AbstractVerticle {

  private int server_port = 8080;

  @Override
  public void start(Promise<Void> startPromise) throws Exception {

    Future<Void> handshake = prepareDatabase().compose(estb -> startServer());
    handshake.onComplete(startPromise);

  }

  private Future<Void> startServer(){
    Promise<Void> promise = Promise.promise();

    Router router = Router.router(vertx);
    HttpServer server = vertx.createHttpServer();
TemplateEngine engine = ThymeleafTemplateEngine.create((Vertx) vertx);
TemplateHandler handler = TemplateHandler.create(engine);
    router.route("/").handler(routingContext -> {
      HttpServerResponse response = routingContext.response();
      response.putHeader("content-type", "text/html").end("<h1>First App</h1>");
    });

    server.requestHandler(router).listen(config().getInteger("http.port", server_port), result -> {
      if(result.succeeded()){
        System.out.println("Server Started at Port '"+server_port+"'");
        promise.complete();
      }
      else{
        System.out.println("Failed to Start Server");
        promise.fail(result.cause());
      }
    });

    return promise.future();
  }

  private Future<Void> prepareDatabase(){
    Promise<Void> promise = Promise.promise();

    MySQLConnectOptions connectOptions = new MySQLConnectOptions()
      .setPort(3306)
      .setHost("localhost")
      .setDatabase("vertx_db")
      .setUser("root")
      .setPassword("");

    PoolOptions poolOptions = new PoolOptions().setMaxSize(5);

    MySQLPool client = MySQLPool.pool(vertx, connectOptions, poolOptions);

    client.getConnection(connect -> {
      if (connect.failed()){
        System.out.println("Failed to Connect to Database.");
        promise.fail(connect.cause());
      }
      else{
        SqlConnection conn = connect.result();
        conn.close();
        System.out.println("Database connection successful.");
        promise.complete();
      }
    });

    return promise.future();
  }
}

Please guide me If you know how to fix. Thanks


Solution

  • Where are you importing the following ...reactivex... classes from? (i.e. which JAR?):

    import io.vertx.reactivex.core.Vertx;
    import io.vertx.reactivex.ext.web.common.template.TemplateEngine;
    import io.vertx.reactivex.ext.web.handler.TemplateHandler;
    import io.vertx.reactivex.ext.web.templ.thymeleaf.ThymeleafTemplateEngine;
    

    It looks as if that JAR contains a class io.vertx.reactivex.core.Vertx which conflicts with the Vertex you need to use: io.vertx.core.Vertx.

    Try removing that JAR from your project (or just from that class, if you need it elsewhere) and then using the following instead (presented as Maven dependencies):

    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-core</artifactId>
        <version>3.9.0</version>
    </dependency>
    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-web</artifactId>
        <version>3.9.0</version>
    </dependency>
    <dependency>
        <groupId>io.vertx</groupId>
        <artifactId>vertx-web-templ-thymeleaf</artifactId>
        <version>3.9.0</version>
    </dependency>
    <dependency>
        [others, as needed - e.g. your SQL dependencies...]
    </dependency>
    

    Then, you should only need to do something like this, to support Thymeleaf templating:

    import io.vertx.ext.web.templ.thymeleaf.ThymeleafTemplateEngine;
    
    ...
    
    final ThymeleafTemplateEngine engine = ThymeleafTemplateEngine.create(vertx);
    

    And then use engine.render() to render your chosen template with its model data.

    There is an example on GitHub here. The example also depends on the Runner class which is here.