Skip to content

[BUG][Java Client] Automatic port detection returns 0 after an embedded server binds a random port #8426

Open

Description

@Aias00

Is there an existing issue for this?

  • I have searched the existing issues and relevant migration work.

Current Behavior

With a started Spring Boot embedded Tomcat configured for port 0, the Java client's automatic port helper returns the configured value 0 rather than the actual bound port. A real embedded-server probe printed:

server.port=0: actual-bound-port=57737, client-detected-port=0

The selected port varies per run. The client-detected zero is the defect.

PortUtils.findPort reflects getPort() on the web-server factory, whose configured port remains 0. It returns immediately, so the legacy fallback does not correct the result. SpringMvcClientEventListener.getPort and ClientRegisterConfigImpl.getPort consume this helper for automatic address selection.

Expected Behavior

After the owned server has bound, register its actual reachable port. Obtain it from the appropriate server lifecycle/context instead of assuming a factory's configured value is the runtime endpoint. Keep a positive explicitly configured advertised port authoritative where the existing configuration contract requires it.

Steps To Reproduce

Build the core and its dependencies with Java 17 from the repository root:

./mvnw -B -ntp -pl shenyu-client/shenyu-client-core -am test   -Dtest=PortUtilsTest -Dsurefire.failIfNoSpecifiedTests=false

Save the following as /tmp/ClientBoundPortProbe.java:

import org.apache.shenyu.client.core.utils.PortUtils;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;

public final class ClientBoundPortProbe {
    public static void main(String[] args) {
        ServletWebServerApplicationContext context = new ServletWebServerApplicationContext();
        TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
        context.registerBean("servletWebServerFactory", TomcatServletWebServerFactory.class, () -> factory);
        try {
            context.refresh();
            int bound = context.getWebServer().getPort();
            int detected = PortUtils.findPort(context.getBeanFactory());
            System.out.println("actual-bound-port=" + bound + ", client-detected-port=" + detected);
            if (bound <= 0 || detected != 0) {
                throw new AssertionError("Unexpected reproduction result");
            }
        } finally {
            context.close();
        }
    }
}

Compile/run against the Surefire classpath produced by that command:

python3 - <<'PYPROBE'
import os
from pathlib import Path
import subprocess
import xml.etree.ElementTree as ET

report = Path('shenyu-client/shenyu-client-core/target/surefire-reports/TEST-org.apache.shenyu.client.core.utils.PortUtilsTest.xml')
properties = {p.attrib['name']: p.attrib['value'] for p in ET.parse(report).findall('./properties/property')}
classpath = properties['java.class.path']
output = Path('/tmp/shenyu-client-port-classes')
output.mkdir(exist_ok=True)
java_bin = Path(os.environ['JAVA_HOME']) / 'bin'
subprocess.run([str(java_bin / 'javac'), '-cp', classpath, '-d', str(output), '/tmp/ClientBoundPortProbe.java'], check=True)
subprocess.run([str(java_bin / 'java'), '-cp', str(output) + os.pathsep + classpath, 'ClientBoundPortProbe'], check=True)
PYPROBE

Acceptance Criteria

  • A real embedded server with server.port=0 supplies its actual positive bound port to the registration path, and a request through bootstrap reaches that instance.
  • Cover both the legacy listener and opt-in registrar path where supported; include a static-port control and a positive advertised-port override.
  • Registration waits for the correct server/context to initialize. A management port or another application context must not be selected accidentally; no default/zero port is silently treated as a usable address.
  • Preserve the documented external-container behavior and clearly diagnose unsupported/ambiguous connector selection. Test each container/framework combination the fix claims to support.
  • Ensure discovered endpoints also feed heartbeat/offline identities consistently; do not fix only the printed metadata or change the registration wire format unnecessarily.

Environment and Validation Limits

ShenYu 2.7.3-SNAPSHOT, main 9dd9a12fb7c64e8a0e26449caa906fe562350dca, Java 17, repository-managed Spring Boot 3.3.1 / embedded Tomcat 10.1.25, macOS. The real-server helper probe above reproduced the mismatch; it did not execute a full Admin/bootstrap registration deployment. The existing PortUtilsTest checks a factory's default 8080 without starting a server and does not exercise this boundary.

Related: historical #4575 was closed as a question, but the mismatch is reproduced on the current reviewed implementation. This report is scoped to the confirmed HTTP port-discovery path and does not assert a separately reproduced Dubbo failure. Track migration compatibility under #7602/#6366 and sync the eventual fix into the accepted shenyu-client-java candidate.

Activity

  1. konlue commented on Nov 11, 2026

    @konlue
    Contributor

    /assign

  2. added 4 commits that reference this issue on Nov 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

type: bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions