Introduction
I am learning Vert.x recently. As for what it is and what it is useful for, I will update it in the blog when I have almost learned it. In short, it is lighter and faster than SpringBoot. The content of this article is an error encountered in the practice. Record it here and share it with the beginner Vert.x friends who encounter the same problem.
Error Demo Description
This demo is used to practice routing requests and return json response data after processing. Below I created an entity class that contains four attributes. The main error is reported on the attribute of type LocalDateTime.
package demo.module;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
/**
* @author Huhailong
* @Description
* @Date 2022/11/9.
*/
public class UserInfo {
private String username;
private Integer age;
private String gender;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public LocalDateTime getCreateTime() {
return createTime;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
}
The main code of the test route is as follows:
package demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import demo.module.UserInfo;
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.core.json.JsonObject;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import java.time.LocalDateTime;
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
System.setProperty("vertxweb.environment","dev");
HttpServer httpServer = vertx.createHttpServer(); //创建HTTP服务
Router router = Router.router(vertx); //创建路由对象
UserInfo userInfo = new UserInfo();
userInfo.setUsername("huhailong");
userInfo.setAge(26);
userInfo.setGender("man");
userInfo.setCreateTime(LocalDateTime.now());
router.get("/some/path/").respond(ctx-> Future.succeededFuture(new JsonObject().put("hello","world")));
router.get("/some/path2/").respond(ctx-> Future.succeededFuture(userInfo));
httpServer.requestHandler(router).listen(8888);
}
}
In the test demo, I defined two routes. Here I mainly look at the path2 route. It returns a result of serializing UserInfo into JSON. The problem occurs here. The error content is as follows:
十一月 09, 2022 12:28:46 下午 io.vertx.ext.web.RoutingContext
严重: Unhandled exception in router
io.vertx.core.json.EncodeException: Failed to encode as JSON: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to ena
ble handling (through reference chain: demo.module.UserInfo["createTime"])
at io.vertx.core.json.jackson.DatabindCodec.toBuffer(DatabindCodec.java:173)
at io.vertx.core.spi.json.JsonCodec.toBuffer(JsonCodec.java:69)
at io.vertx.core.json.Json.encodeToBuffer(Json.java:60)
at io.vertx.ext.web.RoutingContext.json(RoutingContext.java:752)
at io.vertx.ext.web.Route.lambda$null$0(Route.java:361)
at io.vertx.core.impl.future.SucceededFuture.onSuccess(SucceededFuture.java:64)
at io.vertx.ext.web.Route.lambda$respond$1(Route.java:341)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:173)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:140)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:68)
at io.vertx.ext.web.impl.RouterImpl.handle(RouterImpl.java:37)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:67)
at io.vertx.core.http.impl.Http1xServerRequestHandler.handle(Http1xServerRequestHandler.java:30)
at io.vertx.core.impl.EventLoopContext.emit(EventLoopContext.java:55)
at io.vertx.core.impl.DuplicatedContext.emit(DuplicatedContext.java:158)
at io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:145)
at io.vertx.core.net.impl.ConnectionBase.read(ConnectionBase.java:157)
at io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:153)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
at io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xUpgradeToH2CHandler.channelRead(Http1xUpgradeToH2CHandler.java:116)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:336)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:308)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.vertx.core.http.impl.Http1xOrH2CHandler.end(Http1xOrH2CHandler.java:61)
at io.vertx.core.http.impl.Http1xOrH2CHandler.channelRead(Http1xOrH2CHandler.java:38)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerCon at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerConte
xt.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.jav
a:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerCon
text.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
The error content shows that jackson-datatype-jsr310
dependencies need to be added, but I added it, and this error is still the same.
problem causes
According to online search information, after version 2.13, the serialization of Java8 date/time is no longer supported by default, and then I went to the official website of Vert.x to find that the official solution has been given
Solution
Register time module for ObjectMapper
ObjectMapper mapper = DatabindCodec.mapper();
mapper.registerModule(new JavaTimeModule());
resolved code
package demo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import demo.module.UserInfo;
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.core.json.JsonObject;
import io.vertx.core.json.jackson.DatabindCodec;
import io.vertx.ext.web.Route;
import io.vertx.ext.web.Router;
import java.time.LocalDateTime;
public class MainVerticle extends AbstractVerticle {
@Override
public void start(Promise<Void> startPromise) throws Exception {
System.setProperty("vertxweb.environment","dev");
HttpServer httpServer = vertx.createHttpServer(); //创建HTTP服务
Router router = Router.router(vertx); //创建路由对象
ObjectMapper mapper = DatabindCodec.mapper();
mapper.registerModule(new JavaTimeModule());
UserInfo userInfo = new UserInfo();
userInfo.setUsername("huhailong");
userInfo.setAge(26);
userInfo.setGender("man");
userInfo.setCreateTime(LocalDateTime.now());
router.get("/some/path/").respond(ctx-> Future.succeededFuture(new JsonObject().put("hello","world")));
router.get("/some/path2/").respond(ctx-> Future.succeededFuture(userInfo));
httpServer.requestHandler(router).listen(8888);
}
}
operation result
Summarize
When Vert.x serializes LocalDate or LocalDateTime, it needs to register the date and time module of jsr310 with ObjectMapper to take effect.
Still have to read the official website documentation carefully !!!