+ * }
*
* This method provided for convenience of handling user input endpoints, and do not have a strict meaning. Make sure all unit test cases
* work before change.
diff --git a/core/src/test/java/org/apache/servicecomb/core/TestInvocation.java b/core/src/test/java/org/apache/servicecomb/core/TestInvocation.java
index 4cf335cd34c..80b6bbda461 100644
--- a/core/src/test/java/org/apache/servicecomb/core/TestInvocation.java
+++ b/core/src/test/java/org/apache/servicecomb/core/TestInvocation.java
@@ -17,7 +17,6 @@
package org.apache.servicecomb.core;
import java.util.Arrays;
-import java.util.Map;
import org.apache.servicecomb.core.definition.InvocationRuntimeType;
import org.apache.servicecomb.core.definition.OperationMeta;
@@ -49,7 +48,6 @@
import mockit.Mocked;
public class TestInvocation {
- Invocation invocation;
@Mocked
Endpoint endpoint;
@@ -60,9 +58,6 @@ public class TestInvocation {
@Mocked
InvocationRuntimeType invocationRuntimeType;
- @Mocked
- Map arguments;
-
static long nanoTime = 123;
@BeforeClass
@@ -95,7 +90,7 @@ public void onStart(InvocationStartEvent event) {
};
EventManager.register(subscriber);
- Invocation invocation = new Invocation(endpoint, operationMeta, arguments);
+ Invocation invocation = new Invocation(endpoint, operationMeta, null);
invocation.onStart();
Assertions.assertSame(invocation, result.value);
@@ -115,7 +110,7 @@ public void onStart(InvocationFinishEvent event) {
};
EventManager.register(subscriber);
- Invocation invocation = new Invocation(endpoint, operationMeta, arguments);
+ Invocation invocation = new Invocation(endpoint, operationMeta, null);
Assertions.assertFalse(invocation.isFinished());
Response response = Response.succResp(null);
invocation.onFinish(response);
@@ -134,19 +129,19 @@ public void onStart(InvocationFinishEvent event) {
@Test
public void isConsumer_yes() {
- Invocation invocation = new Invocation(endpoint, operationMeta, arguments);
+ Invocation invocation = new Invocation(endpoint, operationMeta, null);
Assertions.assertFalse(invocation.isConsumer());
}
@Test
public void isConsumer_no(@Mocked ReferenceConfig referenceConfig) {
- Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments);
+ Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null);
Assertions.assertTrue(invocation.isConsumer());
}
@Test
public void localContext(@Mocked ReferenceConfig referenceConfig) {
- Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments);
+ Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null);
invocation.addLocalContext("k", 1);
Assertions.assertSame(invocation.getHandlerContext(), invocation.getLocalContext());
@@ -155,7 +150,7 @@ public void localContext(@Mocked ReferenceConfig referenceConfig) {
@Test
public void traceId_fromContext(@Mocked ReferenceConfig referenceConfig) {
- Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments);
+ Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null);
invocation.addContext(CoreConst.TRACE_ID_NAME, "abc");
invocation.onStart();
@@ -173,7 +168,7 @@ public void traceId_consumerCreateTraceId(@Mocked ReferenceConfig referenceConfi
result = "abc";
}
};
- Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments);
+ Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null);
invocation.onStart();
@@ -189,7 +184,7 @@ public void traceId_fromRequest(@Mocked Endpoint endpoint, @Mocked HttpServletRe
result = "abc";
}
};
- Invocation invocation = new Invocation(endpoint, operationMeta, arguments);
+ Invocation invocation = new Invocation(endpoint, operationMeta, null);
invocation.onStart(requestEx);
@@ -199,6 +194,7 @@ public void traceId_fromRequest(@Mocked Endpoint endpoint, @Mocked HttpServletRe
@Test
public void traceId_producerCreateTraceId(@Mocked Endpoint endpoint, @Mocked HttpServletRequestEx requestEx) {
+
TraceIdGenerator generator = SPIServiceUtils.getTargetService(TraceIdGenerator.class, BraveTraceIdGenerator.class);
new Expectations(generator) {
{
@@ -206,7 +202,7 @@ public void traceId_producerCreateTraceId(@Mocked Endpoint endpoint, @Mocked Htt
result = "abc";
}
};
- Invocation invocation = new Invocation(endpoint, operationMeta, arguments);
+ Invocation invocation = new Invocation(endpoint, operationMeta, null);
invocation.onStart(requestEx);
@@ -250,7 +246,7 @@ public void onBusinessMethodStart(InvocationBusinessMethodStartEvent event) {
}
};
EventManager.getEventBus().register(listener);
- Invocation invocation = new Invocation(endpoint, operationMeta, arguments);
+ Invocation invocation = new Invocation(endpoint, operationMeta, null);
mockNonaTime();
invocation.onBusinessMethodStart();
EventManager.getEventBus().unregister(listener);
@@ -265,12 +261,12 @@ public void onBusinessMethodStart(InvocationBusinessMethodStartEvent event) {
public void marker(@Mocked ReferenceConfig referenceConfig) {
Invocation.INVOCATION_ID.set(0);
- Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments);
+ Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null);
invocation.addContext(CoreConst.TRACE_ID_NAME, "abc");
invocation.onStart();
Assertions.assertEquals("abc", invocation.getTraceIdLogger().getName());
- invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments);
+ invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null);
invocation.addContext(CoreConst.TRACE_ID_NAME, "abc");
invocation.onStart();
Assertions.assertEquals("abc", invocation.getTraceIdLogger().getName());
diff --git a/core/src/test/java/org/apache/servicecomb/core/executor/TestGroupExecutor.java b/core/src/test/java/org/apache/servicecomb/core/executor/TestGroupExecutor.java
index d92ca3bb2ce..dd95105992b 100644
--- a/core/src/test/java/org/apache/servicecomb/core/executor/TestGroupExecutor.java
+++ b/core/src/test/java/org/apache/servicecomb/core/executor/TestGroupExecutor.java
@@ -111,7 +111,7 @@ public void maxThreads() {
Assertions.assertEquals(
"servicecomb.executor.default.thread-per-group is deprecated, recommended to use servicecomb.executor.default.maxThreads-per-group.",
collector.getEvents().get(collector.getEvents().size() - 2).getMessage().getFormattedMessage());
- collector.teardown();
+ collector.tearDown();
Mockito.when(environment.getProperty(KEY_MAX_THREADS, int.class, -1)).thenReturn(300);
groupExecutor.initConfig();
@@ -127,7 +127,7 @@ public void adjustCoreThreads() {
Assertions.assertEquals(
"coreThreads is bigger than maxThreads, change from 25 to 10.",
collector.getEvents().get(collector.getEvents().size() - 2).getMessage().getFormattedMessage());
- collector.teardown();
+ collector.tearDown();
}
@Test
diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilterTest.java b/core/src/test/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilterTest.java
index 4531895e9b2..dd46b17d28b 100644
--- a/core/src/test/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilterTest.java
+++ b/core/src/test/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilterTest.java
@@ -189,8 +189,7 @@ public void should_unify_IllegalArgumentException_message_when_convert_exception
assertThat(future)
.failsWithin(Duration.ofSeconds(1))
.withThrowableOfType(ExecutionException.class)
- .withCauseExactlyInstanceOf(IllegalArgumentException.class)
- .withMessage("java.lang.IllegalArgumentException: wrong number of arguments");
+ .withCauseExactlyInstanceOf(IllegalArgumentException.class);
InvocationException throwable = Exceptions
.convert(invocation, catchThrowable(future::get), INTERNAL_SERVER_ERROR);
diff --git a/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointTest.java b/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointTest.java
index a28a2be4208..b3c0733bb48 100644
--- a/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointTest.java
+++ b/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointTest.java
@@ -26,7 +26,6 @@
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.core.Transport;
import org.apache.servicecomb.foundation.common.Holder;
-import org.apache.servicecomb.swagger.SwaggerUtils;
import org.apache.servicecomb.swagger.engine.SwaggerConsumer;
import org.apache.servicecomb.swagger.engine.SwaggerConsumerOperation;
import org.apache.servicecomb.swagger.engine.SwaggerEnvironment;
@@ -46,22 +45,10 @@ void should_ignore_endpoint_when_generate_swagger() {
SwaggerGenerator generator = SwaggerGenerator.create(TestSchema.class);
OpenAPI swagger = generator.generate();
- assertThat(SwaggerUtils.swaggerToString(swagger))
- .isEqualTo("openapi: 3.0.1\n"
- + "info:\n"
- + " title: swagger definition for org.apache.servicecomb.core.invocation.endpoint.EndpointTest$TestSchema\n"
- + " version: 1.0.0\n"
- + "servers:\n"
- + "- url: /TestSchema\n"
- + "paths:\n"
- + " /say:\n"
- + " post:\n"
- + " operationId: say\n"
- + " responses:\n"
- + " \"200\":\n"
- + " description: response of 200\n"
- + "components: {}\n"
- + "");
+ assertThat(swagger.getInfo().getTitle()).contains("EndpointTest$TestSchema");
+ assertThat(swagger.getPaths()).containsKey("/say");
+ assertThat(swagger.getPaths().get("/say").getPost().getOperationId()).isEqualTo("say");
+ assertThat(swagger.getPaths().get("/say").getPost().getResponses()).containsKey("200");
}
@Test
diff --git a/core/src/test/java/org/apache/servicecomb/core/transport/TestAbstractTransport.java b/core/src/test/java/org/apache/servicecomb/core/transport/TestAbstractTransport.java
index 934381fe455..65c44b12560 100644
--- a/core/src/test/java/org/apache/servicecomb/core/transport/TestAbstractTransport.java
+++ b/core/src/test/java/org/apache/servicecomb/core/transport/TestAbstractTransport.java
@@ -32,7 +32,7 @@
import org.mockito.Mockito;
import org.springframework.core.env.Environment;
-import io.vertx.core.file.impl.FileResolverImpl;
+import io.vertx.core.impl.SysProps;
public class TestAbstractTransport {
Environment environment = Mockito.mock(Environment.class);
@@ -56,7 +56,7 @@ public void setUp() {
Mockito.when(environment.getProperty("servicecomb.my.publishPort", int.class, 0)).thenReturn(0);
Mockito.when(environment.getProperty("servicecomb.transport.eventloop.size", int.class, -1))
.thenReturn(-1);
- Mockito.when(environment.getProperty(FileResolverImpl.DISABLE_CP_RESOLVING_PROP_NAME, boolean.class, true))
+ Mockito.when(environment.getProperty(SysProps.DISABLE_FILE_CP_RESOLVING.name, boolean.class, true))
.thenReturn(true);
LegacyPropertyFactory.setEnvironment(environment);
}
diff --git a/coverage-reports/pom.xml b/coverage-reports/pom.xml
index 7bb79b0ce8c..97f795fcbf5 100644
--- a/coverage-reports/pom.xml
+++ b/coverage-reports/pom.xml
@@ -21,7 +21,7 @@
org.apache.servicecombjava-chassis-parent
- 3.3.0-SNAPSHOT
+ 3.4.0-SNAPSHOT../parents/default4.0.0
diff --git a/demo/demo-consul/README.md b/demo/demo-consul/README.md
new file mode 100644
index 00000000000..872a1d2e93a
--- /dev/null
+++ b/demo/demo-consul/README.md
@@ -0,0 +1,5 @@
+# Notice
+
+This integration tests is designed for Consul registry and configuration. And extra test cases include:
+
+* Test cases related to SpringMVC annotations that demo-springmvc can not cover.
diff --git a/demo/demo-consul/consumer/pom.xml b/demo/demo-consul/consumer/pom.xml
new file mode 100644
index 00000000000..eccc75e41b1
--- /dev/null
+++ b/demo/demo-consul/consumer/pom.xml
@@ -0,0 +1,104 @@
+
+
+
+ 4.0.0
+
+
+ org.apache.servicecomb.demo
+ demo-consul
+ 3.4.0-SNAPSHOT
+
+
+ consul-consumer
+ Java Chassis::Demo::Consul::CONSUMER
+ jar
+
+
+
+ org.apache.servicecomb
+ java-chassis-spring-boot-starter-standalone
+
+
+ org.apache.servicecomb
+ registry-consul
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ docker
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+ ${project.artifactId}:${project.version}
+ ${project.artifactId}
+
+ eclipse-temurin:17-jre-jammy
+
+ 7070
+ 8080
+
+
+ tar
+ ${root.basedir}/assembly/assembly.xml
+
+
+ java -Xmx128m $JAVA_OPTS -jar $JAR_PATH
+
+
+
+
+
+
+
+ build
+ package
+
+ build
+
+
+
+
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+
+
+
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java
new file mode 100644
index 00000000000..f71738a9ed6
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java
@@ -0,0 +1,52 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.core.CoreConst;
+import org.apache.servicecomb.core.annotation.Transport;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.vertx.core.http.ServerWebSocket;
+import io.vertx.core.http.WebSocket;
+
+@RestSchema(schemaId = "ClientWebsocketController")
+@RequestMapping(path = "/ws")
+public class ClientWebsocketController {
+ interface ProviderService {
+ WebSocket websocket();
+ }
+
+ @RpcReference(schemaId = "WebsocketController", microserviceName = "provider")
+ private ProviderService providerService;
+
+ @PostMapping("/websocket")
+ @Transport(name = CoreConst.WEBSOCKET)
+ public void websocket(ServerWebSocket serverWebsocket) {
+ WebSocket providerWebSocket = providerService.websocket();
+ providerWebSocket.closeHandler(v -> serverWebsocket.close());
+ providerWebSocket.textMessageHandler(m -> {
+ serverWebsocket.writeTextMessage(m);
+ });
+ serverWebsocket.textMessageHandler(m -> {
+ providerWebSocket.writeTextMessage(m);
+ });
+ }
+}
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsulConsumerApplication.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsulConsumerApplication.java
new file mode 100644
index 00000000000..da243836198
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsulConsumerApplication.java
@@ -0,0 +1,33 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+public class ConsulConsumerApplication {
+ public static void main(String[] args) throws Exception {
+ try {
+ new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ConsulConsumerApplication.class).run(args);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
new file mode 100644
index 00000000000..e66fb2cb3d0
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java
@@ -0,0 +1,52 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@RestSchema(schemaId = "ConsumerController")
+@RequestMapping(path = "/")
+public class ConsumerController {
+ @RpcReference(schemaId = "ProviderController", microserviceName = "provider")
+ private ProviderService providerService;
+
+ // consumer service which delegate the implementation to provider service.
+ @GetMapping("/sayHello")
+ public String sayHello(@RequestParam("name") String name) {
+ return providerService.sayHello(name);
+ }
+
+ @GetMapping("/getConfig")
+ public String getConfig(@RequestParam("key") String key) {
+ return providerService.getConfig(key);
+ }
+
+ @PostMapping(path = "/testContentType", consumes = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseBody
+ public User testContentType(@RequestBody User user) {
+ return providerService.testContentType(user);
+ }
+}
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java
new file mode 100644
index 00000000000..f0e894d6745
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java
@@ -0,0 +1,55 @@
+/*
+ * 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.servicecomb.samples;
+
+import java.util.List;
+
+import org.apache.servicecomb.demo.api.IHeaderParamWithListSchemaSpringMvc;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+@RestSchema(schemaId = "ConsumerHeaderParamWithListSchema", schemaInterface = IHeaderParamWithListSchemaSpringMvc.class)
+public class ConsumerHeaderParamWithListSchema implements IHeaderParamWithListSchemaSpringMvc {
+ @RpcReference(microserviceName = "provider", schemaId = "HeaderParamWithListSchema")
+ private IHeaderParamWithListSchemaSpringMvc provider;
+
+ @Override
+ public String headerListDefault(List headerList) {
+ return provider.headerListDefault(headerList);
+ }
+
+ @Override
+ public String headerListCSV(List headerList) {
+ return provider.headerListCSV(headerList);
+ }
+
+ @Override
+ public String headerListMULTI(List headerList) {
+ return provider.headerListMULTI(headerList);
+ }
+
+ @Override
+ public String headerListSSV(List headerList) {
+ return provider.headerListSSV(headerList);
+ }
+
+ @Override
+ public String headerListPIPES(List headerList) {
+ return provider.headerListPIPES(headerList);
+ }
+}
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java
new file mode 100644
index 00000000000..aa169801cf7
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java
@@ -0,0 +1,84 @@
+/*
+ * 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.servicecomb.samples;
+
+
+import org.apache.servicecomb.core.CoreConst;
+import org.apache.servicecomb.core.annotation.Transport;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.reactivestreams.Publisher;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RestSchema(schemaId = "ReactiveStreamController")
+@RequestMapping(path = "/")
+public class ConsumerReactiveStreamController {
+ interface ProviderReactiveStreamController {
+ Publisher sseString();
+
+ Publisher sseModel();
+ }
+
+ @RpcReference(microserviceName = "provider", schemaId = "ReactiveStreamController")
+ ProviderReactiveStreamController controller;
+
+ public static class Model {
+ private String name;
+
+ private int age;
+
+ public Model() {
+
+ }
+
+ public Model(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public Model setAge(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Model setName(String name) {
+ this.name = name;
+ return this;
+ }
+ }
+
+ @GetMapping("/sseString")
+ @Transport(name = CoreConst.RESTFUL)
+ public Publisher sseString() {
+ return controller.sseString();
+ }
+
+ @GetMapping("/sseModel")
+ @Transport(name = CoreConst.RESTFUL)
+ public Publisher sseModel() {
+ return controller.sseModel();
+ }
+}
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
new file mode 100644
index 00000000000..2899546c752
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.servicecomb.samples;
+
+public interface ProviderService {
+ String sayHello(String name);
+
+ String getConfig(String key);
+
+ User testContentType(User user);
+}
diff --git a/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/User.java b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/User.java
new file mode 100644
index 00000000000..ff421930ef2
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/java/org/apache/servicecomb/samples/User.java
@@ -0,0 +1,41 @@
+/*
+ * 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.servicecomb.samples;
+
+
+public class User {
+
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/demo/demo-consul/consumer/src/main/resources/application.yml b/demo/demo-consul/consumer/src/main/resources/application.yml
new file mode 100644
index 00000000000..ef0d45c1dcb
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/resources/application.yml
@@ -0,0 +1,40 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+servicecomb:
+ service:
+ application: demo-consul
+ version: 0.0.1
+ name: consumer
+ properties:
+ group: green
+
+ registry:
+ consul:
+ enabled: true
+ host: 127.0.0.1
+ scheme: http
+ discovery:
+ enabled: true
+ acl-token: ''
+ watch-seconds: 8
+
+ rest:
+ address: 0.0.0.0:9092?websocketEnabled=true
+ server:
+ websocket-prefix: /ws
diff --git a/demo/demo-consul/consumer/src/main/resources/log4j2.xml b/demo/demo-consul/consumer/src/main/resources/log4j2.xml
new file mode 100644
index 00000000000..c51f7ad5036
--- /dev/null
+++ b/demo/demo-consul/consumer/src/main/resources/log4j2.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/demo-consul/gateway/pom.xml b/demo/demo-consul/gateway/pom.xml
new file mode 100644
index 00000000000..1dad3860e7f
--- /dev/null
+++ b/demo/demo-consul/gateway/pom.xml
@@ -0,0 +1,107 @@
+
+
+
+ 4.0.0
+
+
+ org.apache.servicecomb.demo
+ demo-consul
+ 3.4.0-SNAPSHOT
+
+
+ consul-gateway
+ Java Chassis::Demo::Consul::GATEWAY
+ jar
+
+
+
+ org.apache.servicecomb
+ java-chassis-spring-boot-starter-standalone
+
+
+ org.apache.servicecomb
+ edge-core
+
+
+ org.apache.servicecomb
+ registry-consul
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ docker
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+ ${project.artifactId}:${project.version}
+ ${project.artifactId}
+
+ eclipse-temurin:17-jre-jammy
+
+ 7070
+ 8080
+
+
+ tar
+ ${root.basedir}/assembly/assembly.xml
+
+
+ java -Xmx128m $JAVA_OPTS -jar $JAR_PATH
+
+
+
+
+
+
+
+ build
+ package
+
+ build
+
+
+
+
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+
+
+
diff --git a/demo/demo-consul/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-consul/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java
new file mode 100644
index 00000000000..7d58caafd9d
--- /dev/null
+++ b/demo/demo-consul/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java
@@ -0,0 +1,33 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+public class GatewayApplication {
+ public static void main(String[] args) throws Exception {
+ try {
+ new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(GatewayApplication.class).run(args);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/demo/demo-consul/gateway/src/main/resources/application.yml b/demo/demo-consul/gateway/src/main/resources/application.yml
new file mode 100644
index 00000000000..9855a87a1de
--- /dev/null
+++ b/demo/demo-consul/gateway/src/main/resources/application.yml
@@ -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.
+## ---------------------------------------------------------------------------
+
+servicecomb:
+ service:
+ application: demo-consul
+ version: 0.0.1
+ name: gateway
+
+ registry:
+ consul:
+ enabled: true
+ host: 127.0.0.1
+ scheme: http
+ discovery:
+ enabled: true
+ acl-token: ''
+ watch-seconds: 8
+
+ rest:
+ address: 0.0.0.0:9090?websocketEnabled=true
+ server:
+ websocket-prefix: /ws
+
+ http:
+ dispatcher:
+ edge:
+ default:
+ enabled: false
+ url:
+ enabled: true
+ pattern: /(.*)
+ mappings:
+ consumer:
+ prefixSegmentCount: 0
+ path: "/.*"
+ microserviceName: consumer
+ versionRule: 0.0.0+
+ websocket:
+ mappings:
+ consumer:
+ prefixSegmentCount: 0
+ path: "/ws/.*"
+ microserviceName: consumer
+ versionRule: 0.0.0+
diff --git a/demo/demo-consul/gateway/src/main/resources/log4j2.xml b/demo/demo-consul/gateway/src/main/resources/log4j2.xml
new file mode 100644
index 00000000000..c51f7ad5036
--- /dev/null
+++ b/demo/demo-consul/gateway/src/main/resources/log4j2.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/demo-consul/pom.xml b/demo/demo-consul/pom.xml
new file mode 100644
index 00000000000..aaa8f3b91ce
--- /dev/null
+++ b/demo/demo-consul/pom.xml
@@ -0,0 +1,62 @@
+
+
+
+
+ 4.0.0
+
+ org.apache.servicecomb.demo
+ demo-parent
+ 3.4.0-SNAPSHOT
+
+
+ demo-consul
+ Java Chassis::Demo::Consul
+ pom
+
+
+
+ org.apache.servicecomb.demo
+ demo-schema
+
+
+ org.apache.servicecomb
+ solution-basic
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+
+
+ org.apache.logging.log4j
+ log4j-core
+
+
+ org.apache.logging.log4j
+ log4j-api
+
+
+
+
+ provider
+ consumer
+ gateway
+ test-client
+
+
diff --git a/demo/demo-consul/provider/pom.xml b/demo/demo-consul/provider/pom.xml
new file mode 100644
index 00000000000..0986f9f4342
--- /dev/null
+++ b/demo/demo-consul/provider/pom.xml
@@ -0,0 +1,114 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.servicecomb.demo
+ demo-consul
+ 3.4.0-SNAPSHOT
+
+
+ consul-provider
+ Java Chassis::Demo::Consul::PROVIDER
+ jar
+
+
+
+ org.apache.servicecomb
+ java-chassis-spring-boot-starter-standalone
+
+
+ org.apache.servicecomb
+ registry-consul
+
+
+ org.apache.servicecomb
+ config-consul
+
+
+
+ io.reactivex.rxjava3
+ rxjava
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ docker
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+ ${project.artifactId}:${project.version}
+ ${project.artifactId}
+
+ eclipse-temurin:17-jre-jammy
+
+ 7070
+ 8080
+
+
+ tar
+ ${root.basedir}/assembly/assembly.xml
+
+
+ java -Xmx128m $JAVA_OPTS -jar $JAR_PATH
+
+
+
+
+
+
+
+ build
+ package
+
+ build
+
+
+
+
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+
+
+
diff --git a/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ConsulProviderApplication.java b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ConsulProviderApplication.java
new file mode 100644
index 00000000000..b84da167943
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ConsulProviderApplication.java
@@ -0,0 +1,33 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+
+@SpringBootApplication
+public class ConsulProviderApplication {
+ public static void main(String[] args) throws Exception {
+ try {
+ new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ConsulProviderApplication.class).run(args);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java
new file mode 100644
index 00000000000..8a773f91c72
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java
@@ -0,0 +1,51 @@
+/*
+ * 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.servicecomb.samples;
+
+import java.util.List;
+
+import org.apache.servicecomb.demo.api.IHeaderParamWithListSchemaSpringMvc;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+@RestSchema(schemaId = "HeaderParamWithListSchema", schemaInterface = IHeaderParamWithListSchemaSpringMvc.class)
+public class HeaderParamWithListSchema implements IHeaderParamWithListSchemaSpringMvc {
+ @Override
+ public String headerListDefault(List headerList) {
+ return headerList == null ? "null" : headerList.size() + ":" + headerList;
+ }
+
+ @Override
+ public String headerListCSV(List headerList) {
+ return headerList == null ? "null" : headerList.size() + ":" + headerList;
+ }
+
+ @Override
+ public String headerListMULTI(List headerList) {
+ return headerList == null ? "null" : headerList.size() + ":" + headerList;
+ }
+
+ @Override
+ public String headerListSSV(List headerList) {
+ return headerList == null ? "null" : headerList.size() + ":" + headerList;
+ }
+
+ @Override
+ public String headerListPIPES(List headerList) {
+ return headerList == null ? "null" : headerList.size() + ":" + headerList;
+ }
+}
diff --git a/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java
new file mode 100644
index 00000000000..677c20ed106
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.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.servicecomb.samples;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+@RestSchema(schemaId = "ProviderController")
+@RequestMapping(path = "/")
+public class ProviderController implements InitializingBean {
+ private Environment environment;
+
+ @Autowired
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ // a very simple service to echo the request parameter
+ @GetMapping("/sayHello")
+ public String sayHello(@RequestParam("name") String name) {
+// return "Hello " + environment.getProperty("servicecomb.rest.address");
+ return "Hello " + name;
+ }
+
+ @GetMapping("/getConfig")
+ public String getConfig(@RequestParam("key") String key) {
+ return environment.getProperty(key);
+ }
+
+ @PostMapping(path = "/testContentType", consumes = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseBody
+ public User testContentType(@RequestBody User user) {
+ return user;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ }
+}
diff --git a/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java
new file mode 100644
index 00000000000..8108d15fd46
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java
@@ -0,0 +1,78 @@
+/*
+ * 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.servicecomb.samples;
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.CoreConst;
+import org.apache.servicecomb.core.annotation.Transport;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.reactivestreams.Publisher;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.reactivex.rxjava3.core.Flowable;
+
+@RestSchema(schemaId = "ReactiveStreamController")
+@RequestMapping(path = "/")
+@Transport(name = CoreConst.RESTFUL)
+public class ReactiveStreamController {
+ public static class Model {
+ private String name;
+
+ private int age;
+
+ public Model() {
+
+ }
+
+ public Model(String name, int age) {
+ this.name = name;
+ this.age = age;
+ }
+
+ public int getAge() {
+ return age;
+ }
+
+ public Model setAge(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Model setName(String name) {
+ this.name = name;
+ return this;
+ }
+ }
+
+ @GetMapping("/sseString")
+ public Publisher sseString() {
+ return Flowable.fromArray("a", "b", "c");
+ }
+
+ @GetMapping("/sseModel")
+ public Publisher sseModel() {
+ return Flowable.intervalRange(0, 5, 0, 1, TimeUnit.SECONDS)
+ .map(item -> new Model("jack", item.intValue()));
+ }
+}
diff --git a/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/User.java b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/User.java
new file mode 100644
index 00000000000..ca12402d672
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/User.java
@@ -0,0 +1,40 @@
+/*
+ * 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.servicecomb.samples;
+
+public class User {
+
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java
new file mode 100644
index 00000000000..6381ef1d54c
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java
@@ -0,0 +1,71 @@
+/*
+ * 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.servicecomb.samples;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.servicecomb.core.CoreConst;
+import org.apache.servicecomb.core.annotation.Transport;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.vertx.core.http.ServerWebSocket;
+
+@RestSchema(schemaId = "WebsocketController")
+@RequestMapping(path = "/ws")
+public class WebsocketController {
+ @PostMapping("/websocket")
+ @Transport(name = CoreConst.WEBSOCKET)
+ public void websocket(ServerWebSocket serverWebsocket) {
+ AtomicInteger receiveCount = new AtomicInteger(0);
+ CountDownLatch startSend = new CountDownLatch(1);
+ serverWebsocket.textMessageHandler(s -> {
+ if ("start".equals(s)) {
+ startSend.countDown();
+ serverWebsocket.writeTextMessage("started");
+ return;
+ }
+ receiveCount.getAndIncrement();
+ });
+ serverWebsocket.closeHandler((v) -> System.out.println("closed"));
+
+ new Thread(() -> {
+ try {
+ startSend.await(30, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ serverWebsocket.writeTextMessage("hello");
+
+ for (int i = 0; i < 5; i++) {
+ serverWebsocket.writeTextMessage("hello " + i);
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ serverWebsocket.writeTextMessage("total " + receiveCount.get());
+ serverWebsocket.close();
+ }).start();
+ }
+}
diff --git a/demo/demo-consul/provider/src/main/resources/application.yml b/demo/demo-consul/provider/src/main/resources/application.yml
new file mode 100644
index 00000000000..31bbfa5d4c7
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/resources/application.yml
@@ -0,0 +1,67 @@
+#
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+# spring boot configurations
+servicecomb:
+ service:
+ application: demo-consul
+ version: 0.0.1
+ name: provider
+ properties:
+ group: green
+
+ registry:
+ consul:
+ enabled: true
+ host: 127.0.0.1
+ scheme: http
+ discovery:
+ enabled: true
+ acl-token: ''
+ watch-seconds: 8
+
+ config:
+ consul:
+ enabled: true
+ host: 127.0.0.1
+ scheme: http
+ acl-token: ''
+ watch-seconds: 8
+
+ rest:
+ address: 0.0.0.0:9094?websocketEnabled=true
+ server:
+ websocket-prefix: /ws
+
+ cors:
+ enabled: true
+ origin: "*"
+ allowCredentials: false
+ allowedMethod: "*"
+ maxAge: 3600
+
+
+key1: 1
+key2: 3
+key3: 5
+
+test1: env
+test2: applition
+test3: service
+test4: version
+test5: tag
diff --git a/demo/demo-consul/provider/src/main/resources/log4j2.xml b/demo/demo-consul/provider/src/main/resources/log4j2.xml
new file mode 100644
index 00000000000..c51f7ad5036
--- /dev/null
+++ b/demo/demo-consul/provider/src/main/resources/log4j2.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demo/demo-consul/test-client/pom.xml b/demo/demo-consul/test-client/pom.xml
new file mode 100644
index 00000000000..791ac474886
--- /dev/null
+++ b/demo/demo-consul/test-client/pom.xml
@@ -0,0 +1,220 @@
+
+
+
+
+ 4.0.0
+
+
+ org.apache.servicecomb.demo
+ demo-consul
+ 3.4.0-SNAPSHOT
+
+
+ consul-test-client
+ Java Chassis::Demo::Consul::TEST-CLIENT
+ jar
+
+
+
+
+
+
+ org.apache.servicecomb
+ java-chassis-spring-boot-starter-standalone
+
+
+ org.apache.servicecomb.demo
+ demo-schema
+
+
+ org.apache.servicecomb
+ registry-local
+
+
+ org.kiwiproject
+ consul-client
+
+
+ com.google.code.gson
+ gson
+
+
+
+
+
+ docker
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+ hashicorp/consul:1.21
+ consul
+
+ alias
+
+ consulServer
+
+
+ 8500
+
+
+
+
+
+ 8500:8500
+
+
+ yes
+
+
+
+
+ consul-provider:${project.version}
+ consul-provider
+
+ alias
+
+
+ -Dservicecomb.registry.consul.enabled=true
+ -Dservicecomb.registry.consul.scheme=http
+ -Dservicecomb.registry.consul.host=consul
+ -Dservicecomb.registry.consul.port=8500
+ -Dservicecomb.config.consul.enabled=true
+ -Dservicecomb.config.consul.scheme=http
+ -Dservicecomb.config.consul.host=consul
+ -Dservicecomb.config.consul.port=8500
+
+ /maven/maven/consul-provider-${project.version}.jar
+
+
+ consul:consul
+
+
+ ServiceComb is ready
+
+
+ 9094
+
+
+
+
+
+ 9094:9094
+
+
+
+
+ consul-consumer:${project.version}
+ consul-consumer
+
+ alias
+
+
+ -Dservicecomb.registry.consul.enabled=true
+ -Dservicecomb.registry.consul.scheme=http
+ -Dservicecomb.registry.consul.host=consul
+ -Dservicecomb.registry.consul.port=8500
+
+ /maven/maven/consul-consumer-${project.version}.jar
+
+
+ consul:consul
+
+
+ ServiceComb is ready
+
+
+ 9092
+
+
+
+
+
+ 9092:9092
+
+
+
+
+ consul-gateway:${project.version}
+ consul-gateway
+
+ alias
+
+
+ -Dservicecomb.registry.consul.enabled=true
+ -Dservicecomb.registry.consul.scheme=http
+ -Dservicecomb.registry.consul.host=consul
+ -Dservicecomb.registry.consul.port=8500
+
+ /maven/maven/consul-gateway-${project.version}.jar
+
+
+ consul:consul
+
+
+ ServiceComb is ready
+
+
+ 9090
+
+
+
+
+
+ 9090:9090
+
+
+
+
+
+
+
+ start
+ pre-integration-test
+
+ start
+
+
+
+ stop
+ post-integration-test
+
+ stop
+
+
+
+
+
+
+
+
+
+ io.fabric8
+ docker-maven-plugin
+
+
+
+
+
+
diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/Config.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/Config.java
new file mode 100644
index 00000000000..2e9105cdd4a
--- /dev/null
+++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/Config.java
@@ -0,0 +1,22 @@
+/*
+ * 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.servicecomb.samples;
+
+public interface Config {
+ String GATEWAY_URL = "http://localhost:9090";
+}
diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ConsulConfigIT.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ConsulConfigIT.java
new file mode 100644
index 00000000000..1a7be4b874d
--- /dev/null
+++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ConsulConfigIT.java
@@ -0,0 +1,140 @@
+/*
+ * 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.servicecomb.samples;
+
+import com.google.common.net.HostAndPort;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.foundation.common.utils.ConditionWaiter.SleepUtil;
+import org.kiwiproject.consul.Consul;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.concurrent.TimeUnit;
+
+@Component
+public class ConsulConfigIT implements CategorizedTestCase {
+ RestOperations template = new RestTemplate();
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigIT.class);
+
+ @Override
+ public void testRestTransport() throws Exception {
+
+ testEnvironment();
+ testApplication();
+ testService();
+ testVersion();
+ testTag();
+ testOverride();
+ }
+
+ private void testOverride() {
+
+ putValue("/servicecomb/config/environment/production/application2.properties",
+ "testValue=t1");
+ putValue("/servicecomb/config/application/production/demo-consul/application2.properties",
+ "testValue=t2");
+ testGetConfig("testValue", "t2");
+ putValue("/servicecomb/config/service/production/demo-consul/provider/application2.properties",
+ "testValue=t3");
+ testGetConfig("testValue", "t3");
+ putValue("/servicecomb/config/version/production/demo-consul/provider/0.0.1/application2.properties",
+ "testValue=t4");
+ testGetConfig("testValue", "t4");
+ putValue("/servicecomb/config/tag/production/demo-consul/provider/0.0.1/tag1/application2.properties",
+ "testValue=t5");
+ testGetConfig("testValue", "t5");
+ }
+
+ private void testEnvironment() {
+
+ putValue("/servicecomb/config/environment/production/application.properties",
+ "test1=env");
+ putValue("/servicecomb/config/environment/production/application.properties",
+ "test1=env1");
+
+ testGetConfig("test1", "env1");
+ }
+
+
+ private void testApplication() {
+
+ putValue("/servicecomb/config/application/production/demo-consul/application.properties",
+ "test2=applition");
+ putValue("/servicecomb/config/application/production/demo-consul/application.properties",
+ "test2=applition2");
+ testGetConfig("test2", "applition2");
+ }
+
+ private void testService() {
+
+ putValue("/servicecomb/config/service/production/demo-consul/provider/application.properties",
+ "test3=service");
+ putValue("/servicecomb/config/service/production/demo-consul/provider/application.properties",
+ "test3=service3");
+ testGetConfig("test3", "service3");
+ }
+
+ private void testVersion() {
+
+ putValue("/servicecomb/config/version/production/demo-consul/provider/0.0.1/application.properties",
+ "test3=version");
+ putValue("/servicecomb/config/version/production/demo-consul/provider/0.0.1/application.properties",
+ "test4=version4");
+ testGetConfig("test4", "version4");
+ }
+
+ private void testTag() {
+
+ putValue("/servicecomb/config/tag/production/demo-consul/provider/0.0.1/tag1/application.properties",
+ "test5=tag");
+ putValue("/servicecomb/config/tag/production/demo-consul/provider/0.0.1/tag1/application.properties",
+ "test5=tag5");
+ testGetConfig("test5", "tag5");
+ }
+
+ public void putValue(String key, String value) {
+ try {
+ Consul.Builder builder = Consul.builder().withHostAndPort(HostAndPort.fromParts("127.0.0.1", 8500));
+ Consul consulClient = builder.build();
+ consulClient.keyValueClient().putValue(key, value);
+ LOGGER.info("Value set successfully:{}", value);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void testGetConfig(String key, String expectValue) {
+
+ String result = template
+ .getForObject(Config.GATEWAY_URL + "/getConfig?key=" + key, String.class);
+
+ for (int i = 0; i < 4; i++) {
+ if (StringUtils.equals(expectValue, result)) {
+ TestMgr.check(expectValue, result);
+ break;
+ }
+ SleepUtil.sleep(500, TimeUnit.MILLISECONDS);
+ }
+ }
+}
diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java
new file mode 100644
index 00000000000..1b129acc2c6
--- /dev/null
+++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java
@@ -0,0 +1,98 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class HeaderParamWithListSchemaIT implements CategorizedTestCase {
+ RestOperations template = new RestTemplate();
+
+ @Override
+ public void testRestTransport() throws Exception {
+ testHeaderListDefault();
+ testHeaderListMulti();
+ testHeaderListCSV();
+ testHeaderListSSV();
+ testHeaderListPipes();
+ }
+
+ // default to multi
+ private void testHeaderListDefault() {
+ MultiValueMap headers = new HttpHeaders();
+ headers.add("headerList", "a");
+ headers.add("headerList", "b");
+ headers.add("headerList", "c");
+ HttpEntity entity = new HttpEntity<>(headers);
+ String result = template
+ .exchange(Config.GATEWAY_URL + "/headerList/headerListDefault", HttpMethod.GET, entity, String.class).getBody();
+ TestMgr.check("3:[a, b, c]", result);
+ }
+
+ private void testHeaderListPipes() {
+ MultiValueMap headers = new HttpHeaders();
+ headers.add("headerList", "a|b|c");
+ HttpEntity entity = new HttpEntity<>(headers);
+ String result = template
+ .exchange(Config.GATEWAY_URL + "/headerList/headerListPIPES", HttpMethod.GET, entity, String.class).getBody();
+ TestMgr.check("3:[a, b, c]", result);
+ }
+
+ private void testHeaderListSSV() {
+ MultiValueMap headers = new HttpHeaders();
+ headers.add("headerList", "a b c");
+ HttpEntity entity = new HttpEntity<>(headers);
+ String result = template
+ .exchange(Config.GATEWAY_URL + "/headerList/headerListSSV", HttpMethod.GET, entity, String.class).getBody();
+ TestMgr.check("3:[a, b, c]", result);
+ }
+
+ private void testHeaderListCSV() {
+ MultiValueMap headers = new HttpHeaders();
+ headers.add("headerList", "a,b,c");
+ HttpEntity entity = new HttpEntity<>(headers);
+ String result = template
+ .exchange(Config.GATEWAY_URL + "/headerList/headerListCSV", HttpMethod.GET, entity, String.class).getBody();
+ TestMgr.check("3:[a, b, c]", result);
+
+ headers.add("headerList", "a, b, c");
+ entity = new HttpEntity<>(headers);
+ result = template
+ .exchange(Config.GATEWAY_URL + "/headerList/headerListCSV", HttpMethod.GET, entity, String.class).getBody();
+ TestMgr.check("3:[a, b, c]", result);
+ }
+
+ private void testHeaderListMulti() {
+ MultiValueMap headers = new HttpHeaders();
+ headers.add("headerList", "a");
+ headers.add("headerList", "b");
+ headers.add("headerList", "c");
+ HttpEntity entity = new HttpEntity<>(headers);
+ String result = template
+ .exchange(Config.GATEWAY_URL + "/headerList/headerListMULTI", HttpMethod.GET, entity, String.class).getBody();
+ TestMgr.check("3:[a, b, c]", result);
+ }
+}
diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
new file mode 100644
index 00000000000..97e883fb45f
--- /dev/null
+++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java
@@ -0,0 +1,68 @@
+/*
+ * 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.servicecomb.samples;
+
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.TestMgr;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+@Component
+public class HelloWorldIT implements CategorizedTestCase {
+ RestOperations template = new RestTemplate();
+
+ @Override
+ public void testRestTransport() throws Exception {
+ testHelloWorld();
+ testGetConfig();
+ }
+
+ private void testGetConfig() {
+ String result = template
+ .getForObject(Config.GATEWAY_URL + "/getConfig?key=key1", String.class);
+ TestMgr.check("1", result);
+ result = template
+ .getForObject(Config.GATEWAY_URL + "/getConfig?key=key2", String.class);
+ TestMgr.check("3", result);
+ result = template
+ .getForObject(Config.GATEWAY_URL + "/getConfig?key=key3", String.class);
+ TestMgr.check("5", result);
+ }
+
+ private void testHelloWorld() {
+ String result = template
+ .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class);
+ TestMgr.check("Hello World", result);
+
+ // test trace id added
+ MultiValueMap headers = new HttpHeaders();
+ headers.add("X-B3-TraceId", "81de2eb7691c2bbb");
+ HttpEntity