LoginSignup
12

More than 5 years have passed since last update.

SpringBoot + Vert.x(3.0.0) + SqlTemplate を試す

Last updated at Posted at 2015-06-24

はじめに

Vert.xのv3がリリースされたので、SpringBootの中からVert.xを使って、Bootiful SQL Template
を利用してみた。ソースはこちら

コンセプト

  • SpringBootを使ってJavaアプリケーションを作成する。
  • Vert.xはSpringBootアプリケーションの中でembeddedの形で使う。

プロジェクト構成

├── pom.xml
└── src
    └── main
        ├── java
        │   └── muraken
        │       └── example
        │           ├── Application.java
        │           ├── HttpServerVerticle.java
        │           ├── SqlTemplateService.java
        │           ├── SqlTemplateVerticle.java
        │           └── entity
        │               ├── Dept.java
        │               └── Emp.java
        └── resources
            ├── application.properties
            ├── data.sql
            ├── schema.sql
            └── sql
                ├── selectAll.sql
                ├── selectByArgs.sql
                ├── selectByEmpno.sql
                └── selectByParam.sql

pom.xml

pom.xmlにはVert.x、SpringBoot、SqlTemplate、Jacksonを追加。
長いので、リンク先参照。

Application.java

Vert.xのVerticleを@Beanで登録してみる。SqlTemplateはJDBCアクセスするblocking codeなので、SqlTemplateをラップするSqlTemplateVerticleはWorkerVerticleとしてdeployする。

Application.java
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {

  @Bean
  SqlTemplate sqlTemplate(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
    return new SqlTemplate(jdbcTemplate, namedParameterJdbcTemplate);
  }

  @Bean
  ObjectMapper jsonMapper() {
    return new ObjectMapper();
  }

  @Bean
  SqlTemplateVerticle sqlTemplateVerticle() {
    return new SqlTemplateVerticle();
  }

  @Bean
  HttpServerVerticle httpServerVerticle() {
    return new HttpServerVerticle();
  }

  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);

    final Vertx vertx = Vertx.vertx();

    vertx.deployVerticle(context.getBean(SqlTemplateVerticle.class), new DeploymentOptions().setWorker(true));
    vertx.deployVerticle(context.getBean(HttpServerVerticle.class));

  }
}

HttpServerVerticle.java

HttpServerを立ち上げて、リクエストが来たらEventBusを使って、SqlTemplateVerticleにメッセージを送信し、レスポンスをそのまま画面に返す。

HttpServerVerticle.java
@Component
public class HttpServerVerticle extends AbstractVerticle {

  public void start() {
    console("start.");

    vertx.createHttpServer().requestHandler(req -> {
      console("Received a http request");

      vertx.eventBus().send("eb.sqltemplate", "findAll req", ar -> {
        if (ar.succeeded()) {
          console("Received reply: " + ar.result().body());
          req.response().end((String) ar.result().body());
        }
      });
    }).listen(8080);
  }

  private void console(String message) {
    System.out.println("[" + Thread.currentThread().getName() + " ] " + getClass().getName() + " : " + message);
  }
}

SqlTemplateVerticle.java

SqlTemplateを利用するSqlTemplateServiceをインジェクションしてもらう。JacksonのObjectMapperもそうしたけど、これはNGかも。
EventBusからメッセージが来たら、SqlTemplateServiceを呼び出して、結果をJSONに変換してリプライを返すようにしている。
Vert.xのJsonObjectは取り回しがやりづらく、結局JSONで扱うなら、Stringでもよいのではないかと。

SqlTemplateVerticle.java
@Component
public class SqlTemplateVerticle extends AbstractVerticle {

  @Autowired
  private SqlTemplateService sqlTemplateService;

  @Autowired
  private ObjectMapper jsonMapper;

  public void start() throws JsonProcessingException {
    console("start.");

    vertx.eventBus().consumer("eb.sqltemplate", message -> {
      console("Received a message: " + message.body());

      List<Emp> emps = this.sqlTemplateService.findAll();

      try {
        String json =this.jsonMapper.writeValueAsString(emps);
        message.reply(json);
      } catch (JsonProcessingException e) {
        e.printStackTrace();
      }
    });
  }

  private void console(String message) {
    System.out.println("[" + Thread.currentThread().getName() + " ] " + getClass().getName() + " : " + message);
  }
}

SqlTemplateService.java

こちらはBootiful SQL Templateから抜粋で拝借。 2Way SQLですよ。

SqlTemplateService.java
@Component
public class SqlTemplateService {
  @Autowired
  SqlTemplate template;

  public List<Emp> findAll() {
    return template.forList("sql/selectAll.sql", Emp.class);
  }
}

実行

通常のJavaアプリケーションとして実行できる。Java8が必要。
実行したらlocalhosto:8080にアクセスする。

mvn package

java -jar target/springboot-vertx-example-1.0.0.jar

起動すると SqlTemplateVerticleがWorkerThreadで、HttpServerVerticleがEventLoopThreadで動作しているのが分かる。

2015-06-25 00:27:00.858  INFO 73715 --- [           main] muraken.example.Application              : Started Application in 4.783 seconds (JVM running for 6.034)
[vert.x-worker-thread-0 ] muraken.example.SqlTemplateVerticle : start.
[vert.x-eventloop-thread-4 ] muraken.example.HttpServerVerticle : start.

続けてlocalhost:8080にアクセスすると次のようになる。

[vert.x-eventloop-thread-4 ] muraken.example.HttpServerVerticle : Received a http request
[vert.x-worker-thread-1 ] muraken.example.SqlTemplateVerticle : Received a message: findAll req
2015-06-25 00:28:38.357 DEBUG 73715 --- [worker-thread-1] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2015-06-25 00:28:38.358 DEBUG 73715 --- [worker-thread-1] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [select
    *
from
    emp]
[vert.x-eventloop-thread-4 ] muraken.example.HttpServerVerticle : Received reply: [{"empno":7369,"ename":"SMITH","job":"CLERK","mgr":7902,"hiredate":345826800000,"sal":800.0,"comm":null},{"empno":7499,"ename":"ALLEN","job":"SALESMAN","mgr":7698,"hiredate":351442800000,"sal":1600.0,"comm":300.0},{"empno":7521,"ename":"WARD","job":"SALESMAN","mgr":7698,"hiredate":351615600000,"sal":1250.0,"comm":500.0},{"empno":7566,"ename":"JONES","job":"MANAGER","mgr":7839,"hiredate":354985200000,"sal":2975.0,"comm":null},{"empno":7654,"ename":"MARTIN","job":"SALESMAN","mgr":7698,"hiredate":370450800000,"sal":1250.0,"comm":1400.0},{"empno":7698,"ename":"BLAKE","job":"MANAGER","mgr":7839,"hiredate":352220400000,"sal":2850.0,"comm":null},{"empno":7782,"ename":"CLARK","job":"MANAGER","mgr":7839,"hiredate":347814000000,"sal":2450.0,"comm":null},{"empno":7788,"ename":"SCOTT","job":"ANALYST","mgr":7566,"hiredate":408207600000,"sal":3000.0,"comm":null},{"empno":7839,"ename":"KING","job":"PRESIDENT","mgr":null,"hiredate":374770800000,"sal":5000.0,"comm":null},{"empno":7844,"ename":"TURNER","job":"SALESMAN","mgr":7698,"hiredate":368722800000,"sal":1500.0,"comm":0.0},{"empno":7876,"ename":"ADAMS","job":"CLERK","mgr":7788,"hiredate":411145200000,"sal":1100.0,"comm":null},{"empno":7900,"ename":"JAMES","job":"CLERK","mgr":7698,"hiredate":376153200000,"sal":950.0,"comm":null},{"empno":7902,"ename":"FORD","job":"ANALYST","mgr":7566,"hiredate":376153200000,"sal":3000.0,"comm":null},{"empno":7934,"ename":"MILLER","job":"CLERK","mgr":7782,"hiredate":380559600000,"sal":1300.0,"comm":null}]

何回かブラウザでアクセスすると、HttpServerVerticleは常にvert.x-eventloop-thread-4で動作するのに対して、SqlTemplateVerticleはvert.x-worker-thread-1の1の部分が、2, 3, 4...となり、スレッドが変わることが分かる。

感想

  • Vert.x v3のリリースおめでとうございます!
  • SpringBoot、data.sqlとschema.sqlが超便利!(そこ?)
  • EventBusを使ってnon blockingな非同期メッセージング処理が簡単に書ける
  • 今回やってないけど、cluster組むのもEventBusがあるから簡単。
  • Bootiful SQL Template2Way SQLで 堅くて良いよね。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12