This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 4f90bff128c6cb39bd0ebb8cf1eb6565229dcf86
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue May 4 17:02:38 2021 +0100

    First part of fix for BZ 65262. Make WebSocket more IoC friendly
    
    This first part tackles the Endpoints. Endpoint instance creation has
    been refactored and will now run through the InstanceManger for object
    creation where possible. Where that isn't possible, the objects will
    continue to be registered with the InstanceManager.
    
    https://bz.apache.org/bugzilla/show_bug.cgi?id=65262
---
 .../tomcat/websocket/ClientEndpointHolder.java     | 27 +++++++
 .../tomcat/websocket/EndpointClassHolder.java      | 57 ++++++++++++++
 .../apache/tomcat/websocket/EndpointHolder.java    | 56 ++++++++++++++
 .../tomcat/websocket/LocalStrings.properties       |  5 +-
 .../tomcat/websocket/LocalStrings_fr.properties    |  1 -
 .../tomcat/websocket/LocalStrings_ja.properties    |  1 -
 .../tomcat/websocket/LocalStrings_ko.properties    |  1 -
 .../tomcat/websocket/LocalStrings_zh_CN.properties |  1 -
 .../apache/tomcat/websocket/PojoClassHolder.java   | 63 +++++++++++++++
 java/org/apache/tomcat/websocket/PojoHolder.java   | 60 +++++++++++++++
 java/org/apache/tomcat/websocket/WsSession.java    | 84 +++++++++++++-------
 .../tomcat/websocket/WsWebSocketContainer.java     | 90 +++++++++-------------
 .../tomcat/websocket/pojo/LocalStrings.properties  |  2 -
 .../websocket/pojo/LocalStrings_cs.properties      |  2 -
 .../websocket/pojo/LocalStrings_de.properties      |  2 -
 .../websocket/pojo/LocalStrings_es.properties      |  2 -
 .../websocket/pojo/LocalStrings_fr.properties      |  2 -
 .../websocket/pojo/LocalStrings_ja.properties      |  2 -
 .../websocket/pojo/LocalStrings_ko.properties      |  2 -
 .../websocket/pojo/LocalStrings_zh_CN.properties   |  2 -
 .../tomcat/websocket/pojo/PojoEndpointServer.java  | 19 +----
 webapps/docs/changelog.xml                         |  5 ++
 22 files changed, 368 insertions(+), 118 deletions(-)

diff --git a/java/org/apache/tomcat/websocket/ClientEndpointHolder.java 
b/java/org/apache/tomcat/websocket/ClientEndpointHolder.java
new file mode 100644
index 0000000..d3334d1
--- /dev/null
+++ b/java/org/apache/tomcat/websocket/ClientEndpointHolder.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomcat.websocket;
+
+import jakarta.websocket.DeploymentException;
+import jakarta.websocket.Endpoint;
+
+import org.apache.tomcat.InstanceManager;
+
+public interface ClientEndpointHolder {
+    String getClassName();
+    Endpoint getInstance(InstanceManager instanceManager) throws 
DeploymentException;
+}
diff --git a/java/org/apache/tomcat/websocket/EndpointClassHolder.java 
b/java/org/apache/tomcat/websocket/EndpointClassHolder.java
new file mode 100644
index 0000000..7a2cf21
--- /dev/null
+++ b/java/org/apache/tomcat/websocket/EndpointClassHolder.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomcat.websocket;
+
+import javax.naming.NamingException;
+
+import jakarta.websocket.DeploymentException;
+import jakarta.websocket.Endpoint;
+
+import org.apache.tomcat.InstanceManager;
+import org.apache.tomcat.util.res.StringManager;
+
+public class EndpointClassHolder implements ClientEndpointHolder {
+
+    private static final StringManager sm = 
StringManager.getManager(EndpointClassHolder.class);
+
+    private final Class<? extends Endpoint> clazz;
+
+
+    public EndpointClassHolder(Class<? extends Endpoint> clazz) {
+        this.clazz = clazz;
+    }
+
+
+    @Override
+    public String getClassName() {
+        return clazz.getName();
+    }
+
+
+    @Override
+    public Endpoint getInstance(InstanceManager instanceManager) throws 
DeploymentException {
+        try {
+            if (instanceManager == null) {
+                return clazz.getConstructor().newInstance();
+            } else {
+                return (Endpoint) instanceManager.newInstance(clazz);
+            }
+        } catch (ReflectiveOperationException | NamingException e) {
+            throw new 
DeploymentException(sm.getString("clientEndpointHolder.instanceCreationFailed"),
 e);
+        }
+    }
+}
diff --git a/java/org/apache/tomcat/websocket/EndpointHolder.java 
b/java/org/apache/tomcat/websocket/EndpointHolder.java
new file mode 100644
index 0000000..dcf9a9a
--- /dev/null
+++ b/java/org/apache/tomcat/websocket/EndpointHolder.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomcat.websocket;
+
+import javax.naming.NamingException;
+
+import jakarta.websocket.DeploymentException;
+import jakarta.websocket.Endpoint;
+
+import org.apache.tomcat.InstanceManager;
+import org.apache.tomcat.util.res.StringManager;
+
+public class EndpointHolder implements ClientEndpointHolder {
+
+    private static final StringManager sm = 
StringManager.getManager(EndpointHolder.class);
+
+    private final Endpoint endpoint;
+
+
+    public EndpointHolder(Endpoint endpoint) {
+        this.endpoint = endpoint;
+    }
+
+
+    @Override
+    public String getClassName() {
+        return endpoint.getClass().getName();
+    }
+
+
+    @Override
+    public Endpoint getInstance(InstanceManager instanceManager) throws 
DeploymentException {
+        if (instanceManager != null) {
+            try {
+                instanceManager.newInstance(endpoint);
+            } catch (ReflectiveOperationException | NamingException e) {
+                throw new 
DeploymentException(sm.getString("clientEndpointHolder.instanceRegistrationFailed"),
 e);
+            }
+        }
+        return endpoint;
+    }
+}
diff --git a/java/org/apache/tomcat/websocket/LocalStrings.properties 
b/java/org/apache/tomcat/websocket/LocalStrings.properties
index 67630ba..3ee86ae 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings.properties
@@ -33,6 +33,9 @@ backgroundProcessManager.processFailed=A background process 
failed
 
 caseInsensitiveKeyMap.nullKey=Null keys are not permitted
 
