はじめに
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する。
@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にメッセージを送信し、レスポンスをそのまま画面に返す。
@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でもよいのではないかと。
@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ですよ。
@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 Templateは
2Way SQLで堅くて良いよね。