Chrisp12138 opened a new issue, #7168:
URL: https://github.com/apache/shenyu/issues/7168

   ## Description
   
   When using the Spring websocket client 
(`shenyu-spring-boot-starter-client-spring-websocket`) in `isFull=true` mode, 
the websocket selector is never created in shenyu-admin and the ws route never 
becomes available. The admin logs an endless 5s retry loop of `selectorDO 
object is null, wait to retry`.
   
   The http (springmvc) client in the same `isFull` mode works, because it 
publishes **both** a `MetaDataRegisterDTO` and a `URIRegisterDTO`. The 
websocket client publishes **only** the `URIRegisterDTO`, while the admin side 
**never creates** a selector from a URI report — it requires the selector to 
already exist.
   
   ## Environment
   
   * ShenYu version(s): 2.7.2-SNAPSHOT (master as of 2026-09), same code paths 
exist in 2.7.0/2.7.1
   * Client: Spring Boot 3.5.x (spring-websocket handler endpoints, **no** 
`@ShenyuServerEndpoint` annotations)
   * Register type: `http` (`shenyu.register.registerType=http`)
   
   ## Steps to reproduce
   
   1. Start shenyu-admin; enable the `websocket` plugin (it is enabled by 
default).
   2. Start a service with `shenyu-spring-boot-starter-client-spring-websocket` 
on the classpath and:
   
   ```yaml
   shenyu:
     register:
       registerType: http
       serverLists: http://127.0.0.1:9095
       props:
         username: admin
         password: 123456
     client:
       websocket:
         props:
           appName: my-service
           contextPath: /my-service
           port: 8101
           protocol: ws://
           isFull: true
   ```
   
   3. Watch the admin log and the `selector` table for plugin `websocket`.
   
   **Actual result:** every ~5 s the admin logs
   
   ```
   Register exception: cause: doRegister Failed to execute, because selectorDO 
object is null, wait to retry.
   ```
   
   and no row is ever created in `selector` for plugin `websocket`. WS 
handshakes through the gateway fail with `{"code":-107,"message":"websocket:Can 
not find selector..."}` (and after a manually pre-created selector, 
`{"code":-102,"message":"websocket:Rule not found!"}` until a rule is also 
created by hand).
   
   ## Root cause
   
   1. `SpringWebSocketClientEventListener#getBeans` — the `isFull` branch 
publishes **only** a `URIRegisterDTO` and returns an empty bean map, so no 
metadata is ever reported:
   
   ```java
   // 
shenyu-client-websocket/shenyu-client-spring-websocket/.../SpringWebSocketClientEventListener.java
   public Map<String, Object> getBeans(final ApplicationContext context) {
       if (Boolean.TRUE.equals(isFull)) {
           if (!markRegistered()) {
               return Collections.emptyMap();
           }
           LOG.info("init spring websocket client success with isFull mode");
           List<String> namespaceIds = super.getNamespace();
           namespaceIds.forEach(namespaceId -> 
getPublisher().publishEvent(buildURIRegisterDTO(context, 
Collections.emptyMap(), namespaceId)));
           return Collections.emptyMap();          // <-- no 
MetaDataRegisterDTO ever published
       }
       ...
   }
   ```
   
   2. On the admin side, a URI report **updates** an existing selector but does 
not create one:
   
   ```java
   // 
shenyu-admin/.../AbstractShenyuClientRegisterServiceImpl.java#doRegisterURI
   SelectorDO selectorDO = 
selectorService.findByNameAndPluginNameAndNamespaceId(selectorName, pluginName, 
namespaceId);
   if (Objects.isNull(selectorDO)) {
       throw new ShenyuException("doRegister Failed to execute, because 
selectorDO object is null, wait to retry.");
   }
   ```
   
   3. The http client's `isFull` branch publishes metadata **and** URI (the 
correct pattern) — see `SpringMvcClientEventListener#getBeans` 
(`publishEvent(MetaDataRegisterDTO.builder()...)` followed by 
`publishEvent(buildURIRegisterDTO(...))`). The websocket client is asymmetric 
with it.
   
   Since no metadata ever arrives, the selector is never created and the 5 s 
`FallbackRegisterTask` retry (unlimited attempts) never converges.
   
   ## Expected result
   
   `isFull=true` on the websocket client should create the websocket selector + 
default rule (context-path based) from a metadata report, and then fill the 
handle from the URI report — exactly like the springmvc client.
   
   ## Suggested fix
   
   In `SpringWebSocketClientEventListener#getBeans` (`isFull` branch), publish 
a `MetaDataRegisterDTO` before the URI report, mirroring 
`SpringMvcClientEventListener`:
   
   ```java
   getPublisher().publishEvent(MetaDataRegisterDTO.builder()
           .appName(getAppName())
           .contextPath(getContextPath())
           .path(contextPath)          // registerContextPath creates selector 
+ default rule
           .rpcType(RpcTypeEnum.WEB_SOCKET.getName())
           .enabled(true)
           .namespaceId(namespaceId)
           .build());
   ```
   
   (Alternatively, `doRegisterURI` could lazily create the selector + default 
rule when missing — but aligning the client with the http client's isFull 
behavior is the smaller, symmetric change.)
   
   ## Workaround we used
   
   Manually pre-create the websocket selector + rule (admin REST), after which 
the pending URI report is accepted and the handle is filled with 
`ws://host:port`.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to