From 8f2a09b531e763c0ebb7882ac1213665c5b9c15d Mon Sep 17 00:00:00 2001 From: hengyuss <1183660933@qq.com> Date: Sat, 5 Sep 2026 15:49:03 +0800 Subject: [PATCH 1/3] fix: make shenyu-examples-mcp work normally --- .../ShenyuClientRegisterEventPublisher.java | 14 ++++++++++---- ...henyuClientRegisterEventPublisherTest.java | 6 +++++- shenyu-examples/pom.xml | 2 +- .../ShenyuTestMcpApplication.java | 2 +- .../controller/OrderController.java | 4 ++-- .../shenyu/{ => examples}/dto/OrderDTO.java | 2 +- .../src/main/resources/application.yml | 2 -- .../server/callback/ShenyuToolCallback.java | 5 ++++- .../callback/ShenyuToolCallbackTest.java | 16 ++++++++++++++++ .../main/resources/META-INF/spring.factories | 19 +++++++++++++++++++ .../main/resources/META-INF/spring.provides | 18 ++++++++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 18 ++++++++++++++++++ 12 files changed, 95 insertions(+), 13 deletions(-) rename shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/{ => examples}/ShenyuTestMcpApplication.java (97%) rename shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/{ => examples}/controller/OrderController.java (97%) rename shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/{ => examples}/dto/OrderDTO.java (97%) create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.factories create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.provides create mode 100644 shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports diff --git a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java index dc896149fa51..b7479c3537be 100644 --- a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java +++ b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java @@ -27,6 +27,8 @@ import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; import org.apache.shenyu.register.common.type.DataTypeParent; +import java.util.Objects; + /** * The type shenyu client register event publisher. */ @@ -34,7 +36,7 @@ public class ShenyuClientRegisterEventPublisher { private static final ShenyuClientRegisterEventPublisher INSTANCE = new ShenyuClientRegisterEventPublisher(); - private DisruptorProviderManage providerManage; + private volatile DisruptorProviderManage providerManage; /** * Get instance. @@ -50,14 +52,18 @@ public static ShenyuClientRegisterEventPublisher getInstance() { * * @param shenyuClientRegisterRepository shenyuClientRegisterRepository */ - public void start(final ShenyuClientRegisterRepository shenyuClientRegisterRepository) { + public synchronized void start(final ShenyuClientRegisterRepository shenyuClientRegisterRepository) { + if (Objects.nonNull(providerManage)) { + return; + } RegisterClientExecutorFactory factory = new RegisterClientExecutorFactory(); factory.addSubscribers(new ShenyuClientMetadataExecutorSubscriber(shenyuClientRegisterRepository)); factory.addSubscribers(new ShenyuClientURIExecutorSubscriber(shenyuClientRegisterRepository)); factory.addSubscribers(new ShenyuClientApiDocExecutorSubscriber(shenyuClientRegisterRepository)); factory.addSubscribers(new ShenyuClientMcpExecutorSubscriber(shenyuClientRegisterRepository)); - providerManage = new DisruptorProviderManage<>(factory); - providerManage.startup(); + DisruptorProviderManage newProviderManage = new DisruptorProviderManage<>(factory); + newProviderManage.startup(); + providerManage = newProviderManage; } /** diff --git a/shenyu-client/shenyu-client-core/src/test/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientRegisterEventPublisherTest.java b/shenyu-client/shenyu-client-core/src/test/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientRegisterEventPublisherTest.java index a3ccf5ed6400..9cb90e3226a2 100644 --- a/shenyu-client/shenyu-client-core/src/test/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientRegisterEventPublisherTest.java +++ b/shenyu-client/shenyu-client-core/src/test/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientRegisterEventPublisherTest.java @@ -18,6 +18,7 @@ package org.apache.shenyu.client.core.disruptor.subcriber; import org.apache.shenyu.client.core.disruptor.ShenyuClientRegisterEventPublisher; +import org.apache.shenyu.disruptor.DisruptorProviderManage; import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; import org.apache.shenyu.register.common.type.DataTypeParent; import org.junit.jupiter.api.Assertions; @@ -45,7 +46,10 @@ public void testGetInstanceReturnsSameInstance() { public void testStart() { ShenyuClientRegisterEventPublisher publisher = ShenyuClientRegisterEventPublisher.getInstance(); publisher.start(shenyuClientRegisterRepository); - Assertions.assertNotNull(publisher.getProviderManage()); + DisruptorProviderManage providerManage = publisher.getProviderManage(); + Assertions.assertNotNull(providerManage); + publisher.start(shenyuClientRegisterRepository); + assertSame(providerManage, publisher.getProviderManage()); assertDoesNotThrow(() -> publisher.getProviderManage().startup()); } diff --git a/shenyu-examples/pom.xml b/shenyu-examples/pom.xml index 8990b04599ee..88998b8476a1 100644 --- a/shenyu-examples/pom.xml +++ b/shenyu-examples/pom.xml @@ -39,7 +39,7 @@ 0.40.1 3.4.0 2.6.0 - 2.7.0.3 + 2.7.2-SNAPSHOT diff --git a/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/ShenyuTestMcpApplication.java b/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/ShenyuTestMcpApplication.java similarity index 97% rename from shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/ShenyuTestMcpApplication.java rename to shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/ShenyuTestMcpApplication.java index 9950241f11a6..e5a383c4f73f 100644 --- a/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/ShenyuTestMcpApplication.java +++ b/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/ShenyuTestMcpApplication.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.shenyu; +package org.apache.shenyu.examples; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/controller/OrderController.java b/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/controller/OrderController.java similarity index 97% rename from shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/controller/OrderController.java rename to shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/controller/OrderController.java index e09f3c7d5169..1c3f4af24b04 100644 --- a/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/controller/OrderController.java +++ b/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/controller/OrderController.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.shenyu.controller; +package org.apache.shenyu.examples.controller; import io.swagger.v3.oas.annotations.OpenAPIDefinition; import io.swagger.v3.oas.annotations.Operation; @@ -30,7 +30,7 @@ import org.apache.shenyu.client.mcp.common.annotation.ShenyuMcpTool; import org.apache.shenyu.client.mcp.common.annotation.ShenyuMcpToolParam; import org.apache.shenyu.client.springmvc.annotation.ShenyuSpringMvcClient; -import org.apache.shenyu.dto.OrderDTO; +import org.apache.shenyu.examples.dto.OrderDTO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/dto/OrderDTO.java b/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/dto/OrderDTO.java similarity index 97% rename from shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/dto/OrderDTO.java rename to shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/dto/OrderDTO.java index c97c963ed91b..79aa0da5e49f 100644 --- a/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/dto/OrderDTO.java +++ b/shenyu-examples/shenyu-examples-mcp/src/main/java/org/apache/shenyu/examples/dto/OrderDTO.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.shenyu.dto; +package org.apache.shenyu.examples.dto; import java.io.Serializable; import java.util.StringJoiner; diff --git a/shenyu-examples/shenyu-examples-mcp/src/main/resources/application.yml b/shenyu-examples/shenyu-examples-mcp/src/main/resources/application.yml index accdbbb2efa0..38dbf7fc0392 100644 --- a/shenyu-examples/shenyu-examples-mcp/src/main/resources/application.yml +++ b/shenyu-examples/shenyu-examples-mcp/src/main/resources/application.yml @@ -18,8 +18,6 @@ server: address: 0.0.0.0 tomcat: max-http-form-post-size: 100MB - servlet: - context-path: /mcp shenyu: namespace: 649330b6-c2d7-4edc-be8e-8a54df9eb385 register: diff --git a/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java b/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java index dad414af2878..9359510017ad 100644 --- a/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java +++ b/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallback.java @@ -24,6 +24,7 @@ import io.modelcontextprotocol.server.McpSyncServerExchange; import org.apache.shenyu.common.constant.Constants; import org.apache.shenyu.common.dto.MetaData; +import org.apache.shenyu.common.enums.RpcTypeEnum; import org.apache.shenyu.common.utils.GsonUtils; import org.apache.shenyu.plugin.api.ShenyuPluginChain; import org.apache.shenyu.plugin.api.context.ShenyuContext; @@ -660,9 +661,11 @@ private void configureShenyuContext(final ServerWebExchange decoratedExchange, MetaData metaData = MetaDataCache.getInstance().obtain(configHelper.getUrlTemplate()); if (Objects.nonNull(metaData) && Boolean.TRUE.equals(metaData.getEnabled())) { decoratedExchange.getAttributes().put(Constants.META_DATA, metaData); - shenyuContext.setRpcType(metaData.getRpcType()); } + // MCP tools are invoked through an internal HTTP request. The response plugin + // must therefore select an HTTP MessageWriter rather than an MCP writer. + shenyuContext.setRpcType(RpcTypeEnum.HTTP.getName()); shenyuContext.setPath(extractRawPath(decoratedPath)); final Map attributes = decoratedExchange.getAttributes(); diff --git a/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java b/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java index 69acb2848f5e..9072c93dc6ea 100644 --- a/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java +++ b/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/callback/ShenyuToolCallbackTest.java @@ -19,6 +19,7 @@ import io.modelcontextprotocol.server.McpSyncServerExchange; import org.apache.shenyu.common.constant.Constants; +import org.apache.shenyu.common.enums.RpcTypeEnum; import org.apache.shenyu.plugin.api.ShenyuPluginChain; import org.apache.shenyu.plugin.api.context.ShenyuContext; import org.apache.shenyu.plugin.mcp.server.definition.ShenyuToolDefinition; @@ -34,6 +35,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.ai.chat.model.ToolContext; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.server.ServerWebExchange; import java.util.HashMap; @@ -45,6 +47,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; /** @@ -252,6 +255,19 @@ void testCallWithValidSetup() throws Exception { }); } + @Test + void testToolCallUsesHttpRpcType() { + shenyuToolCallback = new ShenyuToolCallback(toolDefinition); + when(exchange.getAttribute(Constants.CONTEXT)).thenReturn(shenyuContext); + when(exchange.getAttributes()).thenReturn(new HashMap<>()); + + ReflectionTestUtils.invokeMethod(shenyuToolCallback, "configureShenyuContext", exchange, + "session123", "/mcp/order/findAll", + "{\"requestTemplate\":{\"url\":\"/mcp/order/findAll\",\"method\":\"GET\"},\"argsPosition\":{}}"); + + verify(shenyuContext).setRpcType(RpcTypeEnum.HTTP.getName()); + } + @Test void testConstructorWithNullToolDefinition() { assertThrows(NullPointerException.class, () -> { diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.factories b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.factories new file mode 100644 index 000000000000..3fee4a16a531 --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.factories @@ -0,0 +1,19 @@ +# +# 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. +# + +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +org.apache.shenyu.springboot.starter.client.mcp.ShenyuMcpClientConfiguration diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.provides b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.provides new file mode 100644 index 000000000000..43e1f868c160 --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring.provides @@ -0,0 +1,18 @@ +# +# 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. +# + +provides: shenyu-spring-boot-starter-client-mcp diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 000000000000..1e553ca26083 --- /dev/null +++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1,18 @@ +# +# 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. +# + +org.apache.shenyu.springboot.starter.client.mcp.ShenyuMcpClientConfiguration From ddb02fdcad93fa25b44aa8a83fcc52e382b47172 Mon Sep 17 00:00:00 2001 From: hengyuss <1183660933@qq.com> Date: Sun, 6 Sep 2026 13:23:12 +0800 Subject: [PATCH 2/3] fix: make client register event publisher startup idempotent --- .../core/disruptor/ShenyuClientRegisterEventPublisher.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java index b7479c3537be..fb72aea59057 100644 --- a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java +++ b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/ShenyuClientRegisterEventPublisher.java @@ -27,8 +27,6 @@ import org.apache.shenyu.register.client.api.ShenyuClientRegisterRepository; import org.apache.shenyu.register.common.type.DataTypeParent; -import java.util.Objects; - /** * The type shenyu client register event publisher. */ @@ -38,6 +36,8 @@ public class ShenyuClientRegisterEventPublisher { private volatile DisruptorProviderManage providerManage; + private boolean initialized; + /** * Get instance. * @@ -53,7 +53,7 @@ public static ShenyuClientRegisterEventPublisher getInstance() { * @param shenyuClientRegisterRepository shenyuClientRegisterRepository */ public synchronized void start(final ShenyuClientRegisterRepository shenyuClientRegisterRepository) { - if (Objects.nonNull(providerManage)) { + if (initialized) { return; } RegisterClientExecutorFactory factory = new RegisterClientExecutorFactory(); @@ -64,6 +64,7 @@ public synchronized void start(final ShenyuClientRegisterRepository shenyuClient DisruptorProviderManage newProviderManage = new DisruptorProviderManage<>(factory); newProviderManage.startup(); providerManage = newProviderManage; + initialized = true; } /** From e8f8a46b917eb295b89afa6642f06881b81a1f00 Mon Sep 17 00:00:00 2001 From: hengyuss <1183660933@qq.com> Date: Sat, 19 Sep 2026 10:22:29 +0800 Subject: [PATCH 3/3] fix: update related build/documentation --- shenyu-examples/README.md | 82 +++++++++++++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/shenyu-examples/README.md b/shenyu-examples/README.md index 56b8312a92e2..fcc4b3a34d0e 100644 --- a/shenyu-examples/README.md +++ b/shenyu-examples/README.md @@ -4,7 +4,7 @@ This module contains example applications that demonstrate how to integrate your ## Client Dependencies -The example modules now consume **independent [shenyu-client-java](https://github.com/apache/shenyu-client-java) artifacts** from Maven Central, rather than depending on in-tree source modules from the main `apache/shenyu` repository. +The example modules resolve ShenYu client artifacts through Maven dependencies. Released client artifacts are published by [shenyu-client-java](https://github.com/apache/shenyu-client-java). The current development branch defaults to `2.7.2-SNAPSHOT` to use the MCP registration fixes in this repository; build and install these artifacts locally before building the examples. This reflects the recommended approach for real users: add the ShenYu client library as an external Maven dependency. @@ -13,11 +13,13 @@ This reflects the recommended approach for real users: add the ShenYu client lib The parent POM (`shenyu-examples/pom.xml`) defines a property: ```xml -2.7.0.3 +2.7.2-SNAPSHOT ``` All `shenyu-client-*` and `shenyu-spring-boot-starter-client-*` dependencies in individual example POMs are managed by this property through the `` section. The version is inherited automatically — individual examples do not specify a `` for these artifacts. +This default applies to all examples. A clean standalone build cannot assume that these unreleased artifacts are available from Maven Central. Follow the local build steps below, or override the version to `2.7.0.3` for examples that do not require the MCP fixes. + ### Which Artifacts Are Consumed Externally | Client Artifact | Used By | @@ -42,7 +44,61 @@ The following dependencies remain internal to this repository (`${project.versio - `shenyu-sdk-*` — ShenYu SDK modules (not extracted to shenyu-client-java) - `shenyu-spring-boot-starter-sdk-*` — ShenYu SDK starters (not extracted to shenyu-client-java) -## Testing with Unreleased Client Artifacts +## Building with 2.7.2-SNAPSHOT + +Use JDK 17 and run the following commands from the root of this `apache/shenyu` checkout. Use a checkout containing the MCP fixes: installing an unrelated snapshot from `shenyu-client-java` does not provide the changes in this repository. + +### Build and Run the MCP Example + +The MCP example uses both the MCP and Spring MVC client starters. Build both starters and their required reactor modules into the local Maven repository: + +```bash +mvn install -pl shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-mcp,shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc -am -DskipTests +``` + +Build the MCP example and its shared example utilities using the separate examples reactor: + +```bash +mvn -f shenyu-examples/pom.xml install -pl shenyu-examples-mcp -am \ + -Dshenyu.client.java.version=2.7.2-SNAPSHOT -DskipTests +``` + +Before starting the example, configure `shenyu-examples/shenyu-examples-mcp/src/main/resources/application.yml` for your ShenYu Admin address, credentials, namespace, and reachable service address. Run ShenYu Admin and Bootstrap from a checkout containing the corresponding MCP gateway fixes. + +```bash +mvn -f shenyu-examples/pom.xml spring-boot:run -pl shenyu-examples-mcp \ + -Dshenyu.client.java.version=2.7.2-SNAPSHOT +``` + +Keep the same version override for build and run commands. This selects `2.7.2-SNAPSHOT` for both starters through the parent dependency management. Check the resolved ShenYu dependencies with: + +```bash +mvn -f shenyu-examples/pom.xml dependency:tree -pl shenyu-examples-mcp \ + -Dshenyu.client.java.version=2.7.2-SNAPSHOT '-Dincludes=org.apache.shenyu:*' +``` + +Confirm that the selected MCP and Spring MVC starters and their shared client dependencies use `2.7.2-SNAPSHOT`. Then verify that the example registers its upstream and MCP tools in ShenYu Admin and that a tool invocation through the gateway succeeds. + +### Build Other Examples + +To prepare client dependencies for other examples using the default snapshot version, install the client and client starter modules and their dependencies from the repository root: + +```bash +mvn install -pl shenyu-client,shenyu-spring-boot-starter/shenyu-spring-boot-starter-client -am -DskipTests +``` + +Examples with internal SDK dependencies also require the corresponding SDK modules to be installed. + +For an example that does not require the MCP fixes, you can use the released client artifacts without changing any POM. For example, from the repository root: + +```bash +mvn -f shenyu-examples/pom.xml install -pl shenyu-examples-springmvc -am \ + -Dshenyu.client.java.version=2.7.0.3 -DskipTests +mvn -f shenyu-examples/pom.xml spring-boot:run -pl shenyu-examples-springmvc \ + -Dshenyu.client.java.version=2.7.0.3 +``` + +## Testing with Other Unreleased Client Artifacts When developing or testing changes to the `shenyu-client-java` library, you may need to build the client artifacts locally and use them in these examples. @@ -59,8 +115,9 @@ mvn clean install -DskipTests This installs the artifacts with the project's snapshot version (e.g., `2.7.0.1-jdk8-SNAPSHOT`). Then, build the examples using that version: ```bash -cd shenyu -mvn clean install -pl shenyu-examples -Dshenyu.client.java.version=2.7.0.1-jdk8-SNAPSHOT +# Run from the apache/shenyu repository root; select the example to test. +mvn -f shenyu-examples/pom.xml clean install -pl shenyu-examples-springmvc -am \ + -Dshenyu.client.java.version=2.7.0.1-jdk8-SNAPSHOT ``` ### Option 2: Modify the Property in Parent POM @@ -71,7 +128,7 @@ For a more permanent change during development, edit the `2.7.0.1-jdk8-SNAPSHOT ``` -> **Note**: When using `-SNAPSHOT` versions, you may need to configure the Apache Snapshot Repository in your `settings.xml` or POM: +> **Note**: Locally installed snapshots do not require a remote snapshot repository. If the required snapshot has been published, you can configure the Apache Snapshot Repository in your POM or an active profile in `settings.xml` (inside ``): > ```xml > > apache-snapshots @@ -87,10 +144,11 @@ For a more permanent change during development, edit the ` **Note**: Running `mvn spring-boot:run` directly from within an individual example directory (e.g., `cd shenyu-examples-springmvc && mvn spring-boot:run`) will fail because `shenyu-examples-common` and the parent POM cannot be resolved outside the reactor. Always use the `-pl` approach from the `shenyu-examples/` root. +> **Note**: `-pl` selects an example but does not build its dependencies. Install the required internal modules before running it. If you used a client version override when building, pass the same override to `spring-boot:run`. ### Confirm Registration