From cf3d8616f86bf9a4ff68d691e362e272956b96d0 Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 22:49:43 +0100 Subject: [PATCH 1/4] Simplify AnnotatedEndpointFactory --- .../annotated/AnnotatedEndpointFactory.java | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java index 7664c748c..6006c1a50 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java @@ -75,7 +75,6 @@ private AnnotatedEndpointFactory(final Class endpointClass, final BoundMethod public static AnnotatedEndpointFactory create(final Class endpointClass, final EncodingFactory encodingFactory, final Set paths) throws DeploymentException { - final Set> found = new HashSet<>(); BoundMethod onOpen = null; BoundMethod onClose = null; BoundMethod onError = null; @@ -87,40 +86,37 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina do { for (final Method method : c.getDeclaredMethods()) { if (method.isAnnotationPresent(OnOpen.class)) { - if (found.contains(OnOpen.class)) { + if (onOpen != null) { if(!onOpen.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnOpen.class); } else { continue; } } - found.add(OnOpen.class); onOpen = new BoundMethod(method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, EndpointConfig.class, true), createBoundPathParameters(method, paths, endpointClass)); } if (method.isAnnotationPresent(OnClose.class)) { - if (found.contains(OnClose.class)) { + if (onClose != null) { if(!onClose.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnClose.class); } else { continue; } } - found.add(OnClose.class); onClose = new BoundMethod(method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, CloseReason.class, true), createBoundPathParameters(method, paths, endpointClass)); } if (method.isAnnotationPresent(OnError.class)) { - if (found.contains(OnError.class)) { + if (onError != null) { if(!onError.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnError.class); } else { continue; } } - found.add(OnError.class); onError = new BoundMethod(method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, Throwable.class, false), createBoundPathParameters(method, paths, endpointClass)); @@ -365,25 +361,21 @@ public Class getType() { */ private static class BoundPathParameters implements BoundParameter { - private final Class endpointClass; - private final Set paths; private final String[] positions; private final Encoding[] encoders; private final Class[] types; BoundPathParameters(final String[] positions, final Method method, Class endpointClass, Set paths) throws DeploymentException { this.positions = positions; - this.endpointClass = endpointClass; - this.paths = paths; this.encoders = new Encoding[positions.length]; this.types = new Class[positions.length]; for (int i = 0; i < positions.length; ++i) { Class type = method.getParameterTypes()[i]; Annotation[] annotations = method.getParameterAnnotations()[i]; - for(int j = 0; j < annotations.length; ++j) { - if(annotations[j] instanceof PathParam) { - PathParam param = (PathParam) annotations[j]; - if(!paths.contains(param.value())) { + for (Annotation annotation : annotations) { + if (annotation instanceof PathParam) { + PathParam param = (PathParam) annotation; + if (!paths.contains(param.value())) { JsrWebSocketLogger.ROOT_LOGGER.pathTemplateNotFound(endpointClass, param, method, paths); } } From 8403f588b68b74ee1610613153ad27095850a91a Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 22:56:19 +0100 Subject: [PATCH 2/4] Format source code --- .../annotated/AnnotatedEndpointFactory.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java index 6006c1a50..1af4e15a7 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java @@ -87,7 +87,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina for (final Method method : c.getDeclaredMethods()) { if (method.isAnnotationPresent(OnOpen.class)) { if (onOpen != null) { - if(!onOpen.overrides(method)) { + if (!onOpen.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnOpen.class); } else { continue; @@ -99,7 +99,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } if (method.isAnnotationPresent(OnClose.class)) { if (onClose != null) { - if(!onClose.overrides(method)) { + if (!onClose.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnClose.class); } else { continue; @@ -111,7 +111,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } if (method.isAnnotationPresent(OnError.class)) { if (onError != null) { - if(!onError.overrides(method)) { + if (!onError.overrides(method)) { throw JsrWebSocketMessages.MESSAGES.moreThanOneAnnotation(OnError.class); } else { continue; @@ -121,14 +121,14 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina new BoundSingleParameter(method, Throwable.class, false), createBoundPathParameters(method, paths, endpointClass)); } - if (method.isAnnotationPresent(OnMessage.class) && ! method.isBridge()) { - if(binaryMessage != null && binaryMessage.overrides(method)) { + if (method.isAnnotationPresent(OnMessage.class) && !method.isBridge()) { + if (binaryMessage != null && binaryMessage.overrides(method)) { continue; } - if(textMessage != null && textMessage.overrides(method)) { + if (textMessage != null && textMessage.overrides(method)) { continue; } - if(pongMessage != null && pongMessage.overrides(method)) { + if (pongMessage != null && pongMessage.overrides(method)) { continue; } long maxMessageSize = method.getAnnotation(OnMessage.class).maxMessageSize(); @@ -142,7 +142,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } final Class param = parameterTypes[i]; - if(param == boolean.class || param == Boolean.class) { + if (param == boolean.class || param == Boolean.class) { booleanLocation = i; } else if (encodingFactory.canDecodeText(param)) { if (textMessage != null) { @@ -286,7 +286,7 @@ private static boolean hasAnnotation(Class annotationType, } public AnnotatedEndpoint createInstance(InstanceHandle endpointInstance) { - if(!endpointClass.isInstance(endpointInstance.getInstance())) { + if (!endpointClass.isInstance(endpointInstance.getInstance())) { throw JsrWebSocketMessages.MESSAGES.endpointNotOfCorrectType(endpointInstance, endpointClass); } return new AnnotatedEndpoint(endpointInstance, OnOpen, OnClose, OnError, textMessage, binaryMessage, pongMessage); From 7c93d8e86e7c0628185e1ab6a680c3b7e69870d0 Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 23:20:53 +0100 Subject: [PATCH 3/4] Respect endpoint encoders/decoders for path parameters `PathParameters` could only make use of the default encoding factory, which allows primitive and String types. With this change, custom encoders/decoders are considered, too. Fixes GH-52 --- .../jsr/ServerWebSocketContainer.java | 45 ++++++++++--------- .../annotated/AnnotatedEndpointFactory.java | 36 +++++++-------- .../test/annotated/AnnotatedEndpointTest.java | 1 + .../jsr/test/annotated/UuidEndpoint.java | 44 ++++++++++++++++++ 4 files changed, 86 insertions(+), 40 deletions(-) create mode 100644 websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/ServerWebSocketContainer.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/ServerWebSocketContainer.java index be5e76c78..6f65bb0fc 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/ServerWebSocketContainer.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/ServerWebSocketContainer.java @@ -463,7 +463,7 @@ public InstanceHandle createInstance() throws InstantiationException { AnnotatedEndpointFactory annotatedEndpointFactory = null; if (!Endpoint.class.isAssignableFrom(sec.getEndpointClass())) { - annotatedEndpointFactory = AnnotatedEndpointFactory.create(sec.getEndpointClass(), encodingFactory, pt.getParameterNames()); + annotatedEndpointFactory = AnnotatedEndpointFactory.create(sec.getEndpointClass(), encodingFactory, pt.getParameterNames(), config); } @@ -686,24 +686,6 @@ private synchronized void addEndpointInternal(final Class endpoint, boolean r seenPaths.add(template); Class configuratorClass = serverEndpoint.configurator(); - EncodingFactory encodingFactory = EncodingFactory.createFactory(classIntrospecter, serverEndpoint.decoders(), serverEndpoint.encoders()); - AnnotatedEndpointFactory annotatedEndpointFactory = AnnotatedEndpointFactory.create(endpoint, encodingFactory, template.getParameterNames()); - InstanceFactory instanceFactory = null; - try { - instanceFactory = classIntrospecter.createInstanceFactory(endpoint); - } catch (Exception e) { - //so it is possible that this is still valid if a custom configurator is in use - if (configuratorClass == ServerEndpointConfig.Configurator.class) { - throw JsrWebSocketMessages.MESSAGES.couldNotDeploy(e); - } else { - instanceFactory = new InstanceFactory() { - @Override - public InstanceHandle createInstance() throws InstantiationException { - throw JsrWebSocketMessages.MESSAGES.endpointDoesNotHaveAppropriateConstructor(endpoint); - } - }; - } - } ServerEndpointConfig.Configurator configurator; if (configuratorClass != ServerEndpointConfig.Configurator.class) { try { @@ -719,10 +701,28 @@ public InstanceHandle createInstance() throws InstantiationException { .decoders(Arrays.asList(serverEndpoint.decoders())) .encoders(Arrays.asList(serverEndpoint.encoders())) .subprotocols(Arrays.asList(serverEndpoint.subprotocols())) - .extensions(Collections.emptyList()) + .extensions(Collections.emptyList()) .configurator(configurator) .build(); + EncodingFactory encodingFactory = EncodingFactory.createFactory(classIntrospecter, serverEndpoint.decoders(), serverEndpoint.encoders()); + AnnotatedEndpointFactory annotatedEndpointFactory = AnnotatedEndpointFactory.create(endpoint, encodingFactory, template.getParameterNames(), config); + InstanceFactory instanceFactory = null; + try { + instanceFactory = classIntrospecter.createInstanceFactory(endpoint); + } catch (Exception e) { + //so it is possible that this is still valid if a custom configurator is in use + if (configuratorClass == ServerEndpointConfig.Configurator.class) { + throw JsrWebSocketMessages.MESSAGES.couldNotDeploy(e); + } else { + instanceFactory = new InstanceFactory() { + @Override + public InstanceHandle createInstance() throws InstantiationException { + throw JsrWebSocketMessages.MESSAGES.endpointDoesNotHaveAppropriateConstructor(endpoint); + } + }; + } + } ConfiguredServerEndpoint confguredServerEndpoint = new ConfiguredServerEndpoint(config, instanceFactory, template, encodingFactory, annotatedEndpointFactory, installedExtensions); configuredServerEndpoints.add(confguredServerEndpoint); @@ -749,7 +749,6 @@ public InstanceHandle createInstance() throws InstantiationException { } } } - AnnotatedEndpointFactory factory = AnnotatedEndpointFactory.create(endpoint, encodingFactory, Collections.emptySet()); ClientEndpointConfig.Configurator configurator = null; try { @@ -764,6 +763,8 @@ public InstanceHandle createInstance() throws InstantiationException { .configurator(configurator) .build(); + AnnotatedEndpointFactory factory = AnnotatedEndpointFactory.create(endpoint, encodingFactory, Collections.emptySet(), config); + ConfiguredClientEndpoint configuredClientEndpoint = new ConfiguredClientEndpoint(config, factory, encodingFactory, instanceFactory); clientEndpoints.put(endpoint, configuredClientEndpoint); } else { @@ -803,7 +804,7 @@ public void addEndpoint(final ServerEndpointConfig endpoint) throws DeploymentEx AnnotatedEndpointFactory annotatedEndpointFactory = null; if (!Endpoint.class.isAssignableFrom(endpoint.getEndpointClass())) { // We may want to check that the path in @ServerEndpoint matches the specified path, and throw if they are not equivalent - annotatedEndpointFactory = AnnotatedEndpointFactory.create(endpoint.getEndpointClass(), encodingFactory, template.getParameterNames()); + annotatedEndpointFactory = AnnotatedEndpointFactory.create(endpoint.getEndpointClass(), encodingFactory, template.getParameterNames(), endpoint); } ConfiguredServerEndpoint confguredServerEndpoint = new ConfiguredServerEndpoint(endpoint, null, template, encodingFactory, annotatedEndpointFactory, endpoint.getExtensions()); configuredServerEndpoints.add(confguredServerEndpoint); diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java index 1af4e15a7..8b8580813 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java @@ -74,7 +74,7 @@ private AnnotatedEndpointFactory(final Class endpointClass, final BoundMethod } - public static AnnotatedEndpointFactory create(final Class endpointClass, final EncodingFactory encodingFactory, final Set paths) throws DeploymentException { + public static AnnotatedEndpointFactory create(final Class endpointClass, final EncodingFactory encodingFactory, final Set paths, final EndpointConfig endpointConfig) throws DeploymentException { BoundMethod onOpen = null; BoundMethod onClose = null; BoundMethod onError = null; @@ -95,7 +95,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } onOpen = new BoundMethod(method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, EndpointConfig.class, true), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); } if (method.isAnnotationPresent(OnClose.class)) { if (onClose != null) { @@ -107,7 +107,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } onClose = new BoundMethod(method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, CloseReason.class, true), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); } if (method.isAnnotationPresent(OnError.class)) { if (onError != null) { @@ -119,7 +119,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } onError = new BoundMethod(method, null, false, 0, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, Throwable.class, false), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); } if (method.isAnnotationPresent(OnMessage.class) && !method.isBridge()) { if (binaryMessage != null && binaryMessage.overrides(method)) { @@ -150,7 +150,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } textMessage = new BoundMethod(method, param, true, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(i, param), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; } else if (encodingFactory.canDecodeBinary(param)) { @@ -159,7 +159,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina } binaryMessage = new BoundMethod(method, param, true, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(i, param), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; } else if (param.equals(byte[].class)) { @@ -169,7 +169,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina binaryMessage = new BoundMethod(method, byte[].class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, byte[].class), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; } else if (param.equals(ByteBuffer.class)) { @@ -180,7 +180,7 @@ public static AnnotatedEndpointFactory create(final Class endpointClass, fina maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, ByteBuffer.class), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; @@ -191,7 +191,7 @@ maxMessageSize, new BoundSingleParameter(method, Session.class, true), binaryMessage = new BoundMethod(method, InputStream.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(i, InputStream.class), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; @@ -202,7 +202,7 @@ maxMessageSize, new BoundSingleParameter(method, Session.class, true), textMessage = new BoundMethod(method, String.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(i, String.class), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; @@ -213,7 +213,7 @@ maxMessageSize, new BoundSingleParameter(method, Session.class, true), textMessage = new BoundMethod(method, Reader.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(i, Reader.class), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; @@ -223,7 +223,7 @@ maxMessageSize, new BoundSingleParameter(method, Session.class, true), } pongMessage = new BoundMethod(method, PongMessage.class, false, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(i, PongMessage.class), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; break; } @@ -237,7 +237,7 @@ maxMessageSize, new BoundSingleParameter(method, Session.class, true), textMessage = new BoundMethod(method, boolClass, true, maxMessageSize, new BoundSingleParameter(method, Session.class, true), new BoundSingleParameter(method, boolean.class, true), new BoundSingleParameter(booleanLocation, boolClass), - createBoundPathParameters(method, paths, endpointClass)); + createBoundPathParameters(method, paths, endpointClass, encodingFactory, endpointConfig)); messageHandled = true; } if (!messageHandled) { @@ -250,8 +250,8 @@ maxMessageSize, new BoundSingleParameter(method, Session.class, true), return new AnnotatedEndpointFactory(endpointClass, onOpen, onClose, onError, textMessage, binaryMessage, pongMessage); } - private static BoundPathParameters createBoundPathParameters(final Method method, Set paths, Class endpointClass) throws DeploymentException { - return new BoundPathParameters(pathParams(method), method, endpointClass, paths); + private static BoundPathParameters createBoundPathParameters(final Method method, Set paths, Class endpointClass, final EncodingFactory encodingFactory, final EndpointConfig endpointConfig) throws DeploymentException { + return new BoundPathParameters(pathParams(method), method, endpointClass, paths, encodingFactory, endpointConfig); } @@ -365,7 +365,7 @@ private static class BoundPathParameters implements BoundParameter { private final Encoding[] encoders; private final Class[] types; - BoundPathParameters(final String[] positions, final Method method, Class endpointClass, Set paths) throws DeploymentException { + BoundPathParameters(final String[] positions, final Method method, Class endpointClass, Set paths, final EncodingFactory encodingFactory, final EndpointConfig endpointConfig) throws DeploymentException { this.positions = positions; this.encoders = new Encoding[positions.length]; this.types = new Class[positions.length]; @@ -383,8 +383,8 @@ private static class BoundPathParameters implements BoundParameter { if (positions[i] == null || type == null || type == String.class) { continue; } - if (EncodingFactory.DEFAULT.canEncodeText(type)) { - encoders[i] = EncodingFactory.DEFAULT.createEncoding(EmptyEndpointConfig.INSTANCE); + if (encodingFactory.canEncodeText(type)) { + encoders[i] = encodingFactory.createEncoding(endpointConfig); types[i] = type; } else { diff --git a/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/AnnotatedEndpointTest.java b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/AnnotatedEndpointTest.java index 1d94407ee..bce29d6fe 100644 --- a/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/AnnotatedEndpointTest.java +++ b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/AnnotatedEndpointTest.java @@ -87,6 +87,7 @@ public static void setup() throws Exception { .addEndpoint(AnnotatedClientEndpoint.class) .addEndpoint(AnnotatedClientEndpointWithConfigurator.class) .addEndpoint(IncrementEndpoint.class) + .addEndpoint(UuidEndpoint.class) .addEndpoint(EncodingEndpoint.class) .addEndpoint(EncodingGenericsEndpoint.class) .addEndpoint(TimeoutEndpoint.class) diff --git a/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java new file mode 100644 index 000000000..f11239bd8 --- /dev/null +++ b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java @@ -0,0 +1,44 @@ +/* + * JBoss, Home of Professional Open Source. + * Copyright 2014 Red Hat, Inc., and individual contributors + * as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.undertow.websockets.jsr.test.annotated; + +import javax.websocket.EndpointConfig; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; +import javax.websocket.Session; +import javax.websocket.server.PathParam; +import javax.websocket.server.ServerEndpoint; +import java.util.UUID; + +@ServerEndpoint("/uuid/{id}") +public class UuidEndpoint { + + UUID id; + + @OnOpen + public void open(Session session, EndpointConfig config, @PathParam("id") UUID id) { + this.id = id; + } + + @OnMessage + public String handleMessage(String message) { + return message + id; + } + +} From 693c30cecbf0a4328345f4eeaf076af0d89359df Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Mon, 8 Feb 2021 19:08:06 +0100 Subject: [PATCH 4/4] Fix decoding of non-text values I'm not sure how this worked for other decoders, but calling `canEncodeText()` when decoding a value seems wrong. --- .../annotated/AnnotatedEndpointFactory.java | 2 +- .../jsr/test/annotated/UuidDecoder.java | 33 +++++++++++++++++++ .../jsr/test/annotated/UuidEndpoint.java | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidDecoder.java diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java index 8b8580813..888623b5b 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/annotated/AnnotatedEndpointFactory.java @@ -383,7 +383,7 @@ private static class BoundPathParameters implements BoundParameter { if (positions[i] == null || type == null || type == String.class) { continue; } - if (encodingFactory.canEncodeText(type)) { + if (encodingFactory.canDecodeText(type)) { encoders[i] = encodingFactory.createEncoding(endpointConfig); types[i] = type; diff --git a/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidDecoder.java b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidDecoder.java new file mode 100644 index 000000000..9e89c0f04 --- /dev/null +++ b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidDecoder.java @@ -0,0 +1,33 @@ +package io.undertow.websockets.jsr.test.annotated; + +import javax.websocket.Decoder; +import javax.websocket.EndpointConfig; +import java.util.UUID; + +public class UuidDecoder implements Decoder.Text { + + @Override + public void init(EndpointConfig config) { + + } + + @Override + public void destroy() { + + } + + @Override + public UUID decode(String s) { + return UUID.fromString(s); + } + + @Override + public boolean willDecode(String s) { + try { + UUID.fromString(s); + return true; + } catch (IllegalArgumentException e) { + return false; + } + } +} \ No newline at end of file diff --git a/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java index f11239bd8..4a4f044d8 100644 --- a/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java +++ b/websockets-jsr/src/test/java/io/undertow/websockets/jsr/test/annotated/UuidEndpoint.java @@ -26,7 +26,7 @@ import javax.websocket.server.ServerEndpoint; import java.util.UUID; -@ServerEndpoint("/uuid/{id}") +@ServerEndpoint(value = "/uuid/{id}", decoders = UuidDecoder.class) public class UuidEndpoint { UUID id;