+clientEndpointHolder.instanceCreationFailed=Failed to create WebSocketEndpoint
+clientEndpointHolder.instanceRegistrationFailed=Failed to register Endpoint 
instance with the InstanceManager
+
 futureToSendHandler.timeout=Operation timed out after waiting [{0}] [{1}] to 
complete
 
 perMessageDeflate.alreadyClosed=The transformer has been closed and may no 
longer be used
@@ -114,6 +117,7 @@ wsSession.duplicateHandlerBinary=A binary message handler 
has already been confi
 wsSession.duplicateHandlerPong=A pong message handler has already been 
configured
 wsSession.duplicateHandlerText=A text message handler has already been 
configured
 wsSession.flushFailOnClose=Failed to flush batched messages on session close
+wsSession.instanceCreateFailed=Endpoint instance creation failed
 wsSession.instanceNew=Endpoint instance registration failed
 wsSession.invalidHandlerTypePong=A pong message handler must implement 
MessageHandler.Whole
 wsSession.messageFailed=Unable to write the complete message as the WebSocket 
connection has been closed
@@ -132,7 +136,6 @@ wsWebSocketContainer.asynchronousSocketChannelFail=Unable 
to open a connection t
 wsWebSocketContainer.connect.entry=Connecting endpoint instance of type [{0}] 
to [{1}]
 wsWebSocketContainer.connect.write=Writing the HTTP upgrade request from 
buffer starting at [{0}] with a limit of [{1}] from local address [{2}]
 wsWebSocketContainer.defaultConfiguratorFail=Failed to create the default 
configurator
-wsWebSocketContainer.endpointCreateFail=Failed to create a local endpoint of 
type [{0}]
 wsWebSocketContainer.failedAuthentication=Failed to handle HTTP response code 
[{0}]. Authentication header was not accepted by server.
 wsWebSocketContainer.httpRequestFailed=The HTTP request to initiate the 
WebSocket connection to [{0}] failed
 wsWebSocketContainer.invalidExtensionParameters=The server responded with 
extension parameters the client is unable to support
diff --git a/java/org/apache/tomcat/websocket/LocalStrings_fr.properties 
b/java/org/apache/tomcat/websocket/LocalStrings_fr.properties
index 0a8d5e8..4d12b3c 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings_fr.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings_fr.properties
@@ -117,7 +117,6 @@ 
wsWebSocketContainer.asynchronousSocketChannelFail=Impossible d'ouvrir une conne
 wsWebSocketContainer.connect.entry=Connection à l''instance d''endpoint de 
type [{0}] à [{1}]
 wsWebSocketContainer.connect.write=Ecriture de la requête d''upgrade HTTP 
depuis le tampon à partir de [{0}] avec une limite de [{1}] depuis l''adresse 
locale [{2}]
 wsWebSocketContainer.defaultConfiguratorFail=Impossible de créer le 
configurateur par défaut
-wsWebSocketContainer.endpointCreateFail=Echec de création d''un point 
d''entrée local de type [{0}]
 wsWebSocketContainer.failedAuthentication=Echec du traitement du code de 
réponse HTTP [{0}], l''en-tête d''authentification n''a pas été accepté par le 
serveur
 wsWebSocketContainer.httpRequestFailed=La requête HTTP pour initier la 
connection WebSocket a échoué
 wsWebSocketContainer.invalidExtensionParameters=Le serveur a répondu avec des 
paramètres d'extension que le client n'est pas capable de traiter
diff --git a/java/org/apache/tomcat/websocket/LocalStrings_ja.properties 
b/java/org/apache/tomcat/websocket/LocalStrings_ja.properties
index 912995a..daf9dc8 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings_ja.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings_ja.properties
@@ -117,7 +117,6 @@ wsWebSocketContainer.asynchronousSocketChannelFail=サーバーへの接続を
 wsWebSocketContainer.connect.entry=タイプ[{0}]のエンドポイントインスタンスを[{1}]に接続しています
 
wsWebSocketContainer.connect.write=ローカルアドレス[{2}]から[{1}]の制限で[{0}]から始まるバッファからHTTPアップグレードリクエストを書き込んでいます
 wsWebSocketContainer.defaultConfiguratorFail=既定のコンフィグレータ生成に失敗しました。
