如何在 Quarkus 中使用自定义编码器和解码器?
How to use custom Encoder and Decoder in Quarkus?
我有一个 Quarkus 应用程序版本 1.2。0.Final。我有这样的解码器:
public class UuidDecoder implements Decoder.TextStream<UUID>, Decoder, Decoder.Binary<UUID>, Decoder.Text<UUID> {
public UuidDecoder() {
System.out.println("OK!");
}
@Override
public void init(EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public UUID decode(Reader reader) throws DecodeException, IOException {
return UUID.fromString(CharStreams.toString(reader));
}
@Override
public UUID decode(ByteBuffer bytes) throws DecodeException {
return UUID.fromString(new String(bytes.array()));
}
@Override
public boolean willDecode(ByteBuffer bytes) {
try {
UUID.fromString(new String(bytes.array()));
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
@Override
public UUID decode(String s) throws DecodeException {
return UUID.fromString(s);
}
@Override
public boolean willDecode(String s) {
try {
UUID.fromString(s);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
这样的 Websocket 端点:
@ServerEndpoint(value = "/api/ws/search/{id}", decoders = UuidDecoder.class)
public class SearchResource {
private static final Logger LOGGER = Logger.getLogger(SearchResource.class.getName());
@OnOpen
public void onOpen(Session session, @PathParam("id") UUID id) {
LOGGER.info(String.format("We get an open event! ID: %s", id));
}
}
但是,由于某种原因,我无法启动我的应用程序。在日志中:
14:14:57,999 INFO [io.und.web.jsr] UT026003: Adding annotated server endpoint class org.siretch.kafka.entrypoint.SearchResource for path /api/ws/search/{id}
14:14:58,113 ERROR [io.qua.dev.DevModeMain] Failed to start Quarkus: java.lang.ExceptionInInitializerError
at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:193)
at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:182)
at java.base/java.lang.Class.forNameImpl(Native Method)
at java.base/java.lang.Class.forName(Class.java:417)
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:153)
at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:178)
at io.quarkus.dev.DevModeMain.start(DevModeMain.java:96)
at io.quarkus.dev.DevModeMain.main(DevModeMain.java:67)
Caused by: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:390)
... 6 more
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:445)
at io.quarkus.deployment.steps.UndertowBuildStep$build32.deploy_0(UndertowBuildStep$build32.zig:171)
at io.quarkus.deployment.steps.UndertowBuildStep$build32.deploy(UndertowBuildStep$build32.zig:196)
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:376)
... 6 more
Caused by: java.lang.RuntimeException: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:101)
at io.undertow.servlet.core.DeploymentManagerImpl.handleExtensions(DeploymentManagerImpl.java:278)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:155)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:434)
... 9 more
Caused by: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory$BoundPathParameters.<init>(AnnotatedEndpointFactory.java:399)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.createBoundPathParameters(AnnotatedEndpointFactory.java:258)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.create(AnnotatedEndpointFactory.java:100)
at io.undertow.websockets.jsr.ServerWebSocketContainer.addEndpointInternal(ServerWebSocketContainer.java:681)
at io.undertow.websockets.jsr.ServerWebSocketContainer.addEndpoint(ServerWebSocketContainer.java:654)
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:95)
... 12 more
14:14:58,114 INFO [io.qua.dev.DevModeMain] Attempting to start hot replacement endpoint to recover from previous Quarkus startup failure
所以,我的问题是:如何为 URL @PathParam
注册自定义解码器?我认为问题出在 io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.BoundPathParameters#BoundPathParameters
但我不确定我没有做错任何事情。
编辑一:我想用java.util.UUID
class.
有两个原因:
- 添加encoders/decoders时,Quarkus 使用“else if”而不是“if”检查解码器的实现接口;所以你的 class 可能不会实现多个解码器或多个编码器。我filed this as an issue and created a pull request
- 当前的实现(不小心?)忽略了 encoders/decoders 的列表。我filed this as an issue and created a pull request
我有一个 Quarkus 应用程序版本 1.2。0.Final。我有这样的解码器:
public class UuidDecoder implements Decoder.TextStream<UUID>, Decoder, Decoder.Binary<UUID>, Decoder.Text<UUID> {
public UuidDecoder() {
System.out.println("OK!");
}
@Override
public void init(EndpointConfig config) {
}
@Override
public void destroy() {
}
@Override
public UUID decode(Reader reader) throws DecodeException, IOException {
return UUID.fromString(CharStreams.toString(reader));
}
@Override
public UUID decode(ByteBuffer bytes) throws DecodeException {
return UUID.fromString(new String(bytes.array()));
}
@Override
public boolean willDecode(ByteBuffer bytes) {
try {
UUID.fromString(new String(bytes.array()));
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
@Override
public UUID decode(String s) throws DecodeException {
return UUID.fromString(s);
}
@Override
public boolean willDecode(String s) {
try {
UUID.fromString(s);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
这样的 Websocket 端点:
@ServerEndpoint(value = "/api/ws/search/{id}", decoders = UuidDecoder.class)
public class SearchResource {
private static final Logger LOGGER = Logger.getLogger(SearchResource.class.getName());
@OnOpen
public void onOpen(Session session, @PathParam("id") UUID id) {
LOGGER.info(String.format("We get an open event! ID: %s", id));
}
}
但是,由于某种原因,我无法启动我的应用程序。在日志中:
14:14:57,999 INFO [io.und.web.jsr] UT026003: Adding annotated server endpoint class org.siretch.kafka.entrypoint.SearchResource for path /api/ws/search/{id}
14:14:58,113 ERROR [io.qua.dev.DevModeMain] Failed to start Quarkus: java.lang.ExceptionInInitializerError
at java.base/java.lang.J9VMInternals.ensureError(J9VMInternals.java:193)
at java.base/java.lang.J9VMInternals.recordInitializationFailure(J9VMInternals.java:182)
at java.base/java.lang.Class.forNameImpl(Native Method)
at java.base/java.lang.Class.forName(Class.java:417)
at io.quarkus.runner.RuntimeRunner.run(RuntimeRunner.java:153)
at io.quarkus.dev.DevModeMain.doStart(DevModeMain.java:178)
at io.quarkus.dev.DevModeMain.start(DevModeMain.java:96)
at io.quarkus.dev.DevModeMain.main(DevModeMain.java:67)
Caused by: java.lang.RuntimeException: Failed to start quarkus
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:390)
... 6 more
Caused by: java.lang.RuntimeException: java.lang.RuntimeException: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:445)
at io.quarkus.deployment.steps.UndertowBuildStep$build32.deploy_0(UndertowBuildStep$build32.zig:171)
at io.quarkus.deployment.steps.UndertowBuildStep$build32.deploy(UndertowBuildStep$build32.zig:196)
at io.quarkus.runner.ApplicationImpl.<clinit>(ApplicationImpl.zig:376)
... 6 more
Caused by: java.lang.RuntimeException: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:101)
at io.undertow.servlet.core.DeploymentManagerImpl.handleExtensions(DeploymentManagerImpl.java:278)
at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:155)
at io.quarkus.undertow.runtime.UndertowDeploymentRecorder.bootServletContainer(UndertowDeploymentRecorder.java:434)
... 9 more
Caused by: javax.websocket.DeploymentException: UT003028: Could not find decoder for type class java.util.UUID on method public void org.siretch.kafka.entrypoint.SearchResource.onOpen(javax.websocket.Session,java.util.UUID)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory$BoundPathParameters.<init>(AnnotatedEndpointFactory.java:399)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.createBoundPathParameters(AnnotatedEndpointFactory.java:258)
at io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.create(AnnotatedEndpointFactory.java:100)
at io.undertow.websockets.jsr.ServerWebSocketContainer.addEndpointInternal(ServerWebSocketContainer.java:681)
at io.undertow.websockets.jsr.ServerWebSocketContainer.addEndpoint(ServerWebSocketContainer.java:654)
at io.undertow.websockets.jsr.Bootstrap.handleDeployment(Bootstrap.java:95)
... 12 more
14:14:58,114 INFO [io.qua.dev.DevModeMain] Attempting to start hot replacement endpoint to recover from previous Quarkus startup failure
所以,我的问题是:如何为 URL @PathParam
注册自定义解码器?我认为问题出在 io.undertow.websockets.jsr.annotated.AnnotatedEndpointFactory.BoundPathParameters#BoundPathParameters
但我不确定我没有做错任何事情。
编辑一:我想用java.util.UUID
class.
有两个原因:
- 添加encoders/decoders时,Quarkus 使用“else if”而不是“if”检查解码器的实现接口;所以你的 class 可能不会实现多个解码器或多个编码器。我filed this as an issue and created a pull request
- 当前的实现(不小心?)忽略了 encoders/decoders 的列表。我filed this as an issue and created a pull request