-wsWebSocketContainer.endpointCreateFail=クラス [{0}] のローカルエンドポイントを作成できません。
 wsWebSocketContainer.failedAuthentication=HTTP応答コード[{0}]を処理できませんでした。 
認証ヘッダーがサーバーによって受け入れられませんでした。
 wsWebSocketContainer.httpRequestFailed=WebSocket接続を開始するHTTPリクエストが失敗しました。
 
wsWebSocketContainer.invalidExtensionParameters=サーバーはクライアントの解釈できない拡張パラメーターで応答しました。
diff --git a/java/org/apache/tomcat/websocket/LocalStrings_ko.properties 
b/java/org/apache/tomcat/websocket/LocalStrings_ko.properties
index 1bf4f1f..096ddd2 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings_ko.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings_ko.properties
@@ -117,7 +117,6 @@ wsWebSocketContainer.asynchronousSocketChannelFail=서버에 대한 
연결을 
 wsWebSocketContainer.connect.entry=타입이 [{0}]인 엔드포인트 인스턴스를 [{1}]에 연결합니다.
 wsWebSocketContainer.connect.write=로컬 주소 [{2}](으)로부터, 시작 위치 [{0}], 최대 길이 
[{1}]의 데이터를 버퍼에 씁니다.
 wsWebSocketContainer.defaultConfiguratorFail=기본 Configurator를 생성하지 못했습니다.
-wsWebSocketContainer.endpointCreateFail=타입이 [{0}]인 로컬 엔드포인트를 생성하지 못했습니다.
 wsWebSocketContainer.failedAuthentication=HTTP 응답 코드 [{0}]을(를) 처리하지 못했습니다. 인증 
헤더가 서버에 의해 받아들여지지 않았습니다.
 wsWebSocketContainer.httpRequestFailed=웹소켓 연결을 초기화하기 위한 HTTP 요청이 실패했습니다.
 wsWebSocketContainer.invalidExtensionParameters=서버가, 클라이언트가 지원할 수 없는 확장 파라미터들과 
함께 응답했습니다.
diff --git a/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties 
b/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties
index 71b16d6..9a06489 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings_zh_CN.properties
@@ -115,7 +115,6 @@ wsSession.unknownHandlerType=无法添加消息处理程序[{0}],因为它被
 wsWebSocketContainer.asynchronousSocketChannelFail=无法打开与服务器的连接
 wsWebSocketContainer.connect.entry=连接[{0}]类型的终端实例至[{1}]
 wsWebSocketContainer.defaultConfiguratorFail=无法创建默认配置程序。
-wsWebSocketContainer.endpointCreateFail=未能创建类型为[{0}]的本地终结点
 wsWebSocketContainer.failedAuthentication=无法处理http响应代码[{0}]。服务器不接受身份验证头。
 wsWebSocketContainer.httpRequestFailed=启动WebSocket连接的HTTP请求失败
 wsWebSocketContainer.invalidExtensionParameters=服务器用客户端无法支持的扩展参数响应
diff --git a/java/org/apache/tomcat/websocket/PojoClassHolder.java 
b/java/org/apache/tomcat/websocket/PojoClassHolder.java
new file mode 100644
index 0000000..e2c1da8
--- /dev/null
+++ b/java/org/apache/tomcat/websocket/PojoClassHolder.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomcat.websocket;
+
+import javax.naming.NamingException;
+
+import jakarta.websocket.ClientEndpointConfig;
+import jakarta.websocket.DeploymentException;
+import jakarta.websocket.Endpoint;
+
+import org.apache.tomcat.InstanceManager;
+import org.apache.tomcat.util.res.StringManager;
+import org.apache.tomcat.websocket.pojo.PojoEndpointClient;
+
+public class PojoClassHolder implements ClientEndpointHolder {
+
+    private static final StringManager sm = 
StringManager.getManager(PojoClassHolder.class);
+
+    private final Class<?> pojoClazz;
+    private final ClientEndpointConfig clientEndpointConfig;
+
+
+    public PojoClassHolder(Class<?> pojoClazz, ClientEndpointConfig 
clientEndpointConfig) {
+        this.pojoClazz = pojoClazz;
+        this.clientEndpointConfig = clientEndpointConfig;
+    }
+
+
+    @Override
+    public String getClassName() {
+        return pojoClazz.getName();
+    }
+
+    @Override
+    public Endpoint getInstance(InstanceManager instanceManager) throws 
DeploymentException {
+        try {
+            Object pojo;
+            if (instanceManager == null) {
+                pojo = pojoClazz.getConstructor().newInstance();
+            } else {
+                pojo = instanceManager.newInstance(pojoClazz);
+            }
+            return new PojoEndpointClient(pojo, 
clientEndpointConfig.getDecoders());
+        } catch (ReflectiveOperationException | SecurityException | 
NamingException e) {
+            throw new 
DeploymentException(sm.getString("clientEndpointHolder.instanceCreationFailed"),
 e);
+        }
+    }
+
+}
diff --git a/java/org/apache/tomcat/websocket/PojoHolder.java 
b/java/org/apache/tomcat/websocket/PojoHolder.java
new file mode 100644
index 0000000..7195944
--- /dev/null
+++ b/java/org/apache/tomcat/websocket/PojoHolder.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.tomcat.websocket;
+
+import javax.naming.NamingException;
+
+import jakarta.websocket.ClientEndpointConfig;
+import jakarta.websocket.DeploymentException;
+import jakarta.websocket.Endpoint;
+
+import org.apache.tomcat.InstanceManager;
+import org.apache.tomcat.util.res.StringManager;
+import org.apache.tomcat.websocket.pojo.PojoEndpointClient;
+
+public class PojoHolder implements ClientEndpointHolder {
+
+    private static final StringManager sm = 
StringManager.getManager(PojoHolder.class);
+
+    private final Object pojo;
+    private final ClientEndpointConfig clientEndpointConfig;
+
+
+    public PojoHolder(Object pojo, ClientEndpointConfig clientEndpointConfig) {
+        this.pojo = pojo;
+        this.clientEndpointConfig = clientEndpointConfig;
+    }
+
+
+    @Override
+    public String getClassName() {
+        return pojo.getClass().getName();
+    }
+
+
+    @Override
+    public Endpoint getInstance(InstanceManager instanceManager) throws 
DeploymentException {
+        if (instanceManager != null) {
+            try {
+                instanceManager.newInstance(pojo);
+            } catch (ReflectiveOperationException | NamingException e) {
+                throw new 
DeploymentException(sm.getString("clientEndpointHolder.instanceRegistrationFailed"),
 e);
+            }
+        }
+        return new PojoEndpointClient(pojo, 
clientEndpointConfig.getDecoders());
+    }
+}
diff --git a/java/org/apache/tomcat/websocket/WsSession.java 
b/java/org/apache/tomcat/websocket/WsSession.java
index 2085cb3..4c71d84 100644
--- a/java/org/apache/tomcat/websocket/WsSession.java
+++ b/java/org/apache/tomcat/websocket/WsSession.java
@@ -30,6 +30,8 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 
+import javax.naming.NamingException;
+
 import jakarta.websocket.ClientEndpointConfig;
 import jakarta.websocket.CloseReason;
 import jakarta.websocket.CloseReason.CloseCode;
@@ -47,6 +49,7 @@ import jakarta.websocket.SendResult;
 import jakarta.websocket.Session;
 import jakarta.websocket.WebSocketContainer;
 import jakarta.websocket.server.ServerEndpointConfig;
+import jakarta.websocket.server.ServerEndpointConfig.Configurator;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
@@ -55,19 +58,29 @@ import org.apache.tomcat.InstanceManagerBindings;
 import org.apache.tomcat.util.ExceptionUtils;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.websocket.pojo.PojoEndpointServer;
+import org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator;
 
 public class WsSession implements Session {
 
+    private final Log log = LogFactory.getLog(WsSession.class); // must not be 
static
+    private static final StringManager sm = 
StringManager.getManager(WsSession.class);
+
     // An ellipsis is a single character that looks like three periods in a row
     // and is used to indicate a continuation.
     private static final byte[] ELLIPSIS_BYTES = 
"\u2026".getBytes(StandardCharsets.UTF_8);
     // An ellipsis is three bytes in UTF-8
     private static final int ELLIPSIS_BYTES_LEN = ELLIPSIS_BYTES.length;
 
-    private static final StringManager sm = 
StringManager.getManager(WsSession.class);
+    private static final boolean SEC_CONFIGURATOR_USES_IMPL_DEFAULT;
+
     private static AtomicLong ids = new AtomicLong(0);
 
-    private final Log log = LogFactory.getLog(WsSession.class); // must not be 
static
+    static {
+        ServerEndpointConfig.Builder builder = 
ServerEndpointConfig.Builder.create(null, null);
+        ServerEndpointConfig sec = builder.build();
+        SEC_CONFIGURATOR_USES_IMPL_DEFAULT =
+                
sec.getConfigurator().getClass().equals(DefaultServerEndpointConfigurator.class);
+    }
 
     private final Endpoint localEndpoint;
     private final WsRemoteEndpointImplBase wsRemoteEndpoint;
@@ -111,7 +124,7 @@ public class WsSession implements Session {
      * called will be used when calling
      * {@link Endpoint#onClose(Session, CloseReason)}.
      *
-     * @param localEndpoint        The end point managed by this code
+     * @param clientEndpointHolder The end point managed by this code
      * @param wsRemoteEndpoint     The other / remote end point
      * @param wsWebSocketContainer The container that created this session
      * @param negotiatedExtensions The agreed extensions to use for this 
session
@@ -126,12 +139,11 @@ public class WsSession implements Session {
      *                             end point
      * @throws DeploymentException if an invalid encode is specified
      */
-    public WsSession(Endpoint localEndpoint,
+    public WsSession(ClientEndpointHolder clientEndpointHolder,
             WsRemoteEndpointImplBase wsRemoteEndpoint,
             WsWebSocketContainer wsWebSocketContainer,
             List<Extension> negotiatedExtensions, String subProtocol, 
Map<String, String> pathParameters,
             boolean secure, ClientEndpointConfig clientEndpointConfig) throws 
DeploymentException {
-        this.localEndpoint = localEndpoint;
         this.wsRemoteEndpoint = wsRemoteEndpoint;
         this.wsRemoteEndpoint.setSession(this);
         this.remoteEndpointAsync = new WsRemoteEndpointAsync(wsRemoteEndpoint);
@@ -165,13 +177,8 @@ public class WsSession implements Session {
         if (instanceManager == null) {
             instanceManager = 
InstanceManagerBindings.get(applicationClassLoader);
         }
-        if (instanceManager != null) {
-            try {
-                instanceManager.newInstance(localEndpoint);
-            } catch (Exception e) {
-                throw new 
DeploymentException(sm.getString("wsSession.instanceNew"), e);
-            }
-        }
+
+        this.localEndpoint = clientEndpointHolder.getInstance(instanceManager);
 
         if (log.isDebugEnabled()) {
             log.debug(sm.getString("wsSession.created", id));
@@ -221,17 +228,6 @@ public class WsSession implements Session {
             List<Extension> negotiatedExtensions, String subProtocol, 
Map<String, String> pathParameters,
             boolean secure, ServerEndpointConfig serverEndpointConfig) throws 
DeploymentException {
 
-        try {
-            Class<?> clazz = serverEndpointConfig.getEndpointClass();
-            if (Endpoint.class.isAssignableFrom(clazz)) {
-                this.localEndpoint = (Endpoint) 
serverEndpointConfig.getConfigurator().getEndpointInstance(clazz);
-            } else {
-                this.localEndpoint = new PojoEndpointServer(pathParameters);
-            }
-        } catch (InstantiationException e) {
-            throw new 
DeploymentException(sm.getString("wsSession.instanceNew"), e);
-        }
-
         this.wsRemoteEndpoint = wsRemoteEndpoint;
         this.wsRemoteEndpoint.setSession(this);
         this.remoteEndpointAsync = new WsRemoteEndpointAsync(wsRemoteEndpoint);
@@ -269,12 +265,32 @@ public class WsSession implements Session {
         if (instanceManager == null) {
             instanceManager = 
InstanceManagerBindings.get(applicationClassLoader);
         }
-        if (instanceManager != null) {
-            try {
-                instanceManager.newInstance(localEndpoint);
-            } catch (Exception e) {
-                throw new 
DeploymentException(sm.getString("wsSession.instanceNew"), e);
+
+        Configurator configurator = serverEndpointConfig.getConfigurator();
+        Class<?> clazz = serverEndpointConfig.getEndpointClass();
+
+        Object endpointInstance;
+        try {
+            if (instanceManager == null || 
!isDefaultConfigurator(configurator)) {
+                endpointInstance = configurator.getEndpointInstance(clazz);
+                if (instanceManager != null) {
+                    try {
+                        instanceManager.newInstance(endpointInstance);
+                    } catch (ReflectiveOperationException | NamingException e) 
{
+                        throw new 
DeploymentException(sm.getString("wsSession.instanceNew"), e);
+                    }
+                }
+            } else {
+                endpointInstance = instanceManager.newInstance(clazz);
             }
+        } catch (ReflectiveOperationException | NamingException e) {
+            throw new 
DeploymentException(sm.getString("wsSession.instanceCreateFailed"), e);
+        }
+
+        if (endpointInstance instanceof Endpoint) {
+            this.localEndpoint = (Endpoint) endpointInstance;
+        } else {
+            this.localEndpoint = new PojoEndpointServer(pathParameters, 
endpointInstance);
         }
 
         if (log.isDebugEnabled()) {
@@ -283,6 +299,18 @@ public class WsSession implements Session {
     }
 
 
+    private boolean isDefaultConfigurator(Configurator configurator) {
+        if 
(configurator.getClass().equals(DefaultServerEndpointConfigurator.class)) {
+            return true;
+        }
+        if (SEC_CONFIGURATOR_USES_IMPL_DEFAULT &&
+                
configurator.getClass().equals(ServerEndpointConfig.Configurator.class)) {
+            return true;
+        }
+        return false;
+    }
+
+
     /**
      * Creates a new WebSocket session for communication between the two
      * provided end points. The result of {@link 
Thread#getContextClassLoader()}
diff --git a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java 
b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
index 71d2f70..aee1994 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -74,7 +74,6 @@ import org.apache.tomcat.util.codec.binary.Base64;
 import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;
 import org.apache.tomcat.util.res.StringManager;
 import org.apache.tomcat.util.security.KeyStoreUtil;
-import org.apache.tomcat.websocket.pojo.PojoEndpointClient;
 
 public class WsWebSocketContainer implements WebSocketContainer, 
BackgroundProcess {
 
@@ -115,19 +114,30 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
     }
 
     @Override
-    public Session connectToServer(Object pojo, URI path)
-            throws DeploymentException {
+    public Session connectToServer(Object pojo, URI path) throws 
DeploymentException {
+        ClientEndpointConfig config = 
createClientEndpointConfig(pojo.getClass());
+        ClientEndpointHolder holder = new PojoHolder(pojo, config);
+        return connectToServerRecursive(holder, config, path, new HashSet<>());
+    }
+
+
+    @Override
+    public Session connectToServer(Class<?> annotatedEndpointClass, URI path) 
throws DeploymentException {
+        ClientEndpointConfig config = 
createClientEndpointConfig(annotatedEndpointClass);
+        ClientEndpointHolder holder = new 
PojoClassHolder(annotatedEndpointClass, config);
+        return connectToServerRecursive(holder, config, path, new HashSet<>());
+    }
+
 
-        ClientEndpoint annotation =
-                pojo.getClass().getAnnotation(ClientEndpoint.class);
+    private ClientEndpointConfig createClientEndpointConfig(Class<?> 
annotatedEndpointClass)
+            throws DeploymentException {
+        ClientEndpoint annotation = 
annotatedEndpointClass.getAnnotation(ClientEndpoint.class);
         if (annotation == null) {
             throw new DeploymentException(
                     sm.getString("wsWebSocketContainer.missingAnnotation",
-                            pojo.getClass().getName()));
+                            annotatedEndpointClass.getName()));
         }
 
-        Endpoint ep = new PojoEndpointClient(pojo, 
Arrays.asList(annotation.decoders()));
-
         Class<? extends ClientEndpointConfig.Configurator> configuratorClazz =
                 annotation.configurator();
 
@@ -152,59 +162,33 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
                 encoders(Arrays.asList(annotation.encoders())).
                 
preferredSubprotocols(Arrays.asList(annotation.subprotocols())).
                 build();
-        return connectToServer(ep, config, path);
-    }
 
-
-    @Override
-    public Session connectToServer(Class<?> annotatedEndpointClass, URI path)
-            throws DeploymentException {
-
-        Object pojo;
-        try {
-            pojo = annotatedEndpointClass.getConstructor().newInstance();
-        } catch (ReflectiveOperationException e) {
-            throw new DeploymentException(sm.getString(
-                    "wsWebSocketContainer.endpointCreateFail",
-                    annotatedEndpointClass.getName()), e);
-        }
-
-        return connectToServer(pojo, path);
+        return config;
     }
 
 
     @Override
-    public Session connectToServer(Class<? extends Endpoint> clazz,
-            ClientEndpointConfig clientEndpointConfiguration, URI path)
-            throws DeploymentException {
-
-        Endpoint endpoint;
-        try {
-            endpoint = clazz.getConstructor().newInstance();
-        } catch (ReflectiveOperationException e) {
-            throw new DeploymentException(sm.getString(
-                    "wsWebSocketContainer.endpointCreateFail", 
clazz.getName()),
-                    e);
-        }
-
-        return connectToServer(endpoint, clientEndpointConfiguration, path);
+    public Session connectToServer(Class<? extends Endpoint> clazz, 
ClientEndpointConfig clientEndpointConfiguration,
+            URI path) throws DeploymentException {
+        ClientEndpointHolder holder = new EndpointClassHolder(clazz);
+        return connectToServerRecursive(holder, clientEndpointConfiguration, 
path, new HashSet<>());
     }
 
 
     @Override
-    public Session connectToServer(Endpoint endpoint,
-            ClientEndpointConfig clientEndpointConfiguration, URI path)
+    public Session connectToServer(Endpoint endpoint, ClientEndpointConfig 
clientEndpointConfiguration, URI path)
             throws DeploymentException {
-        return connectToServerRecursive(endpoint, clientEndpointConfiguration, 
path, new HashSet<>());
+        ClientEndpointHolder holder = new EndpointHolder(endpoint);
+        return connectToServerRecursive(holder, clientEndpointConfiguration, 
path, new HashSet<>());
     }
 
-    private Session connectToServerRecursive(Endpoint endpoint,
-            ClientEndpointConfig clientEndpointConfiguration, URI path,
-            Set<URI> redirectSet)
+
+    private Session connectToServerRecursive(ClientEndpointHolder 
clientEndpointHolder,
+            ClientEndpointConfig clientEndpointConfiguration, URI path, 
Set<URI> redirectSet)
             throws DeploymentException {
 
         if (log.isDebugEnabled()) {
-            log.debug(sm.getString("wsWebSocketContainer.connect.entry", 
endpoint.getClass().getName(), path));
+            log.debug(sm.getString("wsWebSocketContainer.connect.entry", 
clientEndpointHolder.getClassName(), path));
         }
 
         boolean secure = false;
@@ -398,7 +382,8 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
                                 Integer.toString(maxRedirects)));
                     }
 
-                    return connectToServerRecursive(endpoint, 
clientEndpointConfiguration, redirectLocation, redirectSet);
+                    return connectToServerRecursive(
+                            clientEndpointHolder, clientEndpointConfiguration, 
redirectLocation, redirectSet);
 
                 }
 
@@ -435,7 +420,8 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
                     userProperties.put(Constants.AUTHORIZATION_HEADER_NAME, 
auth.getAuthorization(
                             requestUri, wwwAuthenticateHeaders.get(0), 
userProperties));
 
-                    return connectToServerRecursive(endpoint, 
clientEndpointConfiguration, path, redirectSet);
+                    return connectToServerRecursive(
+                            clientEndpointHolder, clientEndpointConfiguration, 
path, redirectSet);
 
                 } else {
                     throw new 
DeploymentException(sm.getString("wsWebSocketContainer.invalidStatus",
@@ -506,8 +492,8 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
         // Switch to WebSocket
         WsRemoteEndpointImplClient wsRemoteEndpointClient = new 
WsRemoteEndpointImplClient(channel);
 
-        WsSession wsSession = new WsSession(endpoint, wsRemoteEndpointClient, 
this, extensionsAgreed, subProtocol,
-                Collections.<String,String>emptyMap(), secure, 
clientEndpointConfiguration);
+        WsSession wsSession = new WsSession(clientEndpointHolder, 
wsRemoteEndpointClient, this, extensionsAgreed,
+                subProtocol, Collections.<String,String>emptyMap(), secure, 
clientEndpointConfiguration);
 
         WsFrameClient wsFrameClient = new WsFrameClient(response, channel,
                 wsSession, transformation);
@@ -515,8 +501,8 @@ public class WsWebSocketContainer implements 
WebSocketContainer, BackgroundProce
         // completed transformation chain to the remote end point.
         
wsRemoteEndpointClient.setTransformation(wsFrameClient.getTransformation());
 
-        endpoint.onOpen(wsSession, clientEndpointConfiguration);
-        registerSession(endpoint, wsSession);
+        wsSession.getLocal().onOpen(wsSession, clientEndpointConfiguration);
+        registerSession(wsSession.getLocal(), wsSession);
 
         /* It is possible that the server sent one or more messages as soon as
          * the WebSocket connection was established. Depending on the exact
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties
index bca550d..50b47c3 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties
@@ -19,8 +19,6 @@ pojoEndpointBase.onError=No error handling configured for 
[{0}] and the followin
 pojoEndpointBase.onErrorFail=Failed to call onError method of POJO end point 
for POJO of type [{0}]
 pojoEndpointBase.onOpenFail=Failed to call onOpen method of POJO end point for 
POJO of type [{0}]
 
-pojoEndpointServer.getPojoInstanceFail=Failed to create instance of POJO of 
type [{0}]
-
 pojoMessageHandlerWhole.decodeIoFail=IO error while decoding message
 pojoMessageHandlerWhole.maxBufferSize=The maximum supported message size for 
this implementation is Integer.MAX_VALUE
 
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings_cs.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_cs.properties
index b2c8a29..f0bd452 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_cs.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_cs.properties
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-pojoEndpointServer.getPojoInstanceFail=Vytvoření POJO instance typu [{0}] 
selhalo
-
 pojoMethodMapping.duplicateAnnotation=Duplicitní anotace [{0}] přítomná na 
třídě [{1}]
 pojoMethodMapping.duplicatePongMessageParam=Více PongMessage parametrů 
přitomnýcn na metodě [{0}] třídy [{1}], která byla označena anotací OnMessage
 pojoMethodMapping.invalidDecoder=Nelze vytvořit instanci specifikovaného 
dekodéru typu [{0}]
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings_de.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_de.properties
index 26a684a..2bdc86e 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_de.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_de.properties
@@ -13,8 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-pojoEndpointServer.getPojoInstanceFail=Es konnte keine POJO Instanz des Typs 
[{0}] erzeugt werden
-
 pojoMethodMapping.duplicateAnnotation=Doppelte Annotation [{0}] an Klasse 
[{1}] gefunden
 pojoMethodMapping.duplicateLastParam=Es sind mehrere Boolean (letzte) 
Parameter für die Methode [{0}] der Klasse [{1}], die mit OnMessage annotiert 
ist, vorhanden.
 pojoMethodMapping.invalidDecoder=Der angegeben Dekoder vom Typ [{0}] konnte 
nicht instanziiert werden
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings_es.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_es.properties
index bbef800..0c385fb 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_es.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_es.properties
@@ -16,8 +16,6 @@
 pojoEndpointBase.onCloseFail=Fallo al llamar el método onClose del endpoint 
POJO para el tipo POJO [{0}]
 pojoEndpointBase.onOpenFail=Fallo al llamar el método onOpen del end point 
POJO para el tipo POJO [{0}]\n
 
-pojoEndpointServer.getPojoInstanceFail=Fallo al crear la instancia POJO de 
tipo [{0}]\n
-
 pojoMethodMapping.duplicateAnnotation=Anotaciones duplicadas [{0}] presente en 
la clase [{1}]\n
 pojoMethodMapping.duplicatePongMessageParam=Varios parámetros de  PongMessage  
estan presentes en el método [{0}] de la clase [{1}] que fue anotado con 
OnMessage
 pojoMethodMapping.invalidDecoder=El decodificador especificado de tipo [{0}]  
no puede ser instanciado\n
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings_fr.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_fr.properties
index 186ee96..806ef3f 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_fr.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_fr.properties
@@ -19,8 +19,6 @@ pojoEndpointBase.onError=Aucun gestionnaire d''erreur n''est 
configuré pour [{0
 pojoEndpointBase.onErrorFail=Echec de l''appel de la méthode onError du point 
de terminaison POJO pour le type [{0}]
 pojoEndpointBase.onOpenFail=Impossible d’appeler la méthode onOpen du point de 
terminaison POJO de type [{0}]
 
-pojoEndpointServer.getPojoInstanceFail=Échec de création d''une instance de 
POJO de type [{0}]
-
 pojoMessageHandlerWhole.decodeIoFail=Erreur d'IO lors du décodage du message
 pojoMessageHandlerWhole.maxBufferSize=La taille maximale de message supportée 
par cette implémentation est Integer.MAX_VALUE
 
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings_ja.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_ja.properties
index e28e5e3..35da058 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_ja.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_ja.properties
@@ -19,8 +19,6 @@ pojoEndpointBase.onError=[{0}]に対してエラー処理が構成されてお
 pojoEndpointBase.onErrorFail=タイプ[{0}]のPOJOのPOJOエンドポイントのonErrorメソッドの呼び出しに失敗しました
 pojoEndpointBase.onOpenFail=タイプ[{0}]のPOJOのPOJOエンドポイントのonOpenメソッドの呼び出しに失敗しました。
 
-pojoEndpointServer.getPojoInstanceFail=POJO クラス [{0}] をインスタンス化できませんでした。
-
 pojoMessageHandlerWhole.decodeIoFail=メッセージの復号中に入出力エラーが発生しました。
 pojoMessageHandlerWhole.maxBufferSize=この実装で対応可能なメッセージサイズの上限値は 
Integer.MAX_VALUE です。
 
diff --git a/java/org/apache/tomcat/websocket/pojo/LocalStrings_ko.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_ko.properties
index 78174c8..052eb0d 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_ko.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_ko.properties
@@ -19,8 +19,6 @@ pojoEndpointBase.onError=[{0}]을(를) 위한 오류 핸들링이 설정되지 
 pojoEndpointBase.onErrorFail=타입이 [{0}]인 POJO를 위한 POJO 엔드포인트의 onError를 호출하지 
못했습니다.
 pojoEndpointBase.onOpenFail=타입이 [{0}]인 POJO를 위한, POJO 엔드포인트의 onOpen 메소드를 호출하지 
못했습니다.
 
-pojoEndpointServer.getPojoInstanceFail=타입이 [{0}]인 POJO 인스턴스를 생성하지 못했습니다.
-
 pojoMessageHandlerWhole.decodeIoFail=메시지를 디코딩하는 중 IO 오류 발생
 pojoMessageHandlerWhole.maxBufferSize=이 구현을 위해 지원되는 최대 메시지 크기는 
Integer.MAX_VALUE입니다.
 
diff --git 
a/java/org/apache/tomcat/websocket/pojo/LocalStrings_zh_CN.properties 
b/java/org/apache/tomcat/websocket/pojo/LocalStrings_zh_CN.properties
index 3147f4a..ae9909b 100644
--- a/java/org/apache/tomcat/websocket/pojo/LocalStrings_zh_CN.properties
+++ b/java/org/apache/tomcat/websocket/pojo/LocalStrings_zh_CN.properties
@@ -19,8 +19,6 @@ pojoEndpointBase.onError=在错误发生后,没有为[{0}]配置错误处理
 pojoEndpointBase.onErrorFail=无法为类型为[{0}]的POJO调用POJO端点的onError方法
 pojoEndpointBase.onOpenFail=无法为类型为[{0}]的POJO调用POJO端点的onOpen方法
 
-pojoEndpointServer.getPojoInstanceFail=创建类型为 [{0}] 的 POJO 实例失败
-
 pojoMessageHandlerWhole.decodeIoFail=解码消息时出现IO错误
 pojoMessageHandlerWhole.maxBufferSize=此实现支持的最大消息大小为Integer.MAX_VALUE
 
diff --git a/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java 
b/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java
index 2549d55..e91e10b 100644
--- a/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java
+++ b/java/org/apache/tomcat/websocket/pojo/PojoEndpointServer.java
@@ -22,8 +22,6 @@ import jakarta.websocket.EndpointConfig;
 import jakarta.websocket.Session;
 import jakarta.websocket.server.ServerEndpointConfig;
 
-import org.apache.tomcat.util.res.StringManager;
-
 /**
  * Wrapper class for instances of POJOs annotated with
  * {@link jakarta.websocket.server.ServerEndpoint} so they appear as standard
@@ -31,11 +29,9 @@ import org.apache.tomcat.util.res.StringManager;
  */
 public class PojoEndpointServer extends PojoEndpointBase {
 
-    private static final StringManager sm = 
StringManager.getManager(PojoEndpointServer.class);
-
-
-    public PojoEndpointServer(Map<String,String> pathParameters) {
+    public PojoEndpointServer(Map<String,String> pathParameters, Object pojo) {
         super(pathParameters);
+        setPojo(pojo);
     }
 
 
@@ -44,17 +40,6 @@ public class PojoEndpointServer extends PojoEndpointBase {
 
         ServerEndpointConfig sec = (ServerEndpointConfig) endpointConfig;
 
-        Object pojo;
-        try {
-            pojo = sec.getConfigurator().getEndpointInstance(
-                    sec.getEndpointClass());
-        } catch (InstantiationException e) {
-            throw new IllegalArgumentException(sm.getString(
-                    "pojoEndpointServer.getPojoInstanceFail",
-                    sec.getEndpointClass().getName()), e);
-        }
-        setPojo(pojo);
-
         PojoMethodMapping methodMapping =
                 (PojoMethodMapping) sec.getUserProperties().get(
                         Constants.POJO_METHOD_MAPPING_KEY);
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 00ee7d5..391caaf 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -172,6 +172,11 @@
         Refactor the way Tomcat passes path parameters to POJO end points to
         simplify the code. (markt)
       </scode>
+      <fix>
+        <bug>65262</bug>: Refactor the creation of WebSocket end point 
instances
+        to be more IoC friendly. Instances are now created via the
+        <code>InstanceManager</code> where possible. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Web applications">

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to