diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000000..185873ad02a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,33 @@ +name: Bug Report +description: Create a report to help us improve +title: "[BUG] - Issue Title" +labels: bug + +body: + - type: markdown + attributes: + value: "## Describe the bug\nA clear and concise description of what the bug is." + + - type: textarea + attributes: + label: Steps to Reproduce + description: "List the steps to reproduce the bug." + placeholder: "1. Go to '...'\n2. Click on '...'\n3. See error" + + - type: textarea + attributes: + label: Expected Behavior + description: "Describe the behavior you expected to see." + placeholder: "A clear and concise description of what you expected to happen." + + - type: input + attributes: + label: Servicecomb Version + description: "Please provide your Servicecomb version" + placeholder: "3.2.4" + + - type: textarea + attributes: + label: Additional Context + description: "Add any other context about the problem here." + placeholder: "Any additional information that might help us debug the issue." diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000000..16fd2512ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,18 @@ +blank_issues_enabled: false +contact_links: + - name: "Contact Support" + url: "mailto:dev@servicecomb.apache.org" + about: "If you need help, please contact us." +templates: + - name: "Bug Report" + description: "Report a bug or issue." + filename: "bug_report.yml" + - name: "Feature Request" + description: "Request a new feature or improvement." + filename: "feature_request.yml" + - name: "Documentation Issue" + description: "Report an issue with documentation." + filename: "documentation_issue.yml" + - name: "Question" + description: "Ask a question or seek help." + filename: "question.yml" diff --git a/.github/ISSUE_TEMPLATE/documentation_issue.yml b/.github/ISSUE_TEMPLATE/documentation_issue.yml new file mode 100644 index 00000000000..94ef3490041 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation_issue.yml @@ -0,0 +1,27 @@ +name: Documentation Issue +description: Report an issue with the documentation +title: "[DOCUMENTATION] - Documentation Issue Title" +labels: documentation + +body: + - type: markdown + attributes: + value: "## Describe the documentation issue\nA clear and concise description of the issue with the documentation." + + - type: textarea + attributes: + label: Location in documentation + description: "Please provide the URL or section where the issue appears." + placeholder: "e.g. https://docs.example.com/section" + + - type: textarea + attributes: + label: What should be changed? + description: "Please describe what changes or improvements should be made to the documentation." + placeholder: "Explain how we can improve the content." + + - type: textarea + attributes: + label: Additional Context + description: "Provide any other context or examples here." + placeholder: "Additional comments or suggestions for the documentation." diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000000..3a44565e0b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,33 @@ +name: Feature Request +description: Suggest an idea or feature for this project +title: "[FEATURE] - Feature Title" +labels: enhancement + +body: + - type: markdown + attributes: + value: "## Describe the feature request\nA clear and concise description of what you want to be added to the project." + + - type: textarea + attributes: + label: Problem this feature would solve + description: "Please describe the problem or challenge you're facing." + placeholder: "Explain why this feature would be helpful." + + - type: textarea + attributes: + label: Describe the solution + description: "How do you envision this feature working?" + placeholder: "Provide a description of how the feature would solve the problem." + + - type: textarea + attributes: + label: Alternatives considered + description: "Have you considered other solutions or alternatives? If yes, describe them." + placeholder: "Provide any alternative solutions you've thought about." + + - type: textarea + attributes: + label: Additional Context + description: "Any other context or information that might help us implement this feature." + placeholder: "Include any links, mockups, or additional details." diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 00000000000..af3f350b518 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,27 @@ +name: General Question +description: Ask a general question related to the project +title: "[QUESTION] - Question Title" +labels: question + +body: + - type: markdown + attributes: + value: "## What is your question?\nDescribe the question or issue you are facing. Be as specific as possible." + + - type: textarea + attributes: + label: Steps to reproduce (if applicable) + description: "If your question is about a specific problem or bug, please include steps to reproduce it." + placeholder: "Provide steps, if applicable." + + - type: textarea + attributes: + label: What have you tried so far? + description: "Please explain what you have already tried to resolve the issue or answer the question." + placeholder: "Describe the steps you've taken." + + - type: textarea + attributes: + label: Additional context + description: "Provide any other context or information related to the question." + placeholder: "Include any relevant links or background information." diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..7f7754fc299 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,29 @@ +# +# 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. +# +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "monthly" + open-pull-requests-limit: 20 diff --git a/.github/workflows/checkstyle.yml b/.github/workflows/checkstyle.yml new file mode 100644 index 00000000000..3f97b9f1818 --- /dev/null +++ b/.github/workflows/checkstyle.yml @@ -0,0 +1,38 @@ +# +# 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. +# + +name: checkstyle +on: + pull_request: + branches: + - master + +jobs: + checkstyle: + timeout-minutes: 60 + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: Set up jdk + uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: 'temurin' + - name: checkstyle + run: mvn checkstyle:check -B -Pit diff --git a/.github/workflows/linelint.yml b/.github/workflows/linelint.yml new file mode 100644 index 00000000000..8d5112ea3d6 --- /dev/null +++ b/.github/workflows/linelint.yml @@ -0,0 +1,35 @@ +# +# 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. +# + +name: line lint +on: + pull_request: + branches: + - master + +jobs: + linelint: + timeout-minutes: 60 + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: install linelint + run: cargo install linelint-cli + - name: Run linelint check + run: linelint check diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index b86bfb6d3e2..24118c35c99 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -1,5 +1,21 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven +# +# 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. +# name: Java CI with Maven @@ -12,21 +28,25 @@ on: jobs: build: - runs-on: ubuntu-latest + timeout-minutes: 60 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 - - name: Set up JDK 1.8 - uses: actions/setup-java@v1 + - uses: actions/checkout@v6 + - name: Set up jdk + uses: actions/setup-java@v5 with: - java-version: 1.8 - - uses: actions/cache@v2 + java-version: '17.0.8' + distribution: 'temurin' + - name: Set up Maven + uses: stCarolas/setup-maven@v5 + with: + maven-version: 3.9.9 + - uses: actions/cache@v5 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Compilation and Installation - run: bash scripts/build.sh install - - name: publish coverage report - run: bash <(curl -s https://codecov.io/bash) + run: mvn clean verify -Dcheckstyle.skip=true -B -Pdocker -Pjacoco -Pit -Pcoverage diff --git a/.github/workflows/rat_check.yml b/.github/workflows/rat_check.yml new file mode 100644 index 00000000000..c2db2508fea --- /dev/null +++ b/.github/workflows/rat_check.yml @@ -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. +# + +name: rat check +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + rat_check: + timeout-minutes: 60 + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + - name: Set up jdk + uses: actions/setup-java@v5 + with: + java-version: '17' + distribution: 'temurin' + - name: rat check + run: mvn apache-rat:check -B -Pit,release diff --git a/.github/workflows/typo_check.yml b/.github/workflows/typo_check.yml new file mode 100644 index 00000000000..999530a79f7 --- /dev/null +++ b/.github/workflows/typo_check.yml @@ -0,0 +1,38 @@ +# +# 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. +# + +name: typo check +on: + pull_request: + branches: + - master + +jobs: + typo-check: + timeout-minutes: 60 + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v6 + # To run the typo check locally, you can follow these steps: + # 1. Install typos locally using cargo: + # cargo install typos-cli + # 2. Run the typo check with the following command: + # typos + - name: Check typos + uses: crate-ci/typos@v1.38.1 diff --git a/.typos.toml b/.typos.toml new file mode 100644 index 00000000000..e8b6eb33f39 --- /dev/null +++ b/.typos.toml @@ -0,0 +1,38 @@ +# +# 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. +# + +[default.extend-words] +"fo" = "fo" +"VERTX" = "VERTX" +"Vertx" = "Vertx" +"vertx" = "vertx" + +[files] +extend-exclude = [ + "**/cobertura.ser" +] +[default] +extend-ignore-words-re = [ + "Verticle", + "verticle", + "VERTICLE", + "Prelease", + "cobertura", + "ser", +] diff --git a/LICENSE b/LICENSE index 521832a32a7..7898c758729 100644 --- a/LICENSE +++ b/LICENSE @@ -222,12 +222,6 @@ For swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecom This product bundles files from swagger which is licensed under the Apache License v2. For details, see https://github.com/swagger-api/swagger-core -================================================================ -For handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixCommandPropertiesExt.java -================================================================ -This product bundles files from Hystrix which is licensed under the Apache License v2. -For details, see https://github.com/Netflix/Hystrix - ================================================================ For foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/ArrayFieldMapEx.java foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/FieldMapEx.java @@ -244,4 +238,11 @@ For foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/ArrayFie foundations/foundation-protobuf/src/main/java/io/protostuff/SchemaWriter.java ================================================================ This product bundles files from protostuff which is licensed under the Apache License v2. -For details, see https://github.com/protostuff/protostuff \ No newline at end of file +For details, see https://github.com/protostuff/protostuff + +================================================================ +For foundations/foundation-protobuf/src/main/resources/google/protobuf/any.proto +For foundations/foundation-protobuf/src/main/resources/google/protobuf/empty.proto +================================================================ +This product bundles files from swagger which is licensed under the BSD-3-Clause. +For details, see https://github.com/protocolbuffers/protobuf diff --git a/NOTICE b/NOTICE index 8b2f6ccd80c..e4df59ae99a 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache ServiceComb Java Chassis -Copyright 2017-2021 The Apache Software Foundation +Copyright 2017-2025 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/README.md b/README.md index 5ba06325cd7..b2fbc167625 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,91 @@ -# Java Chassis [中文](README_ZH.md) [![Build Status](https://travis-ci.org/apache/servicecomb-java-chassis.svg?branch=master)](https://travis-ci.org/apache/servicecomb-java-chassis?branch=master) [![Coverage Status](https://coveralls.io/repos/github/apache/servicecomb-java-chassis/badge.svg?branch=master)](https://coveralls.io/github/apache/servicecomb-java-chassis?branch=master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.servicecomb/java-chassis-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Corg.apache.servicecomb) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![Gitter](https://img.shields.io/badge/ServiceComb-Gitter-ff69b4.svg)](https://gitter.im/ServiceCombUsers/Lobby) +# Java Chassis [中文](README_ZH.md) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.servicecomb/java-chassis-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Corg.apache.servicecomb) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) -Apache ServiceComb Java Chassis is a Software Development Kit (SDK) for rapid development of microservices in Java, providing service registration, service discovery, dynamic routing, and service management features +Apache ServiceComb Java Chassis is a Software Development Kit (SDK) for rapid development of microservices in Java, providing service registration, service discovery, dynamic routing, and service management features. -# Why use Java Chassis +> If you find this project helpful, please don't forget to `star` it. -- **High performance** +# releases - The transport capability of Java Chassis is based on [Vert.x](https://vertx.io), which enables Java Chassis to process - massive requests with relatively less hardware resources, and support [reactive develop style](https://www.reactivemanifesto.org). +| Release Train | Latest Version | Compiled JDK Version | Tested JDK Version | Open API | Notes | +|----------------|----------------|----------------------|--------------------|----------|--------------------------| +| Java Chassis 3 | 3.3.0 | OpenJDK 17 | OpenJDK 17 | 3.0.x | Depends on Spring Boot 3 | +| Java Chassis 2 | 2.8.24 | OpenJDK 8 | OpenJDK 8, 11, 17 | 2.0.x | Depends on Spring 5 | +| Java Chassis 1 | 1.3.11 | OpenJDK 8 | OpenJDK 8 | 2.0.x | End of Support | -- **Native support for OpenAPI** +Java Chassis core dependencies - Java Chassis describes the APIs of the microservices via [Swagger](https://swagger.io) natively, to help - developers to design microservices that comply to [OpenAPI standard](https://swagger.io/specification/v2/). +| Java Chassis | Spring Boot | Vert.x | Swagger | Jackson | +|--------------|-------------|--------|---------|---------| +| 3.3.x | 3.4.x | 4.5.x | 2.2.x | 2.18.x | +| 3.2.x | 3.3.x | 4.5.x | 2.2.x | 2.18.x | -- **Flexible develop style** +> NOTICE: Since Open API 3.0.x is not compatible with 2.0.x, Java Chassis 2 and Java Chassis 1 can not +> work together with Java Chassis 3. All related consumers, providers and edge service need use Java Chassis 3 when upgrading. - Currently Java Chassis allow developers to develop their microservice APIs in `SpringMVC`/`JAX-RS`/`transparent RPC` styles, - and to send the request in `RPC`/`RestTemplate` styles. And there are three kind of build-in transport mode: - `Rest over Vertx`/`Rest over Servlet`/`Highway`. All of these features can be combined and replaced easily, - because they are decoupled and all based on the Swagger schema, which can provide high flexibility. +> NOTICE: Java Chassis 1 reached its end of support now after it's first release from 2018. -- **Out-of-box microservice governance features** - - Java Chassis provides a lot of features for microservice governance and monitor. - -- **Multi languages support** +# Quick Start - Via [ServiceComb Mesher](https://github.com/apache/servicecomb-mesher), the microservices - built by other languages are also able to work with ServiceComb components. And Java Chassis can communicate with such - microservices and make use of the built-in capabilities. +* Define API +```java +@RequestMapping(path = "/provider") +public interface ProviderService { + @GetMapping("/sayHello") + String sayHello(@RequestParam("name") String name); +} +``` -# Quick Start +* Provider service +```java +@RestSchema(schemaId = "ProviderController", schemaInterface = ProviderService.class) +public class ProviderController implements ProviderService { + @Override + public String sayHello(String name) { + return "Hello " + name; + } +} +``` -Provider service: +* Consumer service ```java -import org.apache.servicecomb.*; -@RpcSchema(schemaId = "helloworld") -public class HelloWorldProvider implements HelloWorld { - public String sayHello(String name) { - return "Hello " + name; - } +@Configuration +public class ProviderServiceConfiguration { + @Bean + public ProviderService providerService() { + return Invoker.createProxy("provider", "ProviderController", ProviderService.class); + } } ``` -Consumer service: +Invoke Provider service with RPC ```java -import org.apache.servicecomb.*; -@Component -public class HelloWorldConsumer { - @RpcReference(microserviceName = "pojo", schemaId = "helloworld") - private static HelloWorld helloWorld; - - public static void main(String[] args) { - helloWorld.sayHello("Tank"); - } +@RestSchema(schemaId = "ConsumerController", schemaInterface = ConsumerService.class) +public class ConsumerController implements ConsumerService { + private ProviderService providerService; + + @Autowired + public void setProviderService(ProviderService providerService) { + this.providerService = providerService; + } + + @Override + public String sayHello(String name) { + return providerService.sayHello(name); + } } ``` +Try out this example [here](https://servicecomb.apache.org/references/java-chassis/zh_CN/start/first-sample.html) . + # Documentation Project documentation is available on the [ServiceComb Java Chassis Developer Guide][java-chassis-developer-guide]. -[java-chassis-developer-guide]: http://servicecomb.gitee.io/servicecomb-java-chassis-doc/java-chassis/ +[java-chassis-developer-guide]: https://servicecomb.apache.org/references/java-chassis/zh_CN/ # Building -You don’t need to build from source to use Java Chassis (binaries in apache nexus ), but if you want to try out the latest and greatest, Java Chassis can be easily built with the maven. You also need JDK 1.8. + You don’t need to build from source to use Java Chassis (binaries in apache nexus ), but if you want to try out the latest and greatest, Java Chassis can be easily built with the maven. You also need JDK 17. mvn clean install @@ -76,17 +95,11 @@ The first build may take a longer than expected as Maven downloads all the depen To build the docker image and run the integration tests with docker, you can use maven docker profile - mvn clean install -Pdocker -Pit -Pdemo-run-release + mvn clean install -Pdocker -Pit If you are using docker machine, please use the following command - mvn clean install -Pdocker -Pit -Pdocker-machine -Pdemo-run-release - - -# Get The Latest Release - -[Download Java-Chassis](http://servicecomb.apache.org/release/java-chassis-downloads/) - + mvn clean install -Pdocker -Pit -Pdocker-machine # Contact @@ -101,13 +114,3 @@ See [CONTRIBUTING](http://servicecomb.apache.org/developers/contributing) for de # License Licensed under an [Apache 2.0 license](LICENSE). - -# Export Notice - -This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See for more information. - -The Apache Software Foundation has classified this software as Export Commodity Control Number (ECCN) 5D002, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this Apache Software Foundation distribution makes it eligible for export under the "publicly available" Section 742.15(b) exemption (see the BIS Export Administration Regulations, Section 742.15(b)) for both object code and source code. - -The following provides more details on the included cryptographic software: - - * Vertx transport can be configured for secure communications diff --git a/README_ZH.md b/README_ZH.md index 5a4f89b99e0..bfae9746c2b 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -1,70 +1,102 @@ -# Java Chassis | [English](README.md) [![Build Status](https://travis-ci.org/apache/servicecomb-java-chassis.svg?branch=master)](https://travis-ci.org/apache/servicecomb-java-chassis?branch=master) [![Coverage Status](https://coveralls.io/repos/github/apache/servicecomb-java-chassis/badge.svg?branch=master)](https://coveralls.io/github/apache/servicecomb-java-chassis?branch=master) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.servicecomb/java-chassis-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Corg.apache.servicecomb) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) [![Gitter](https://img.shields.io/badge/ServiceComb-Gitter-ff69b4.svg)](https://gitter.im/ServiceCombUsers/Lobby) +# Java Chassis | [English](README.md) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.servicecomb/java-chassis-core/badge.svg)](http://search.maven.org/#search%7Cga%7C1%7Corg.apache.servicecomb) [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html) Apache ServiceComb Java Chassis 给开发者提供一个快速构建微服务的JAVA SDK。它包含如下特性: -* 多种开发风格,REST(JAX-RS、Spring MVC)和RPC -* 多种通信协议, HTTP over Vert.x、Http Over Servlet、Highway等 -* 统一一致的服务提供者、服务消费者处理链,以及基于契约的开箱即用的服务治理能力 +* 基于Open API的契约优先(API First)开发模式,满足开发过程可管理、开发规范可验证要求。 +* 多种开发风格,REST(JAX-RS、Spring MVC)和RPC等,高效支持遗留系统迁移和新系统开发场景。 +* 多种通信协议, HTTP over Vert.x、Http Over Servlet、Highway等,满足不同场景对于性能、韧性的需求。 +* 统一一致的服务提供者、服务消费者处理链,易于扩展新功能。 +* 提供服务发现、配置管理、熔断、限流、灰度发布等开箱即用的服务治理能力。 -开发者可以通过[设计选型参考][design]了解更多特性和设计原理。 +可以通过[设计选型参考](https://servicecomb.apache.org/references/java-chassis/zh_CN/start/design.html) 了解更多特性和设计原理。 -[design]: http://servicecomb.gitee.io/servicecomb-java-chassis-doc/java-chassis/zh_CN/start/design/ +> 如果发现项目能帮助到您,别忘了点击右上角`star`表示鼓励。 -# 为什么使用Java Chassis +# 发布版本 -- **高性能** +| 版本火车 | 最新版本 | 编译的JDK版本 | 支持的JDK版本 | Open API | 备注 | +|----------------|--------|------------|-------------------|----------|-----------------| +| Java Chassis 3 | 3.3.0 | OpenJDK 17 | OpenJDK 17 | 3.0.x | 依赖Spring Boot 3 | +| Java Chassis 2 | 2.8.24 | OpenJDK 8 | OpenJDK 8, 11, 17 | 2.0.x | 依赖Spring 5 | +| Java Chassis 1 | 1.3.11 | OpenJDK 8 | OpenJDK 8 | 2.0.x | 停止更新 | - Java Chassis 网络层基于 [Vert.x](https://vertx.io) 实现, 支持开发者使用[响应式编程](https://www.reactivemanifesto.org), 开发者在使用熟悉的REST风格设计业务接口的时候,也能够获取到非常高性能的吞吐量。同时还提供了Highway协议,满足更高性能场景的要求。 +Java Chassis 的核心依赖 -- **原生支持OpenAPI** +| Java Chassis | Spring Boot | Vert.x | Swagger | Jackson | +|--------------|-------------|--------|---------|---------| +| 3.3.x | 3.4.x | 4.5.x | 2.2.x | 2.18.x | +| 3.2.x | 3.3.x | 4.5.x | 2.2.x | 2.18.x | - Java Chassis 的接口开发、服务治理都基于 [Swagger](https://swagger.io) ,并通过接口语义检查,使得接口定义符合 [OpenAPI 规范](https://swagger.io/specification/v2/). +> NOTICE: Open API 3.0.x 不兼容 2.0.x, 因此Java Chassis 2、Java Chassis 1不能与Java Chassis 3共存互访. 升级Java Chassis 3, 需要将相关的消费者、提供者和边缘服务同时升级. -- **灵活的开发方式** +> NOTICE: Java Chassis 1 第一个版本于2018发布,已经停止更新. - 开发者可以使用 `SpringMVC`/`JAX-RS`/`transparent RPC` 任意一种方式定义服务端接口, 并使用`RPC`/`RestTemplate` 等方式访问这些接口. 得益于Java Chassis的通信层与开发方式分离的设计,开发者可以在 `Rest over Vertx`/`Rest over Servlet`/`Highway`等通信模式下自由切换. +# 快速开始 -- **开箱即用的服务治理能力** +* 定义服务契约 - Java Chassis 提供了大量开箱即用的服务治理能力,包括服务发现、熔断容错、负载均衡、流量控制等。 +```java +@RequestMapping(path = "/provider") +public interface ProviderService { + @GetMapping("/sayHello") + String sayHello(@RequestParam("name") String name); +} +``` +* 定义提供者 -# 快速开始 +```java +@RestSchema(schemaId = "ProviderController", schemaInterface = ProviderService.class) +public class ProviderController implements ProviderService { + @Override + public String sayHello(String name) { + return "Hello " + name; + } +} +``` + +* 定义消费者 -定义提供者: ```java -import org.apache.servicecomb.*; -@RpcSchema(schemaId = "helloworld") -public class HelloWorldProvider implements HelloWorld { - public String sayHello(String name) { - return "Hello " + name; - } +@Configuration +public class ProviderServiceConfiguration { + @Bean + public ProviderService providerService() { + return Invoker.createProxy("provider", "ProviderController", ProviderService.class); + } } ``` -定义消费者: +使用RPC方式访问提供者。 + ```java -import org.apache.servicecomb.*; -@Component -public class HelloWorldConsumer { - @RpcReference(microserviceName = "pojo", schemaId = "helloworld") - private static HelloWorld helloWorld; - - public static void main(String[] args) { - helloWorld.sayHello("Tank"); - } +@RestSchema(schemaId = "ConsumerController", schemaInterface = ConsumerService.class) +public class ConsumerController implements ConsumerService { + private ProviderService providerService; + + @Autowired + public void setProviderService(ProviderService providerService) { + this.providerService = providerService; + } + + @Override + public String sayHello(String name) { + return providerService.sayHello(name); + } } ``` +下载并体验上述[示例项目](https://servicecomb.apache.org/references/java-chassis/zh_CN/start/first-sample.html) . + # 用户文档 请访问 [ServiceComb Java Chassis 开发指南][java-chassis-developer-guide]. -[java-chassis-developer-guide]: http://servicecomb.gitee.io/servicecomb-java-chassis-doc/java-chassis/ +[java-chassis-developer-guide]: https://servicecomb.apache.org/references/java-chassis/zh_CN/ -# 编译Java Chassis +# 编译 Java Chassis -开发者可以通过公有mavan仓库使用Java Chassis。 如果需要构建项目,需要使用JDK 8版本,并预先安装maven。 +开发者可以通过MAVEN仓库使用Java Chassis。 如果需要构建项目,需要使用JDK 17版本,并预先安装maven。 mvn clean install @@ -72,23 +104,17 @@ public class HelloWorldConsumer { 开发者需要预先安装docker。 - mvn clean install -Pdocker -Pit -Pdemo-run-release + mvn clean install -Pdocker -Pit 使用docker machine。 - mvn clean install -Pdocker -Pit -Pdocker-machine -Pdemo-run-release - - -# 获取最新版本 - -[下载链接](http://servicecomb.apache.org/cn/release/java-chassis-downloads/) + mvn clean install -Pdocker -Pit -Pdocker-machine # 联系我们 -Bugs: [issues](https://issues.apache.org/jira/browse/SCB) - -mailing list: [subscribe](mailto:dev-subscribe@servicecomb.apache.org) [dev](https://lists.apache.org/list.html?dev@servicecomb.apache.org) +报告缺陷: [issues](https://issues.apache.org/jira/browse/SCB) +邮件列表: [subscribe](mailto:dev-subscribe@servicecomb.apache.org) [dev](https://lists.apache.org/list.html?dev@servicecomb.apache.org) # 参与代码提交 @@ -96,13 +122,3 @@ mailing list: [subscribe](mailto:dev-subscribe@servicecomb.apache.org) [dev](ht # License Licensed under an [Apache 2.0 license](LICENSE). - -# Export Notice - -This distribution includes cryptographic software. The country in which you currently reside may have restrictions on the import, possession, use, and/or re-export to another country, of encryption software. BEFORE using any encryption software, please check your country's laws, regulations and policies concerning the import, possession, or use, and re-export of encryption software, to see if this is permitted. See for more information. - -The Apache Software Foundation has classified this software as Export Commodity Control Number (ECCN) 5D002, which includes information security software using or performing cryptographic functions with asymmetric algorithms. The form and manner of this Apache Software Foundation distribution makes it eligible for export under the "publicly available" Section 742.15(b) exemption (see the BIS Export Administration Regulations, Section 742.15(b)) for both object code and source code. - -The following provides more details on the included cryptographic software: - - * Vertx transport can be configured for secure communications diff --git a/archetypes/README.md b/archetypes/README.md deleted file mode 100644 index d108c68241a..00000000000 --- a/archetypes/README.md +++ /dev/null @@ -1,52 +0,0 @@ -## ServiceComb Java Chassis Archetypes -### What's maven archetypes -From http://maven.apache.org/guides/introduction/introduction-to-archetypes.html : - ->In short, Archetype is a Maven project templating toolkit. An archetype is defined as an original pattern or model from which all other things of the same kind are made. The name fits as we are trying to provide a system that provides a consistent means of generating Maven projects. Archetype will help authors create Maven project templates for users, and provides users with the means to generate parameterized versions of those project templates. - -### What we provide -1. business-service-jaxrs - - Archetype for create a common microservice using jaxrs provider. - -2. business-service-springmvc - - Archetype for create a common microservice using springmvc provider. - -3. business-service-pojo - - Archetype for create a common microservice using pojo provider. - -4. business-service-spring-boot2-starter - - Archetype for create a common microservice using spring-boot-starter provider. - -### How to build these archetypes -We use **business-service-jaxrs** as an example : - -```bash -cd archetypes -mvn install -``` - -### How to use these archetypes to generate a project -We use **business-service-jaxrs** as an example : -#### Generate via IntelliJ IDEA -New Project(Module) -> Maven -> Check "Create from archetype" -> Add Archetype... -> fill *GroupId* with value "org.apache.servicecomb.archetypes", fill *ArtifactId* with value "business-service-jaxrs-archetype", fill *Version* with current archetype version -> select this archetype that had listed, do next steps. - -#### Generate via Eclipse -New Project(Module) -> Maven -> Next -> Add Archetype... -> fill *GroupId* with value "org.apache.servicecomb.archetypes", fill *ArtifactId* with value "business-service-jaxrs-archetype", fill *Version* with current archetype version -> select this archetype that had listed, do next steps. - -#### Generate via command - -```bash -mvn archetype:generate -DarchetypeGroupId=org.apache.servicecomb.archetypes -DarchetypeArtifactId=business-service-jaxrs-archetype -DarchetypeVersion=${archetype-version} -``` - -In console Interactive mode, input your GroupId, ArtifactId and Version of new project(module), after a while the new project will be generated. - -*Notice: We will publish these archetypes to maven center repository since 1.0.0-m2, if you would like to use an archetype from an unreleased version, must use `archetypeRepository` option in the version 2.4 of archetype-plugin in order to set maven repository to apache snapshot groups: * - -```bash -mvn org.apache.maven.plugins:maven-archetype-plugin:2.4:generate -DarchetypeGroupId=org.apache.servicecomb.archetypes -DarchetypeArtifactId=business-service-jaxrs-archetype -DarchetypeVersion=1.0.0-SNAPSHOT -DarchetypeRepository=https://repository.apache.org/content/groups/snapshots-group -``` \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/README.md b/archetypes/business-service-jaxrs/README.md deleted file mode 100644 index 0f1c6221030..00000000000 --- a/archetypes/business-service-jaxrs/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-jaxrs-archetype*, it use **jaxrs provider** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-jax-rs/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ -3. Modify setting value of "mainClass" in pom.xml for package. - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get outputs in target folder: -- lib : contains all dependencies jars -- xxxxxx-{version}.jar -```bash -java -jar xxxxxx-{version}.jar -``` -*Notice: If you need to modify configurations in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can directly place a new "microservice.yaml" file under the same folder, then configurations will be overridden.*** \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/pom.xml b/archetypes/business-service-jaxrs/pom.xml deleted file mode 100644 index db45b1361a5..00000000000 --- a/archetypes/business-service-jaxrs/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - org.apache.servicecomb - archetypes - 2.6.0-SNAPSHOT - - - org.apache.servicecomb.archetypes - Java Chassis::Archetypes::JAXRS - business-service-jaxrs-archetype - maven-archetype - 4.0.0 - - - 2.3 - - - - - - org.apache.maven.archetype - archetype-packaging - ${maven-archetype-packaging-version} - - - - - - src/main/resources - false - - - src/main/resources-filtered - true - - **/archetype-metadata.xml - - - - - \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml b/archetypes/business-service-jaxrs/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml deleted file mode 100644 index e953ae8b716..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - src/main/java - - **/*.java - - - - src/main/resources - - **/* - - - - - - README.md - - - - \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/README.md b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/README.md deleted file mode 100644 index 2f34861a897..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-jaxrs-archetype*, it use **jaxrs provider** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-jax-rs/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ -3. Modify setting value of "mainClass" in pom.xml for package. - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get outputs in target folder: -- lib : contains all dependencies jars -- xxxxxx-{version}.jar -```bash -java -jar xxxxxx-{version}.jar -``` -*Notice: If you need to modify config setting in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can direct place a new "microservice.yaml" file in same folder, then settings will be overridden.*** \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/pom.xml b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/pom.xml deleted file mode 100644 index a1286149213..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/pom.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - ${groupId} - ${artifactId} - ${version} - 4.0.0 - - - UTF-8 - - 2.0.0 - - - - - - org.apache.servicecomb - java-chassis-dependencies - ${java-chassis.version} - pom - import - - - - - - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-highway - - - org.apache.servicecomb - provider-jaxrs - - - org.apache.logging.log4j - log4j-slf4j-impl - - - org.apache.logging.log4j - log4j-api - - - org.apache.logging.log4j - log4j-core - - - - - org.apache.servicecomb - provider-springmvc - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - - true - lib/ - - ${package}.Application - - - . - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - target/lib - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - - - - \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/Application.java b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/Application.java deleted file mode 100644 index 226a6c443d7..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/Application.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; - -public class Application { - public static void main(String[] args) throws Exception { - BeanUtils.init(); - } -} diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java deleted file mode 100644 index b6eb1e39aa4..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.web.client.RestTemplate; - -public class HelloConsumer { - private final RestTemplate restTemplate = RestTemplateBuilder.create(); - - public void invokeHello() { - //service url is : cse://serviceName/operation - restTemplate.getForObject("cse://business-service/hello", String.class); - } -} diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/HelloImpl.java b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/HelloImpl.java deleted file mode 100644 index 85bdacd3855..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/java/HelloImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 ${package}; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; - -import org.apache.servicecomb.provider.rest.common.RestSchema; - -@RestSchema(schemaId = "hello") -@Path("/") -public class HelloImpl { - - @Path("/hello") - @GET - public String hello() { - return "Hello World!"; - } -} diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/resources/log4j2.xml b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/resources/log4j2.xml deleted file mode 100644 index 2ec46303765..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/resources/log4j2.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - ./target/log - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/resources/microservice.yaml b/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/resources/microservice.yaml deleted file mode 100644 index cbed0862768..00000000000 --- a/archetypes/business-service-jaxrs/src/main/resources/archetype-resources/src/main/resources/microservice.yaml +++ /dev/null @@ -1,43 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -#More details can be found : -# 1.http://servicecomb.apache.org/users/service-definition/ -# 2.http://servicecomb.apache.org/users/service-configurations/ -# 3.http://servicecomb.apache.org/users/communicate-protocol/ - -#Indicates an application name -APPLICATION_ID: business -service_description: -#Indicates a microservice name -#The microservice name should be unique within an application. -#The name can contain digits, uppercase and lowercase letters, hyphens(-), underscores(_), and periods(.); and can neither start nor end with punctuations. -#The naming rule is as follows: ^[a-zA-Z0-9]+$|^[a-zA-Z0-9][a-zA-Z0-9_-.]*[a-zA-Z0-9]$. - name: business-service -#Indicates a service version - version: 1.0.0 -servicecomb: - service: - #Specifies the service center IP address. - registry: - address: http://127.0.0.1:30100 - #Specifies the rest transport listening IP address. - rest: - address: 0.0.0.0:8080 - #Specifies the highway transport listening IP address. - highway: - address: 0.0.0.0:7070 \ No newline at end of file diff --git a/archetypes/business-service-pojo/README.md b/archetypes/business-service-pojo/README.md deleted file mode 100644 index 333d938b14b..00000000000 --- a/archetypes/business-service-pojo/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-pojo-archetype*, it use **pojo provider** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-transparent-rpc/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ -3. Modify setting value of "mainClass" in pom.xml for package. - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get outputs in target folder: -- lib : contains all dependencies jars -- xxxxxx-{version}.jar -```bash -java -jar xxxxxx-{version}.jar -``` -*Notice: If you need to modify configurations in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can directly place a new "microservice.yaml" file under the same folder, then configurations will be overridden.*** \ No newline at end of file diff --git a/archetypes/business-service-pojo/pom.xml b/archetypes/business-service-pojo/pom.xml deleted file mode 100644 index f0ad34bfefe..00000000000 --- a/archetypes/business-service-pojo/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - org.apache.servicecomb - archetypes - 2.6.0-SNAPSHOT - - - org.apache.servicecomb.archetypes - Java Chassis::Archetypes::POJO - business-service-pojo-archetype - maven-archetype - 4.0.0 - - - 2.3 - - - - - - org.apache.maven.archetype - archetype-packaging - ${maven-archetype-packaging-version} - - - - - - src/main/resources - false - - - src/main/resources-filtered - true - - **/archetype-metadata.xml - - - - - \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml b/archetypes/business-service-pojo/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml deleted file mode 100644 index e953ae8b716..00000000000 --- a/archetypes/business-service-pojo/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - src/main/java - - **/*.java - - - - src/main/resources - - **/* - - - - - - README.md - - - - \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/README.md b/archetypes/business-service-pojo/src/main/resources/archetype-resources/README.md deleted file mode 100644 index 003255e3665..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-pojo-archetype*, it use **pojo provider** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-transparent-rpc/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ -3. Modify setting value of "mainClass" in pom.xml for package. - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get outputs in target folder: -- lib : contains all dependencies jars -- xxxxxx-{version}.jar -```bash -java -jar xxxxxx-{version}.jar -``` -*Notice: If you need to modify config setting in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can direct place a new "microservice.yaml" file in same folder, then settings will be overridden.*** \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/pom.xml b/archetypes/business-service-pojo/src/main/resources/archetype-resources/pom.xml deleted file mode 100644 index f2aa06d39de..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/pom.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - - ${groupId} - ${artifactId} - ${version} - 4.0.0 - - - UTF-8 - - 2.0.0 - - - - - - org.apache.servicecomb - java-chassis-dependencies - ${java-chassis.version} - pom - import - - - - - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-highway - - - org.apache.servicecomb - provider-pojo - - - org.apache.logging.log4j - log4j-slf4j-impl - - - org.apache.logging.log4j - log4j-api - - - org.apache.logging.log4j - log4j-core - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - - true - lib/ - - ${package}.Application - - - . - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - target/lib - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - - - - \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/Application.java b/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/Application.java deleted file mode 100644 index 3e1feaec169..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/Application.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; - -public class Application { - public static void main(String[] args) throws Exception { - BeanUtils.init(); - } -} \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/Hello.java b/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/Hello.java deleted file mode 100644 index 178c7607274..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/Hello.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 ${package}; - -public interface Hello { - String hello(); -} \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java b/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java deleted file mode 100644 index 1d42d58ca51..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.pojo.RpcReference; -import org.springframework.stereotype.Component; - -@Component -public class HelloConsumer { - @RpcReference(microserviceName = "business-service", schemaId = "hello") - private Hello hello; - - public Hello getHello() { - return hello; - } - - public void invokeHello() { - getHello().hello(); - } -} \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/HelloImpl.java b/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/HelloImpl.java deleted file mode 100644 index b34fe10a2cd..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/java/HelloImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.pojo.RpcSchema; - -@RpcSchema(schemaId = "hello") -public class HelloImpl implements Hello { - - public String hello() { - return "Hello World!"; - } -} \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/resources/log4j2.xml b/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/resources/log4j2.xml deleted file mode 100644 index 2ec46303765..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/resources/log4j2.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - ./target/log - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/resources/microservice.yaml b/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/resources/microservice.yaml deleted file mode 100644 index cbed0862768..00000000000 --- a/archetypes/business-service-pojo/src/main/resources/archetype-resources/src/main/resources/microservice.yaml +++ /dev/null @@ -1,43 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -#More details can be found : -# 1.http://servicecomb.apache.org/users/service-definition/ -# 2.http://servicecomb.apache.org/users/service-configurations/ -# 3.http://servicecomb.apache.org/users/communicate-protocol/ - -#Indicates an application name -APPLICATION_ID: business -service_description: -#Indicates a microservice name -#The microservice name should be unique within an application. -#The name can contain digits, uppercase and lowercase letters, hyphens(-), underscores(_), and periods(.); and can neither start nor end with punctuations. -#The naming rule is as follows: ^[a-zA-Z0-9]+$|^[a-zA-Z0-9][a-zA-Z0-9_-.]*[a-zA-Z0-9]$. - name: business-service -#Indicates a service version - version: 1.0.0 -servicecomb: - service: - #Specifies the service center IP address. - registry: - address: http://127.0.0.1:30100 - #Specifies the rest transport listening IP address. - rest: - address: 0.0.0.0:8080 - #Specifies the highway transport listening IP address. - highway: - address: 0.0.0.0:7070 \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/README.md b/archetypes/business-service-spring-boot2-starter/README.md deleted file mode 100755 index 89d239f6ad6..00000000000 --- a/archetypes/business-service-spring-boot2-starter/README.md +++ /dev/null @@ -1,36 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-spring-boot2-starter-archetype*, it use **java-chassis-spring-boot-starter-standalone** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-spring-boot-starter/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get executable jar in target/bin folder: -- xxxxxx-{version}-exec.jar -```bash -java -jar xxxxxx-{version}-exec.jar -``` -*Notice: If you need to modify config setting in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can direct place a new "microservice.yaml" file in same folder, then settings will be overridden.*** - -## Spring Boot and ServiceComb -### Why ServiceComb make integration with Spring Boot -Spring Boot can accelerate develop speed of Spring application, it provides these features: -* Can create independent executable Spring application -* Tomcat embedded, Jetty as Web server, and do not need package(war) -* Provide many starters in order to simplify maven dependency - -Using Spring Boot in microservice development, can greatly simplifying configure and deploy. ServiceComb is a microservice framework with full functionality of service management, focus on rapidly development of microservices, so integration with Spring Boot can obtain greater advantages. - -### How ServiceComb make integration with Spring Boot2 -Developers often use Spring Boot2 in the following way: -* Java application : import `java-chassis-spring-boot-starter-standalone` and set `web-application-type: none` in application.yaml then develop general application, does not contain WEB -* Web application : import `java-chassis-spring-boot-starter-servlet` then develop web application, also include an embedded Tomcat or Jetty server, and use Spring Web MVC framework to develop REST endpoints - -The first way, do not need any refactoring, directly startup ServiceComb via Spring Boot. - -The second way is replace `Spring MVC DispatcherServlet` with `ServiceComb RestServlet`. \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/pom.xml b/archetypes/business-service-spring-boot2-starter/pom.xml deleted file mode 100755 index 3bb9960debe..00000000000 --- a/archetypes/business-service-spring-boot2-starter/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - org.apache.servicecomb - archetypes - 2.6.0-SNAPSHOT - - - org.apache.servicecomb.archetypes - Java Chassis::Archetypes::Spring Boot2 Starter - business-service-spring-boot2-starter-archetype - maven-archetype - 4.0.0 - - - 2.3 - - - - - - org.apache.maven.archetype - archetype-packaging - ${maven-archetype-packaging-version} - - - - - - src/main/resources - false - - - src/main/resources-filtered - true - - **/archetype-metadata.xml - - - - - \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml b/archetypes/business-service-spring-boot2-starter/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml deleted file mode 100755 index e953ae8b716..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - src/main/java - - **/*.java - - - - src/main/resources - - **/* - - - - - - README.md - - - - \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/README.md b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/README.md deleted file mode 100755 index 89d239f6ad6..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/README.md +++ /dev/null @@ -1,36 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-spring-boot2-starter-archetype*, it use **java-chassis-spring-boot-starter-standalone** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-spring-boot-starter/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get executable jar in target/bin folder: -- xxxxxx-{version}-exec.jar -```bash -java -jar xxxxxx-{version}-exec.jar -``` -*Notice: If you need to modify config setting in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can direct place a new "microservice.yaml" file in same folder, then settings will be overridden.*** - -## Spring Boot and ServiceComb -### Why ServiceComb make integration with Spring Boot -Spring Boot can accelerate develop speed of Spring application, it provides these features: -* Can create independent executable Spring application -* Tomcat embedded, Jetty as Web server, and do not need package(war) -* Provide many starters in order to simplify maven dependency - -Using Spring Boot in microservice development, can greatly simplifying configure and deploy. ServiceComb is a microservice framework with full functionality of service management, focus on rapidly development of microservices, so integration with Spring Boot can obtain greater advantages. - -### How ServiceComb make integration with Spring Boot2 -Developers often use Spring Boot2 in the following way: -* Java application : import `java-chassis-spring-boot-starter-standalone` and set `web-application-type: none` in application.yaml then develop general application, does not contain WEB -* Web application : import `java-chassis-spring-boot-starter-servlet` then develop web application, also include an embedded Tomcat or Jetty server, and use Spring Web MVC framework to develop REST endpoints - -The first way, do not need any refactoring, directly startup ServiceComb via Spring Boot. - -The second way is replace `Spring MVC DispatcherServlet` with `ServiceComb RestServlet`. \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/pom.xml b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/pom.xml deleted file mode 100755 index f1f995e7e0b..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - ${groupId} - ${artifactId} - ${version} - 4.0.0 - - - UTF-8 - - 2.0.0 - 2.1.2.RELEASE - - - - - - org.apache.servicecomb - java-chassis-dependencies-springboot2 - ${java-chassis.version} - pom - import - - - - - - - org.apache.servicecomb - java-chassis-spring-boot-starter-standalone - - - - - - - - org.springframework.boot - spring-boot-maven-plugin - ${springboot.version} - - - - repackage - - - ${project.build.directory}/bin - exec - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - - . - - - - - - - \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/Application.java b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/Application.java deleted file mode 100755 index 1a6d8e30b11..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/Application.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -@EnableServiceComb -public class Application { - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } -} \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java deleted file mode 100755 index c03ebb071d2..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.web.client.RestTemplate; - -public class HelloConsumer { - private final RestTemplate restTemplate = RestTemplateBuilder.create(); - - public void invokeHello() { - //service url is : cse://serviceName/operation - restTemplate.getForObject("cse://business-service/hello", String.class); - } -} \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/HelloImpl.java b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/HelloImpl.java deleted file mode 100755 index 1a304b20d16..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/java/HelloImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@RestSchema(schemaId = "hello") -@RequestMapping(path = "/") -public class HelloImpl { - - @GetMapping(path = "/hello") - public String hello() { - return "Hello World!"; - } -} \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/resources/application.yaml b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/resources/application.yaml deleted file mode 100644 index 80f2aeaf592..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/resources/application.yaml +++ /dev/null @@ -1,22 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -#Set web-application-type to none then develop general application, does not contain WEB -#If need to develop web application,Commented-Out it or set to servlet -spring: - main: - web-application-type: none \ No newline at end of file diff --git a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/resources/microservice.yaml b/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/resources/microservice.yaml deleted file mode 100755 index cbed0862768..00000000000 --- a/archetypes/business-service-spring-boot2-starter/src/main/resources/archetype-resources/src/main/resources/microservice.yaml +++ /dev/null @@ -1,43 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -#More details can be found : -# 1.http://servicecomb.apache.org/users/service-definition/ -# 2.http://servicecomb.apache.org/users/service-configurations/ -# 3.http://servicecomb.apache.org/users/communicate-protocol/ - -#Indicates an application name -APPLICATION_ID: business -service_description: -#Indicates a microservice name -#The microservice name should be unique within an application. -#The name can contain digits, uppercase and lowercase letters, hyphens(-), underscores(_), and periods(.); and can neither start nor end with punctuations. -#The naming rule is as follows: ^[a-zA-Z0-9]+$|^[a-zA-Z0-9][a-zA-Z0-9_-.]*[a-zA-Z0-9]$. - name: business-service -#Indicates a service version - version: 1.0.0 -servicecomb: - service: - #Specifies the service center IP address. - registry: - address: http://127.0.0.1:30100 - #Specifies the rest transport listening IP address. - rest: - address: 0.0.0.0:8080 - #Specifies the highway transport listening IP address. - highway: - address: 0.0.0.0:7070 \ No newline at end of file diff --git a/archetypes/business-service-springmvc/README.md b/archetypes/business-service-springmvc/README.md deleted file mode 100644 index bc15691fb17..00000000000 --- a/archetypes/business-service-springmvc/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-springmvc-archetype*, it use **springmvc provider** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-springmvc/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ -3. Modify setting value of "mainClass" in pom.xml for package. - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get outputs in target folder: -- lib : contains all dependencies jars -- xxxxxx-{version}.jar -```bash -java -jar xxxxxx-{version}.jar -``` -*Notice: If you need to modify configurations in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can directly place a new "microservice.yaml" file under the same folder, then configurations will be overridden.*** \ No newline at end of file diff --git a/archetypes/business-service-springmvc/pom.xml b/archetypes/business-service-springmvc/pom.xml deleted file mode 100644 index b8c5c77015c..00000000000 --- a/archetypes/business-service-springmvc/pom.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - org.apache.servicecomb - archetypes - 2.6.0-SNAPSHOT - - - org.apache.servicecomb.archetypes - Java Chassis::Archetypes::Spring MVC - business-service-springmvc-archetype - maven-archetype - 4.0.0 - - - 2.3 - - - - - - org.apache.maven.archetype - archetype-packaging - ${maven-archetype-packaging-version} - - - - - - src/main/resources - false - - - src/main/resources-filtered - true - - **/archetype-metadata.xml - - - - - \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml b/archetypes/business-service-springmvc/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml deleted file mode 100644 index e953ae8b716..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources-filtered/META-INF/maven/archetype-metadata.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - src/main/java - - **/*.java - - - - src/main/resources - - **/* - - - - - - README.md - - - - \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/README.md b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/README.md deleted file mode 100644 index a09e727dc15..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Welcome to use ServiceComb Java Chassis -This project(module) is generate by *org.apache.servicecomb.archetypes:business-service-springmvc-archetype*, it use **springmvc provider** to develop service producer. - -### More works can be done further: -1. Modify "HelloImpl", add your business service logic, or create some new producers to provide your services. More details can be found : http://servicecomb.apache.org/users/develop-with-springmvc/ -2. Modify "microservice.yaml", change APPLICATION_ID, service_description.name, version, and service center address, endpoints publish address etc. More details can be found : http://servicecomb.apache.org/users/service-definition/ -3. Modify setting value of "mainClass" in pom.xml for package. - -### Package your service -Under project(module) root folder, run -```bash -mvn package -``` -Then you can get outputs in target folder: -- lib : contains all dependencies jars -- xxxxxx-{version}.jar -```bash -java -jar xxxxxx-{version}.jar -``` -*Notice: If you need to modify config setting in "microservice.yaml" like service center address but don't want repackage the executable jar, **you can direct place a new "microservice.yaml" file in same folder, then settings will be overridden.*** \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/pom.xml b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/pom.xml deleted file mode 100644 index f08fa065585..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/pom.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - ${groupId} - ${artifactId} - ${version} - 4.0.0 - - - UTF-8 - 2.1.2.RELEASE - - - - - - org.apache.servicecomb - java-chassis-dependencies - ${java-chassis.version} - pom - import - - - - - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-highway - - - org.apache.servicecomb - provider-springmvc - - - org.apache.logging.log4j - log4j-slf4j-impl - - - org.apache.logging.log4j - log4j-api - - - org.apache.logging.log4j - log4j-core - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 2.6 - - - - true - lib/ - - ${package}.Application - - - . - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - target/lib - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.1 - - 1.8 - 1.8 - - - - - \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/Application.java b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/Application.java deleted file mode 100644 index 3e1feaec169..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/Application.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; - -public class Application { - public static void main(String[] args) throws Exception { - BeanUtils.init(); - } -} \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java deleted file mode 100644 index c03ebb071d2..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/HelloConsumer.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.web.client.RestTemplate; - -public class HelloConsumer { - private final RestTemplate restTemplate = RestTemplateBuilder.create(); - - public void invokeHello() { - //service url is : cse://serviceName/operation - restTemplate.getForObject("cse://business-service/hello", String.class); - } -} \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/HelloImpl.java b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/HelloImpl.java deleted file mode 100644 index 1a304b20d16..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/java/HelloImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 ${package}; - -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@RestSchema(schemaId = "hello") -@RequestMapping(path = "/") -public class HelloImpl { - - @GetMapping(path = "/hello") - public String hello() { - return "Hello World!"; - } -} \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/resources/log4j2.xml b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/resources/log4j2.xml deleted file mode 100644 index 2ec46303765..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/resources/log4j2.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - ./target/log - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/resources/microservice.yaml b/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/resources/microservice.yaml deleted file mode 100644 index cbed0862768..00000000000 --- a/archetypes/business-service-springmvc/src/main/resources/archetype-resources/src/main/resources/microservice.yaml +++ /dev/null @@ -1,43 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -#More details can be found : -# 1.http://servicecomb.apache.org/users/service-definition/ -# 2.http://servicecomb.apache.org/users/service-configurations/ -# 3.http://servicecomb.apache.org/users/communicate-protocol/ - -#Indicates an application name -APPLICATION_ID: business -service_description: -#Indicates a microservice name -#The microservice name should be unique within an application. -#The name can contain digits, uppercase and lowercase letters, hyphens(-), underscores(_), and periods(.); and can neither start nor end with punctuations. -#The naming rule is as follows: ^[a-zA-Z0-9]+$|^[a-zA-Z0-9][a-zA-Z0-9_-.]*[a-zA-Z0-9]$. - name: business-service -#Indicates a service version - version: 1.0.0 -servicecomb: - service: - #Specifies the service center IP address. - registry: - address: http://127.0.0.1:30100 - #Specifies the rest transport listening IP address. - rest: - address: 0.0.0.0:8080 - #Specifies the highway transport listening IP address. - highway: - address: 0.0.0.0:7070 \ No newline at end of file diff --git a/archetypes/pom.xml b/archetypes/pom.xml deleted file mode 100644 index aac449e11b8..00000000000 --- a/archetypes/pom.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - 4.0.0 - - org.apache.servicecomb - java-chassis-parent - 2.6.0-SNAPSHOT - ../parents/default - - - archetypes - Java Chassis::Archetypes - pom - - business-service-jaxrs - business-service-pojo - business-service-springmvc - business-service-spring-boot2-starter - - \ No newline at end of file diff --git a/ci/README.md b/ci/README.md new file mode 100644 index 00000000000..08c14d23741 --- /dev/null +++ b/ci/README.md @@ -0,0 +1,25 @@ +# Java Chassis Code Checks + +* Compilation and Installation + + see .github/workflows/maven.yml + +* Checkstyle + + see .github/workflows/checkstyle.yml + +* Rat Check + + see .github/workflows/rat_check.yml + +* Spot Bugs + + see .github/workflows/spotbugs.yml + +* OWASP Dependency Check + + `mvn verify -Powasp-dependency-check` . Very Slow, run manually. + +* Distribution + + `mvn clean deploy -Dcheckstyle.skip -Dspotbugs.skip=true -Dmaven.javadoc.skip=true -DskipTests -Prelease -Pdistribution` . Run manually when preparing a release. diff --git a/ci/checkstyle/checkstyle.xml b/ci/checkstyle/checkstyle.xml new file mode 100644 index 00000000000..3813950a5c8 --- /dev/null +++ b/ci/checkstyle/checkstyle.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ci/checkstyle/suppressions.xml b/ci/checkstyle/suppressions.xml new file mode 100644 index 00000000000..57e56d56c35 --- /dev/null +++ b/ci/checkstyle/suppressions.xml @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/ci/spotbugs/exclude.xml b/ci/spotbugs/exclude.xml new file mode 100644 index 00000000000..b7c53996e85 --- /dev/null +++ b/ci/spotbugs/exclude.xml @@ -0,0 +1,298 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/clients/README.md b/clients/README.md index bdaaafb125d..53180a4a03b 100644 --- a/clients/README.md +++ b/clients/README.md @@ -1,14 +1,13 @@ # About This module implements common http clients for servicecomb-service-center, servicecomb-kie and other -3rd-party services. +3rd-party services. + +This module is independent on servicecomb-java-chassis, and can be used in many other projects like +Spring Cloud, Dubbo, etc. -This module is independent on servicecomb-java-chassis, and can be used in many other projects like -Spring Cloud, Dubbo, etc. - # 关于 -这个模块给 servicecomb-service-center, servicecomb-kie 以及其他第三方服务实现通用的 Http Client。 +这个模块给 servicecomb-service-center, servicecomb-kie 以及其他第三方服务实现通用的 Http Client。 这个模块独立于 servicecomb-java-chassis, 可以用于 Spring Cloud, Dubbo 等项目。 - diff --git a/clients/config-center-client/pom.xml b/clients/config-center-client/pom.xml index 1f1346b7913..e7e2fa1fc2b 100644 --- a/clients/config-center-client/pom.xml +++ b/clients/config-center-client/pom.xml @@ -22,7 +22,7 @@ clients org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -41,17 +41,5 @@ org.apache.servicecomb config-clients-common - - - junit - junit - test - - - - org.mockito - mockito-core - test - - \ No newline at end of file + diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java deleted file mode 100644 index 28772d4cac6..00000000000 --- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/AddressManager.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.config.center.client; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.lang.StringUtils; -import org.apache.servicecomb.http.client.common.HttpUtils; - -public class AddressManager { - public static final String DEFAULT_PROJECT = "default"; - - private final String projectName; - - private final List addresses; - - private int index = 0; - - public AddressManager(String projectName, List addresses) { - this.projectName = StringUtils.isEmpty(projectName) ? DEFAULT_PROJECT : projectName; - this.addresses = new ArrayList<>(addresses.size()); - addresses.forEach((address -> this.addresses.add(formatAddress(address)))); - } - - private String formatAddress(String address) { - try { - return address + "/v3/" + HttpUtils.encodeURLParam(this.projectName); - } catch (Exception e) { - throw new IllegalStateException("not possible"); - } - } - - public String address() { - synchronized (this) { - this.index++; - if (this.index >= addresses.size()) { - this.index = 0; - } - return addresses.get(index); - } - } - - public boolean sslEnabled() { - return address().startsWith("https://"); - } -} diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterAddressManager.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterAddressManager.java new file mode 100644 index 00000000000..977c84ef63f --- /dev/null +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterAddressManager.java @@ -0,0 +1,47 @@ +/* + * 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.config.center.client; + +import java.util.List; + +import org.apache.servicecomb.http.client.common.AbstractAddressManager; +import org.apache.servicecomb.http.client.common.URLEndPoint; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +public class ConfigCenterAddressManager extends AbstractAddressManager { + + public ConfigCenterAddressManager(String projectName, List addresses, EventBus eventBus, String region, + String availableZone) { + super(projectName, addresses, region, availableZone); + eventBus.register(this); + } + + @Override + protected String normalizeUri(String endpoint) { + String address = new URLEndPoint(endpoint).toString(); + return formatAddress(address); + } + + @Subscribe + public void onRefreshEndpointEvent(RefreshEndpointEvent event) { + refreshEndpoint(event, RefreshEndpointEvent.CONFIG_CENTER_NAME); + } +} diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java index 132fe20449b..8ed31a5a61b 100644 --- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterClient.java @@ -18,22 +18,28 @@ package org.apache.servicecomb.config.center.client; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; -import org.apache.servicecomb.config.center.client.exception.OperationException; +import org.apache.servicecomb.config.common.exception.OperationException; import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest; import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse; import org.apache.servicecomb.http.client.common.HttpRequest; import org.apache.servicecomb.http.client.common.HttpResponse; import org.apache.servicecomb.http.client.common.HttpTransport; import org.apache.servicecomb.http.client.common.HttpUtils; +import org.apache.servicecomb.http.client.event.OperationEvents.UnAuthorizedOperationEvent; +import org.apache.servicecomb.http.client.utils.ServiceCombServiceAvailableUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.eventbus.EventBus; public class ConfigCenterClient implements ConfigCenterOperation { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterClient.class); @@ -48,17 +54,28 @@ public class ConfigCenterClient implements ConfigCenterOperation { public static final String DARK_LAUNCH = "darklaunch@"; - private HttpTransport httpTransport; + private static final String ADDRESS_CHECK_PATH = "/v3/default/configuration/health?mode=readiness"; - private AddressManager addressManager; + private final HttpTransport httpTransport; - public ConfigCenterClient(AddressManager addressManager, HttpTransport httpTransport) { + private final ConfigCenterAddressManager addressManager; + + private final Map> dimensionConfigNames = new HashMap<>(); + + private EventBus eventBus; + + public ConfigCenterClient(ConfigCenterAddressManager addressManager, HttpTransport httpTransport) { this.addressManager = addressManager; this.httpTransport = httpTransport; } + public void setEventBus(EventBus eventBus) { + this.eventBus = eventBus; + addressManager.setEventBus(eventBus); + } + @Override - public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsRequest request) { + public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsRequest request, String address) { String dimensionsInfo = buildDimensionsInfo(request, true); QueryConfigurationsResponse queryConfigurationsResponse = new QueryConfigurationsResponse(); @@ -66,7 +83,7 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques String uri = null; try { - uri = addressManager.address() + "/configuration/items?dimensionsInfo=" + uri = address + "/configuration/items?dimensionsInfo=" + HttpUtils.encodeURLParam(dimensionsInfo) + "&revision=" + request.getRevision(); Map headers = new HashMap<>(); @@ -75,6 +92,7 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques HttpRequest.GET); HttpResponse httpResponse = httpTransport.doRequest(httpRequest); + recordAndSendUnAuthorizedEvent(httpResponse, address); if (httpResponse.getStatusCode() == HttpStatus.SC_OK) { Map> allConfigMap = HttpUtils.deserialize( httpResponse.getContent(), @@ -87,18 +105,24 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques if (allConfigMap.get(APPLICATION_CONFIG) != null) { configurations.putAll(allConfigMap.get(APPLICATION_CONFIG)); + logConfigurationNames(APPLICATION_CONFIG, allConfigMap.get(APPLICATION_CONFIG)); } if (allConfigMap.get(buildDimensionsInfo(request, false)) != null) { configurations.putAll(allConfigMap.get(buildDimensionsInfo(request, false))); + logConfigurationNames(buildDimensionsInfo(request, false), + allConfigMap.get(buildDimensionsInfo(request, false))); } if (allConfigMap.get(buildDarkLaunchDimensionsInfo(request)) != null) { configurations.putAll(allConfigMap.get(buildDarkLaunchDimensionsInfo(request))); + logConfigurationNames(buildDarkLaunchDimensionsInfo(request), + allConfigMap.get(buildDarkLaunchDimensionsInfo(request))); } if (allConfigMap.get(dimensionsInfo) != null) { configurations.putAll(allConfigMap.get(dimensionsInfo)); + logConfigurationNames(dimensionsInfo, allConfigMap.get(dimensionsInfo)); } queryConfigurationsResponse.setConfigurations(configurations); queryConfigurationsResponse.setChanged(true); @@ -106,6 +130,10 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques } else if (httpResponse.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) { queryConfigurationsResponse.setChanged(false); return queryConfigurationsResponse; + } else if (httpResponse.getStatusCode() == HttpStatus.SC_TOO_MANY_REQUESTS) { + LOGGER.warn("rate limited, keep the local dimension [{}] configs unchanged.", dimensionsInfo); + queryConfigurationsResponse.setChanged(false); + return queryConfigurationsResponse; } else if (httpResponse.getStatusCode() == HttpStatus.SC_BAD_REQUEST) { throw new OperationException("Bad request for query configurations."); } else { @@ -118,11 +146,59 @@ public QueryConfigurationsResponse queryConfigurations(QueryConfigurationsReques + httpResponse.getContent()); } } catch (IOException e) { + addressManager.recordFailState(address); LOGGER.error("query configuration from {} failed, message={}", uri, e.getMessage()); throw new OperationException("", e); } } + private void recordAndSendUnAuthorizedEvent(HttpResponse response, String address) { + if (this.eventBus != null && response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + LOGGER.warn("query configuration unauthorized from server [{}], message [{}]", address, response.getMessage()); + addressManager.recordFailState(address); + this.eventBus.post(new UnAuthorizedOperationEvent(address)); + } else { + addressManager.recordSuccessState(address); + } + } + + /** + * Only the name of the new configuration item is printed. + * No log is printed when the configuration content is updated. + * + * @param dimension dimension + * @param configs configs + */ + private void logConfigurationNames(String dimension, Map configs) { + if (CollectionUtils.isEmpty(configs)) { + return; + } + List configNames = dimensionConfigNames.get(dimension); + if (configNames == null) { + configNames = new ArrayList<>(); + } + StringBuilder names = new StringBuilder(); + for (String key : configs.keySet()) { + if (configNames.contains(key)) { + continue; + } + names.append(key).append(","); + configNames.add(key); + } + if (names.isEmpty()) { + return; + } + dimensionConfigNames.put(dimension, configNames); + String fileNames = names.substring(0, names.length() - 1); + LOGGER.info("pulling dimension [{}] configurations success, get config names: [{}].", + dimension, fileNames); + } + + @Override + public void checkAddressAvailable(String address) { + ServiceCombServiceAvailableUtils.checkAddressAvailable(addressManager, address, httpTransport, ADDRESS_CHECK_PATH); + } + private String buildDimensionsInfo(QueryConfigurationsRequest request, boolean withVersion) { String result = request.getServiceName() + DEFAULT_APP_SEPARATOR diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterConfigurationChangedEvent.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterConfigurationChangedEvent.java new file mode 100644 index 00000000000..448c51a3d79 --- /dev/null +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterConfigurationChangedEvent.java @@ -0,0 +1,100 @@ +/* + * 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.config.center.client; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * This event is fired when configuration changed of config center. + */ +public class ConfigCenterConfigurationChangedEvent { + private final Map added; + + private final Map deleted; + + private final Map updated; + + private Set changed; + + private ConfigCenterConfigurationChangedEvent(Map added, Map updated, + Map deleted) { + this.added = added; + this.deleted = deleted; + this.updated = updated; + this.changed = new HashSet<>(); + this.changed.addAll(added.keySet()); + this.changed.addAll(updated.keySet()); + this.changed.addAll(deleted.keySet()); + } + + public static ConfigCenterConfigurationChangedEvent createIncremental(Map latest, + Map last) { + Map itemsCreated = new HashMap<>(); + Map itemsDeleted = new HashMap<>(); + Map itemsModified = new HashMap<>(); + + for (Map.Entry entry : latest.entrySet()) { + String itemKey = entry.getKey(); + if (!last.containsKey(itemKey)) { + itemsCreated.put(itemKey, entry.getValue()); + } else if (!Objects.equals(last.get(itemKey), latest.get(itemKey))) { + itemsModified.put(itemKey, entry.getValue()); + } + } + for (String itemKey : last.keySet()) { + if (!latest.containsKey(itemKey)) { + itemsDeleted.put(itemKey, null); + } + } + ConfigCenterConfigurationChangedEvent event = ConfigCenterConfigurationChangedEvent + .createIncremental(itemsCreated, itemsModified, itemsDeleted); + return event; + } + + public static ConfigCenterConfigurationChangedEvent createIncremental(Map added, + Map updated, + Map deleted) { + return new ConfigCenterConfigurationChangedEvent(added, updated, deleted); + } + + public static ConfigCenterConfigurationChangedEvent createIncremental(Map updated) { + return new ConfigCenterConfigurationChangedEvent(new HashMap<>(), updated, new HashMap<>()); + } + + public final Map getAdded() { + return added; + } + + + public final Map getUpdated() { + return updated; + } + + + public final Map getDeleted() { + return deleted; + } + + public final Set getChanged() { + return changed; + } +} diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java index 256a7bd3de4..7bfc43b4e05 100644 --- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterManager.java @@ -17,12 +17,13 @@ package org.apache.servicecomb.config.center.client; +import java.util.List; import java.util.Map; +import org.apache.servicecomb.config.center.client.model.ConfigCenterConfiguration; import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest; import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse; import org.apache.servicecomb.config.common.ConfigConverter; -import org.apache.servicecomb.config.common.ConfigurationChangedEvent; import org.apache.servicecomb.http.client.task.AbstractTask; import org.apache.servicecomb.http.client.task.Task; import org.slf4j.Logger; @@ -34,22 +35,26 @@ public class ConfigCenterManager extends AbstractTask { private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterManager.class); - private static final long POLL_INTERVAL = 15000; - - private ConfigCenterClient configCenterClient; + private final ConfigCenterClient configCenterClient; private final EventBus eventBus; private QueryConfigurationsRequest queryConfigurationsRequest; - private ConfigConverter configConverter; + private final ConfigConverter configConverter; + + private final ConfigCenterConfiguration configCenterConfiguration; + + private final ConfigCenterAddressManager configCenterAddressManager; - public ConfigCenterManager(ConfigCenterClient configCenterClient, EventBus eventBus, - ConfigConverter configConverter) { + public ConfigCenterManager(ConfigCenterClient configCenterClient, EventBus eventBus, ConfigConverter configConverter, + ConfigCenterConfiguration configCenterConfiguration, ConfigCenterAddressManager configCenterAddressManager) { super("config-center-configuration-task"); this.configCenterClient = configCenterClient; this.eventBus = eventBus; this.configConverter = configConverter; + this.configCenterConfiguration = configCenterConfiguration; + this.configCenterAddressManager = configCenterAddressManager; } public void setQueryConfigurationsRequest(QueryConfigurationsRequest queryConfigurationsRequest) { @@ -58,6 +63,8 @@ public void setQueryConfigurationsRequest(QueryConfigurationsRequest queryConfig public void startConfigCenterManager() { this.startTask(new PollConfigurationTask(0)); + schedulerCheckAddressAvailable("cc-addr-check", new CheckConfigCenterAddressTask(), + configCenterConfiguration.getRefreshIntervalInMillis()); } class PollConfigurationTask implements Task { @@ -70,19 +77,37 @@ public PollConfigurationTask(int failCount) { @Override public void execute() { try { - QueryConfigurationsResponse response = configCenterClient.queryConfigurations(queryConfigurationsRequest); + QueryConfigurationsResponse response = configCenterClient.queryConfigurations(queryConfigurationsRequest, + configCenterAddressManager.address()); if (response.isChanged()) { queryConfigurationsRequest.setRevision(response.getRevision()); Map lastData = configConverter.updateData(response.getConfigurations()); - ConfigurationChangedEvent event = ConfigurationChangedEvent + ConfigCenterConfigurationChangedEvent event = ConfigCenterConfigurationChangedEvent .createIncremental(configConverter.getCurrentData(), lastData); - eventBus.post(event); + if (!event.getChanged().isEmpty()) { + eventBus.post(event); + } } - startTask(new BackOffSleepTask(POLL_INTERVAL, new PollConfigurationTask(0))); + startTask( + new BackOffSleepTask(configCenterConfiguration.getRefreshIntervalInMillis(), new PollConfigurationTask(0))); } catch (Exception e) { - LOGGER.error("get configurations from ConfigCenter failed, and will try again.", e); + LOGGER.warn("get configurations from ConfigCenter failed, and will try again, cause message: {}. current " + + "fail does not affect the obtained historical configuration.", e.getCause().getMessage()); startTask(new BackOffSleepTask(failCount + 1, new PollConfigurationTask(failCount + 1))); } } } + + class CheckConfigCenterAddressTask implements Runnable { + @Override + public void run() { + List isolationAddresses = configCenterAddressManager.getIsolationAddresses(); + if (isolationAddresses.isEmpty()) { + return; + } + for (String address : isolationAddresses) { + configCenterClient.checkAddressAvailable(address); + } + } + } } diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java index 6cd726d47ba..919e9f30cd7 100644 --- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/ConfigCenterOperation.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.config.center.client; -import org.apache.servicecomb.config.center.client.exception.OperationException; +import org.apache.servicecomb.config.common.exception.OperationException; import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest; import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse; @@ -25,8 +25,16 @@ public interface ConfigCenterOperation { /** * 根据查询条件查询配置项。 * @param request 查询的维度(project, application, serviceName, version) 和 revision 信息。 + * @param address 查询的配置中心地址。 * @return 如果存在配置变更,返回全量的配置项, changed = true。 如果没有变更, 返回 null, changed = false, * @throws OperationException If some problems happened to contact service center or non http 200 returned. */ - QueryConfigurationsResponse queryConfigurations(QueryConfigurationsRequest request); + QueryConfigurationsResponse queryConfigurations(QueryConfigurationsRequest request, String address); + + /** + * Check config center isolation address available + * + * @param address isolation address + */ + void checkAddressAvailable(String address); } diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/exception/OperationException.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/exception/OperationException.java deleted file mode 100644 index c63d1bf39b3..00000000000 --- a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/exception/OperationException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.config.center.client.exception; - -public class OperationException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public OperationException(String message) { - super(message); - } - - public OperationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/ConfigCenterConfiguration.java b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/ConfigCenterConfiguration.java new file mode 100644 index 00000000000..0556d14fced --- /dev/null +++ b/clients/config-center-client/src/main/java/org/apache/servicecomb/config/center/client/model/ConfigCenterConfiguration.java @@ -0,0 +1,32 @@ +/* + * 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.config.center.client.model; + +public class ConfigCenterConfiguration { + + private long refreshIntervalInMillis = 15000; + + public long getRefreshIntervalInMillis() { + return refreshIntervalInMillis; + } + + public ConfigCenterConfiguration setRefreshIntervalInMillis(long refreshIntervalInMillis) { + this.refreshIntervalInMillis = refreshIntervalInMillis; + return this; + } +} diff --git a/clients/config-common/pom.xml b/clients/config-common/pom.xml index 09567479057..ff10b993583 100644 --- a/clients/config-common/pom.xml +++ b/clients/config-common/pom.xml @@ -22,7 +22,7 @@ clients org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -41,4 +41,4 @@ - \ No newline at end of file + diff --git a/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java index 3caa641db0c..0d8973d8aeb 100644 --- a/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java +++ b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigConverter.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.config.common; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; @@ -74,7 +74,7 @@ public Map updateData(Map rawData) { private Map createFileSource(Object v) { YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); - yamlFactory.setResources(new ByteArrayResource(v.toString().getBytes(Charset.forName("UTF-8")))); + yamlFactory.setResources(new ByteArrayResource(v.toString().getBytes(StandardCharsets.UTF_8))); return propertiesToMap(yamlFactory.getObject()); } diff --git a/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigurationChangedEvent.java b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigurationChangedEvent.java deleted file mode 100644 index a3514d004d4..00000000000 --- a/clients/config-common/src/main/java/org/apache/servicecomb/config/common/ConfigurationChangedEvent.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.config.common; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - -public class ConfigurationChangedEvent { - private final Map added; - - private final Map deleted; - - private final Map updated; - - private final boolean changed; - - private Map complete; - - private ConfigurationChangedEvent(Map added, Map updated, - Map deleted, boolean changed) { - this.added = added; - this.deleted = deleted; - this.updated = updated; - this.changed = changed; - } - - public static ConfigurationChangedEvent createIncremental(Map latest, Map last) { - Map itemsCreated = new HashMap<>(); - Map itemsDeleted = new HashMap<>(); - Map itemsModified = new HashMap<>(); - boolean changed = false; - - for (String itemKey : latest.keySet()) { - if (!last.containsKey(itemKey)) { - itemsCreated.put(itemKey, latest.get(itemKey)); - changed = true; - } else if (!Objects.equals(last.get(itemKey), latest.get(itemKey))) { - itemsModified.put(itemKey, latest.get(itemKey)); - changed = true; - } - } - for (String itemKey : last.keySet()) { - if (!latest.containsKey(itemKey)) { - itemsDeleted.put(itemKey, null); - changed = true; - } - } - ConfigurationChangedEvent event = ConfigurationChangedEvent - .createIncremental(itemsCreated, itemsModified, itemsDeleted, changed); - event.complete = latest; - return event; - } - - private static ConfigurationChangedEvent createIncremental(Map added, Map updated, - Map deleted, boolean changed) { - return new ConfigurationChangedEvent(added, updated, deleted, changed); - } - - public final Map getAdded() { - return added; - } - - - public final Map getUpdated() { - return updated; - } - - - public final Map getDeleted() { - return deleted; - } - - public final Map getComplete() { - return complete; - } - - public final boolean isChanged() { - return changed; - } -} diff --git a/clients/config-common/src/main/java/org/apache/servicecomb/config/common/exception/OperationException.java b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/exception/OperationException.java new file mode 100644 index 00000000000..f4e26b50505 --- /dev/null +++ b/clients/config-common/src/main/java/org/apache/servicecomb/config/common/exception/OperationException.java @@ -0,0 +1,30 @@ +/* + * 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.config.common.exception; + +public class OperationException extends RuntimeException { + private static final long serialVersionUID = 1L; + + public OperationException(String message) { + super(message); + } + + public OperationException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/clients/config-common/src/test/java/org/apache/servicecomb/config/common/TestConfigurationChangedEvent.java b/clients/config-common/src/test/java/org/apache/servicecomb/config/common/TestConfigurationChangedEvent.java deleted file mode 100644 index bd11efde01c..00000000000 --- a/clients/config-common/src/test/java/org/apache/servicecomb/config/common/TestConfigurationChangedEvent.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.config.common; - -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -public class TestConfigurationChangedEvent { - @Test - public void testConfigurationChangedEvent() { - Map before = new HashMap<>(); - Map after = new HashMap<>(); - before.put("updated", "1"); - before.put("deleted", "1"); - before.put("notChanged", null); - - after.put("added", 1); - after.put("updated", 2); - after.put("addedNull", null); - after.put("notChanged", null); - - ConfigurationChangedEvent event = ConfigurationChangedEvent.createIncremental(after, before); - Assert.assertEquals(2, event.getAdded().size()); - Assert.assertEquals(1, event.getDeleted().size()); - Assert.assertEquals(1, event.getUpdated().size()); - Assert.assertEquals(4, event.getComplete().size()); - Assert.assertEquals(true, event.isChanged()); - } -} diff --git a/clients/config-kie-client/pom.xml b/clients/config-kie-client/pom.xml index f1f6d525876..30dac44ba53 100644 --- a/clients/config-kie-client/pom.xml +++ b/clients/config-kie-client/pom.xml @@ -22,7 +22,7 @@ clients org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -42,7 +42,13 @@ org.springframework spring-beans + + + com.google.guava + failureaccess + test + - \ No newline at end of file + diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java index 5b64f2ded1e..b98a7d3b2a1 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieClient.java @@ -17,16 +17,23 @@ package org.apache.servicecomb.config.kie.client; +import com.google.common.eventbus.EventBus; + import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.stream.Collectors; import org.apache.http.HttpStatus; -import org.apache.servicecomb.config.kie.client.exception.OperationException; + +import org.apache.servicecomb.config.common.exception.OperationException; import org.apache.servicecomb.config.kie.client.model.ConfigConstants; import org.apache.servicecomb.config.kie.client.model.ConfigurationsRequest; import org.apache.servicecomb.config.kie.client.model.ConfigurationsResponse; @@ -39,15 +46,20 @@ import org.apache.servicecomb.http.client.common.HttpResponse; import org.apache.servicecomb.http.client.common.HttpTransport; import org.apache.servicecomb.http.client.common.HttpUtils; +import org.apache.servicecomb.http.client.event.OperationEvents.UnAuthorizedOperationEvent; +import org.apache.servicecomb.http.client.utils.ServiceCombServiceAvailableUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; import org.springframework.core.io.ByteArrayResource; +import org.springframework.util.CollectionUtils; public class KieClient implements KieConfigOperation { private static final Logger LOGGER = LoggerFactory.getLogger(KieClient.class); + private static final String ADDRESS_CHECK_PATH = "/v1/health"; + protected HttpTransport httpTransport; protected String revision = "0"; @@ -58,16 +70,24 @@ public class KieClient implements KieConfigOperation { public static final String DEFAULT_KIE_API_VERSION = "v1"; + private final Map> dimensionConfigNames = new HashMap<>(); + + private EventBus eventBus; + public KieClient(KieAddressManager addressManager, HttpTransport httpTransport, KieConfiguration kieConfiguration) { this.httpTransport = httpTransport; this.addressManager = addressManager; this.kieConfiguration = kieConfiguration; } - @Override - public ConfigurationsResponse queryConfigurations(ConfigurationsRequest request) { - String url = buildUrl(request); + public void setEventBus(EventBus eventBus) { + this.eventBus = eventBus; + addressManager.setEventBus(eventBus); + } + @Override + public ConfigurationsResponse queryConfigurations(ConfigurationsRequest request, String address) { + String url = buildUrl(request, address); try { if (kieConfiguration.isEnableLongPolling()) { url += "&wait=" + kieConfiguration.getPollingWaitInSeconds() + "s"; @@ -75,10 +95,12 @@ public ConfigurationsResponse queryConfigurations(ConfigurationsRequest request) HttpRequest httpRequest = new HttpRequest(url, null, null, HttpRequest.GET); HttpResponse httpResponse = httpTransport.doRequest(httpRequest); + recordAndSendUnAuthorizedEvent(httpResponse, address); ConfigurationsResponse configurationsResponse = new ConfigurationsResponse(); if (httpResponse.getStatusCode() == HttpStatus.SC_OK) { revision = httpResponse.getHeader("X-Kie-Revision"); KVResponse allConfigList = HttpUtils.deserialize(httpResponse.getContent(), KVResponse.class); + logConfigurationNames(request.getLabelsQuery(), allConfigList.getData()); Map configurations = getConfigByLabel(allConfigList); configurationsResponse.setConfigurations(configurations); configurationsResponse.setChanged(true); @@ -92,18 +114,71 @@ public ConfigurationsResponse queryConfigurations(ConfigurationsRequest request) configurationsResponse.setChanged(false); return configurationsResponse; } + if (httpResponse.getStatusCode() == HttpStatus.SC_TOO_MANY_REQUESTS) { + LOGGER.warn("rate limited, keep the local dimension [{}] configs unchanged.", request.getLabelsQuery()); + configurationsResponse.setChanged(false); + return configurationsResponse; + } throw new OperationException( "read response failed. status:" + httpResponse.getStatusCode() + "; message:" + httpResponse.getMessage() + "; content:" + httpResponse.getContent()); } catch (Exception e) { + addressManager.recordFailState(address); LOGGER.error("query configuration from {} failed, message={}", url, e.getMessage()); throw new OperationException("read response failed. ", e); } } - private String buildUrl(ConfigurationsRequest request) { + private void recordAndSendUnAuthorizedEvent(HttpResponse response, String address) { + if (this.eventBus != null && response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + LOGGER.warn("query configuration unauthorized from server [{}], message [{}]", address, response.getMessage()); + addressManager.recordFailState(address); + this.eventBus.post(new UnAuthorizedOperationEvent(address)); + } else { + addressManager.recordSuccessState(address); + } + } + + /** + * Only the name of the new configuration item is printed. + * No log is printed when the configuration content is updated. + * + * @param dimension dimension + * @param data configs-data + */ + private void logConfigurationNames(String dimension, List data) { + if (CollectionUtils.isEmpty(data)) { + return; + } + List configNames = dimensionConfigNames.get(dimension); + if (configNames == null) { + configNames = new ArrayList<>(); + } + StringBuilder names = new StringBuilder(); + for (KVDoc doc : data) { + if (configNames.contains(doc.getKey())) { + continue; + } + names.append(doc.getKey()).append(","); + configNames.add(doc.getKey()); + } + if (names.isEmpty()) { + return; + } + dimensionConfigNames.put(dimension, configNames); + String fileNames = names.substring(0, names.length() - 1); + LOGGER.info("pulling dimension [{}] configurations success, get config names: [{}].", + dimension, fileNames); + } + + @Override + public void checkAddressAvailable(String address) { + ServiceCombServiceAvailableUtils.checkAddressAvailable(addressManager, address, httpTransport, ADDRESS_CHECK_PATH); + } + + private String buildUrl(ConfigurationsRequest request, String currentAddress) { StringBuilder sb = new StringBuilder(); - sb.append(addressManager.address()); + sb.append(currentAddress); sb.append("/"); sb.append(DEFAULT_KIE_API_VERSION); sb.append("/"); @@ -121,6 +196,7 @@ private String buildUrl(ConfigurationsRequest request) { private Map getConfigByLabel(KVResponse resp) { Map resultMap = new HashMap<>(); resp.getData().stream() + .sorted(Comparator.comparing(KVDoc::getUpdateTime, Comparator.nullsFirst(Comparator.naturalOrder()))) .filter(doc -> doc.getStatus() == null || ConfigConstants.STATUS_ENABLED.equalsIgnoreCase(doc.getStatus())) .map(this::processValueType) .collect(Collectors.toList()) @@ -133,7 +209,7 @@ private Map processValueType(KVDoc kvDoc) { try { valueType = ValueType.valueOf(kvDoc.getValueType()); } catch (IllegalArgumentException e) { - throw new OperationException("value type not support"); + throw new OperationException("value type not support [" + kvDoc.getValue() + "]"); } Properties properties = new Properties(); Map kvMap = new HashMap<>(); @@ -142,7 +218,7 @@ private Map processValueType(KVDoc kvDoc) { case yml: case yaml: YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); - yamlFactory.setResources(new ByteArrayResource(kvDoc.getValue().getBytes())); + yamlFactory.setResources(new ByteArrayResource(kvDoc.getValue().getBytes(StandardCharsets.UTF_8))); return toMap(yamlFactory.getObject()); case properties: properties.load(new StringReader(kvDoc.getValue())); @@ -154,7 +230,7 @@ private Map processValueType(KVDoc kvDoc) { return kvMap; } } catch (Exception e) { - LOGGER.error("read config failed"); + LOGGER.error("read config failed", e); } return Collections.emptyMap(); } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java index 298a2c0ce6d..ed251613530 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigManager.java @@ -23,10 +23,10 @@ import java.util.concurrent.Executors; import org.apache.servicecomb.config.common.ConfigConverter; -import org.apache.servicecomb.config.common.ConfigurationChangedEvent; import org.apache.servicecomb.config.kie.client.model.ConfigurationsRequest; import org.apache.servicecomb.config.kie.client.model.ConfigurationsRequestFactory; import org.apache.servicecomb.config.kie.client.model.ConfigurationsResponse; +import org.apache.servicecomb.config.kie.client.model.KieAddressManager; import org.apache.servicecomb.config.kie.client.model.KieConfiguration; import org.apache.servicecomb.http.client.task.AbstractTask; import org.apache.servicecomb.http.client.task.Task; @@ -39,21 +39,22 @@ public class KieConfigManager extends AbstractTask { private static final Logger LOGGER = LoggerFactory.getLogger(KieConfigManager.class); - private static long POLL_INTERVAL = 1000; + private static final long LONG_POLLING_INTERVAL = 1000; - private KieConfigOperation configKieClient; + private final KieConfigOperation configKieClient; private final EventBus eventBus; - private ConfigConverter configConverter; + private final ConfigConverter configConverter; - private List configurationsRequests; + private final List configurationsRequests; - private KieConfiguration kieConfiguration; + private final KieConfiguration kieConfiguration; + + private final KieAddressManager kieAddressManager; public KieConfigManager(KieConfigOperation configKieClient, EventBus eventBus, - KieConfiguration kieConfiguration, - ConfigConverter configConverter) { + KieConfiguration kieConfiguration, ConfigConverter configConverter, KieAddressManager kieAddressManager) { super("config-center-configuration-task"); this.configurationsRequests = ConfigurationsRequestFactory.buildConfigurationRequests(kieConfiguration); this.configurationsRequests.sort(ConfigurationsRequest::compareTo); @@ -61,27 +62,44 @@ public KieConfigManager(KieConfigOperation configKieClient, EventBus eventBus, this.eventBus = eventBus; this.configConverter = configConverter; this.kieConfiguration = kieConfiguration; + this.kieAddressManager = kieAddressManager; } public void firstPull() { + Map data = new HashMap<>(); try { - Map data = new HashMap<>(); - this.configurationsRequests.forEach(r -> { - r.setRevision(ConfigurationsRequest.INITIAL_REVISION); - ConfigurationsResponse response = configKieClient.queryConfigurations(r); - if (response.isChanged()) { - r.setRevision(response.getRevision()); - r.setLastRawData(response.getConfigurations()); - data.putAll(response.getConfigurations()); - } - }); - this.configConverter.updateData(data); - } catch (RuntimeException e) { + firstQueryConfigurations(data); + } catch (Exception e) { if (this.kieConfiguration.isFirstPullRequired()) { throw e; } else { - LOGGER.warn("first pull failed, and ignore {}", e.getMessage()); + LOGGER.warn("first pull failed!"); + } + } + } + + private void firstQueryConfigurations(Map data) { + for (int i = 0; i < 3;) { + String address = kieAddressManager.address(); + try { + this.configurationsRequests.forEach(r -> { + r.setRevision(ConfigurationsRequest.INITIAL_REVISION); + ConfigurationsResponse response = configKieClient.queryConfigurations(r, address); + if (response.isChanged()) { + r.setRevision(response.getRevision()); + r.setLastRawData(response.getConfigurations()); + data.putAll(response.getConfigurations()); + } + }); + this.configConverter.updateData(data); + break; + } catch (Exception e) { + if (i == 2) { + throw e; + } + LOGGER.warn("firstQueryConfigurations failed, config address {} and ignore {}", address, e.getMessage()); } + i++; } } @@ -90,9 +108,9 @@ private void onDataChanged() { this.configurationsRequests.forEach(r -> latestData.putAll(r.getLastRawData())); Map lastData = configConverter.updateData(latestData); - ConfigurationChangedEvent event = ConfigurationChangedEvent + KieConfigurationChangedEvent event = KieConfigurationChangedEvent .createIncremental(configConverter.getCurrentData(), lastData); - if (event.isChanged()) { + if (!event.getChanged().isEmpty()) { eventBus.post(event); } } @@ -106,6 +124,8 @@ protected void initTaskPool(String taskName) { public void startConfigKieManager() { this.configurationsRequests.forEach((t) -> this.startTask(new PollConfigurationTask(0, t))); + schedulerCheckAddressAvailable("kie-addr-check", new CheckKieAddressTask(), + kieConfiguration.getRefreshIntervalInMillis()); } class PollConfigurationTask implements Task { @@ -121,22 +141,39 @@ public PollConfigurationTask(int failCount, ConfigurationsRequest configurations @Override public void execute() { try { - ConfigurationsResponse response = configKieClient.queryConfigurations(configurationsRequest); + ConfigurationsResponse response = configKieClient.queryConfigurations(configurationsRequest, + kieAddressManager.address()); if (response.isChanged()) { configurationsRequest.setRevision(response.getRevision()); configurationsRequest.setLastRawData(response.getConfigurations()); onDataChanged(); } if (KieConfigManager.this.kieConfiguration.isEnableLongPolling()) { - startTask(new BackOffSleepTask(POLL_INTERVAL, new PollConfigurationTask(0, this.configurationsRequest))); + startTask( + new BackOffSleepTask(LONG_POLLING_INTERVAL, new PollConfigurationTask(0, this.configurationsRequest))); } else { - startTask(new PollConfigurationTask(0, this.configurationsRequest)); + startTask(new BackOffSleepTask(kieConfiguration.getRefreshIntervalInMillis(), + new PollConfigurationTask(0, this.configurationsRequest))); } } catch (Exception e) { - LOGGER.error("get configurations from KieConfigCenter failed, and will try again.", e); + LOGGER.warn("get configurations from KieConfigCenter failed, and will try again, cause message: {}. current " + + "fail does not affect the obtained historical configuration.", e.getCause().getMessage()); startTask( new BackOffSleepTask(failCount + 1, new PollConfigurationTask(failCount + 1, this.configurationsRequest))); } } } + + class CheckKieAddressTask implements Runnable { + @Override + public void run() { + List isolationAddresses = kieAddressManager.getIsolationAddresses(); + if (isolationAddresses.isEmpty()) { + return; + } + for (String address : isolationAddresses) { + configKieClient.checkAddressAvailable(address); + } + } + } } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigOperation.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigOperation.java index 1079a1fa576..135ad0c220a 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigOperation.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigOperation.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.config.kie.client; -import org.apache.servicecomb.config.kie.client.exception.OperationException; +import org.apache.servicecomb.config.common.exception.OperationException; import org.apache.servicecomb.config.kie.client.model.ConfigurationsRequest; import org.apache.servicecomb.config.kie.client.model.ConfigurationsResponse; @@ -26,8 +26,16 @@ public interface KieConfigOperation { /** * 根据查询条件查询配置项。 * @param request 查询的维度(project, application, serviceName, version) 和 revision 信息。 + * @param address 查询的配置中心地址。 * @return 如果存在配置变更,返回全量的配置项, changed = true。 如果没有变更, 返回 null, changed = false, * @throws OperationException If some problems happened to contact service center or non http 200 returned. */ - ConfigurationsResponse queryConfigurations(ConfigurationsRequest request); + ConfigurationsResponse queryConfigurations(ConfigurationsRequest request, String address); + + /** + * Check kie isolation address available + * + * @param address isolation address + */ + void checkAddressAvailable(String address); } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigurationChangedEvent.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigurationChangedEvent.java new file mode 100644 index 00000000000..0e22c17e8b9 --- /dev/null +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/KieConfigurationChangedEvent.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.config.kie.client; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * This event is fired when configuration changed of kie. + */ +public class KieConfigurationChangedEvent { + private final Map added; + + private final Map deleted; + + private final Map updated; + + private Set changed; + + private KieConfigurationChangedEvent(Map added, Map updated, + Map deleted) { + this.added = added; + this.deleted = deleted; + this.updated = updated; + this.changed = new HashSet<>(); + this.changed.addAll(added.keySet()); + this.changed.addAll(updated.keySet()); + this.changed.addAll(deleted.keySet()); + } + + public static KieConfigurationChangedEvent createIncremental(Map latest, Map last) { + Map itemsCreated = new HashMap<>(); + Map itemsDeleted = new HashMap<>(); + Map itemsModified = new HashMap<>(); + + for (Map.Entry entry : latest.entrySet()) { + String itemKey = entry.getKey(); + if (!last.containsKey(itemKey)) { + itemsCreated.put(itemKey, entry.getValue()); + } else if (!Objects.equals(last.get(itemKey), latest.get(itemKey))) { + itemsModified.put(itemKey, entry.getValue()); + } + } + for (String itemKey : last.keySet()) { + if (!latest.containsKey(itemKey)) { + itemsDeleted.put(itemKey, null); + } + } + KieConfigurationChangedEvent event = KieConfigurationChangedEvent + .createIncremental(itemsCreated, itemsModified, itemsDeleted); + return event; + } + + public static KieConfigurationChangedEvent createIncremental(Map added, Map updated, + Map deleted) { + return new KieConfigurationChangedEvent(added, updated, deleted); + } + + public static KieConfigurationChangedEvent createIncremental(Map updated) { + return new KieConfigurationChangedEvent(new HashMap<>(), updated, new HashMap<>()); + } + + public final Map getAdded() { + return added; + } + + + public final Map getUpdated() { + return updated; + } + + + public final Map getDeleted() { + return deleted; + } + + public final Set getChanged() { + return changed; + } +} diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/exception/OperationException.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/exception/OperationException.java deleted file mode 100644 index fa14be96687..00000000000 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/exception/OperationException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.config.kie.client.exception; - -public class OperationException extends RuntimeException { - private static final long serialVersionUID = 1L; - - public OperationException(String message) { - super(message); - } - - public OperationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java index cbf964766d0..b22f7ecaa23 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequest.java @@ -17,10 +17,11 @@ package org.apache.servicecomb.config.kie.client.model; +import java.util.HashMap; import java.util.Map; public class ConfigurationsRequest implements Comparable { - public static final String INITIAL_REVISION = "0"; + public static final String INITIAL_REVISION = "-1"; private int order; @@ -30,7 +31,7 @@ public class ConfigurationsRequest implements Comparable private String labelsQuery; - private Map lastRawData; + private Map lastRawData = new HashMap<>(); public int getOrder() { return order; @@ -79,6 +80,7 @@ public ConfigurationsRequest setLastRawData(Map lastRawData) { @Override public int compareTo(ConfigurationsRequest o) { + // Higher priority, query the last return o.getOrder() - this.order; } } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java index dd766aac83b..20c6ba3bacb 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestFactory.java @@ -30,11 +30,15 @@ public class ConfigurationsRequestFactory { private static final String KEY_SERVICE = "service"; - private static final int SERVICE_ORDER = 100; + private static final String KEY_VERSION = "version"; - private static final int APP_ORDER = 200; + private static final int CUSTOM_ORDER = 100; - private static final int CUSTOM_ORDER = 300; + private static final int VERSION_ORDER = 200; + + private static final int SERVICE_ORDER = 300; + + private static final int APP_ORDER = 400; public static List buildConfigurationRequests(KieConfiguration configuration) { List result = new ArrayList<>(); @@ -44,6 +48,9 @@ public static List buildConfigurationRequests(KieConfigur if (configuration.isEnableServiceConfig()) { result.add(createServiceConfigurationsRequest(configuration)); } + if (configuration.isEnableVersionConfig()) { + result.add(createVersionConfigurationsRequest(configuration)); + } if (configuration.isEnableCustomConfig()) { result.add(createCustomConfigurationsRequest(configuration)); } @@ -67,6 +74,16 @@ private static ConfigurationsRequest createServiceConfigurationsRequest(KieConfi buildLabelQueryItem(KEY_ENVIRONMENT, configuration.getEnvironment()))); } + private static ConfigurationsRequest createVersionConfigurationsRequest(KieConfiguration configuration) { + return new ConfigurationsRequest() + .setOrder(VERSION_ORDER) + .setWithExact(true) + .setLabelsQuery(buildLabelQuery(buildLabelQueryItem(KEY_APP, configuration.getAppName()), + buildLabelQueryItem(KEY_SERVICE, configuration.getServiceName()), + buildLabelQueryItem(KEY_ENVIRONMENT, configuration.getEnvironment()), + buildLabelQueryItem(KEY_VERSION, configuration.getVersion()))); + } + private static ConfigurationsRequest createCustomConfigurationsRequest(KieConfiguration configuration) { return new ConfigurationsRequest() .setOrder(CUSTOM_ORDER) diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KVDoc.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KVDoc.java index d5d00c3ad63..3059a581c61 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KVDoc.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KVDoc.java @@ -35,7 +35,7 @@ public class KVDoc { @JsonAlias("label_id") private String labelId; - private Map labels = new HashMap(); + private Map labels = new HashMap<>(); private String value; @@ -44,6 +44,9 @@ public class KVDoc { private String status; + @JsonAlias("update_time") + private long updateTime; + public String getStatus() { return status; } @@ -115,4 +118,12 @@ public void setValue(String value) { public String getValueType() { return valueType; } + + public long getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(long updateTime) { + this.updateTime = updateTime; + } } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java index dde884ff4b4..d8c069ee9b1 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieAddressManager.java @@ -17,30 +17,23 @@ package org.apache.servicecomb.config.kie.client.model; -import java.util.ArrayList; import java.util.List; -public class KieAddressManager { - private final List addresses; +import org.apache.servicecomb.http.client.common.AbstractAddressManager; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; - private int index = 0; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; - public KieAddressManager(List addresses) { - this.addresses = new ArrayList<>(addresses.size()); - this.addresses.addAll(addresses); - } - - public String address() { - synchronized (this) { - this.index++; - if (this.index >= addresses.size()) { - this.index = 0; - } - return addresses.get(index); - } +public class KieAddressManager extends AbstractAddressManager { + + public KieAddressManager(List addresses, EventBus eventBus, String region, String availableZone) { + super(addresses, region, availableZone); + eventBus.register(this); } - public boolean sslEnabled() { - return address().startsWith("https://"); + @Subscribe + public void onRefreshEndpointEvent(RefreshEndpointEvent event) { + refreshEndpoint(event, RefreshEndpointEvent.KIE_NAME); } } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java index 8bf93c1cc21..9c75f2d09c2 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/KieConfiguration.java @@ -22,6 +22,8 @@ public class KieConfiguration { private int pollingWaitInSeconds; + private int refreshIntervalInMillis = 15000; + private String project; private String appName; @@ -30,10 +32,14 @@ public class KieConfiguration { private String environment; + private String version; + private boolean enableAppConfig; private boolean enableServiceConfig; + private boolean enableVersionConfig; + private boolean enableCustomConfig; private String customLabelValue; @@ -123,6 +129,15 @@ public KieConfiguration setEnableLongPolling(boolean enableLongPolling) { return this; } + public boolean isEnableVersionConfig() { + return enableVersionConfig; + } + + public KieConfiguration setEnableVersionConfig(boolean enableVersionConfig) { + this.enableVersionConfig = enableVersionConfig; + return this; + } + public int getPollingWaitInSeconds() { return pollingWaitInSeconds; } @@ -149,4 +164,22 @@ public KieConfiguration setFirstPullRequired(boolean firstPullRequired) { this.firstPullRequired = firstPullRequired; return this; } + + public int getRefreshIntervalInMillis() { + return refreshIntervalInMillis; + } + + public KieConfiguration setRefreshIntervalInMillis(int refreshIntervallnMillis) { + this.refreshIntervalInMillis = refreshIntervallnMillis; + return this; + } + + public String getVersion() { + return version; + } + + public KieConfiguration setVersion(String version) { + this.version = version; + return this; + } } diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/LabelDocResponse.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/LabelDocResponse.java index 62359902919..2b9e055de0f 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/LabelDocResponse.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/LabelDocResponse.java @@ -27,7 +27,7 @@ public class LabelDocResponse { @JsonAlias("label_id") private String labelId; - private Map labels = new HashMap(); + private Map labels = new HashMap<>(); public String getLabelId() { return labelId; diff --git a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ValueType.java b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ValueType.java index b38a1e28f8e..23cbce3b367 100644 --- a/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ValueType.java +++ b/clients/config-kie-client/src/main/java/org/apache/servicecomb/config/kie/client/model/ValueType.java @@ -24,5 +24,6 @@ public enum ValueType { string, text, json, - properties + properties, + xml } diff --git a/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestTest.java b/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestTest.java new file mode 100644 index 00000000000..47c152fa1df --- /dev/null +++ b/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/ConfigurationsRequestTest.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.config.kie.client.model; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +class ConfigurationsRequestTest { + + @Test + void getLastRawData() { + ConfigurationsRequest configurationsRequest = new ConfigurationsRequest(); + Map lastRawData = configurationsRequest.getLastRawData(); + Assertions.assertEquals(lastRawData.size(), 0); + } +} diff --git a/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/KieAddressManagerTest.java b/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/KieAddressManagerTest.java new file mode 100644 index 00000000000..c8bf1f57a29 --- /dev/null +++ b/clients/config-kie-client/src/test/java/org/apache/servicecomb/config/kie/client/model/KieAddressManagerTest.java @@ -0,0 +1,77 @@ +/* + * 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.config.kie.client.model; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; + +import com.google.common.eventbus.EventBus; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class KieAddressManagerTest { + + private static final List addresses = new ArrayList<>(); + + private static KieAddressManager addressManager1; + + @Test + public void kieAddressManagerTest() throws NoSuchFieldException, IllegalAccessException { + addresses.add("http://127.0.0.1:30103"); + addresses.add("https://127.0.0.2:30103"); + addressManager1 = new KieAddressManager(addresses, new EventBus(), "", ""); + Field addressManagerField = addressManager1.getClass().getSuperclass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager1, 0); + + Assertions.assertNotNull(addressManager1); + + List addresses = addressManager1.getAddresses(); + Assertions.assertEquals(2, addresses.size()); + Assertions.assertEquals("http://127.0.0.1:30103", addresses.get(0)); + + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + } + + @Test + public void onRefreshEndpointEvent() { + List addressAZ = new ArrayList<>(); + addressAZ.add("http://127.0.0.3:30100"); + List addressRG = new ArrayList<>(); + addressRG.add("http://127.0.0.4:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", addressRG); + addressManager1 = new KieAddressManager(addresses, new EventBus(), "", ""); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "KIE"); + addressManager1.refreshEndpoint(event, "KIE"); + + List availableZone = addressManager1.getAvailableZone(); + Assertions.assertEquals("http://127.0.0.3:30100", availableZone.get(0)); + + List availableRegion = addressManager1.getAvailableRegion(); + Assertions.assertEquals("http://127.0.0.4:30100", availableRegion.get(0)); + } +} diff --git a/clients/dashboard-client/pom.xml b/clients/dashboard-client/pom.xml new file mode 100644 index 00000000000..fb40407b82a --- /dev/null +++ b/clients/dashboard-client/pom.xml @@ -0,0 +1,50 @@ + + + + + + clients + org.apache.servicecomb + 3.4.0-SNAPSHOT + + 4.0.0 + + dashboard-client + ServiceComb::Clients::Dashboard Client + + + + org.apache.servicecomb + http-client-common + + + org.springframework + spring-beans + + + + com.google.guava + failureaccess + test + + + + + diff --git a/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardAddressManager.java b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardAddressManager.java new file mode 100644 index 00000000000..6897e02acd4 --- /dev/null +++ b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardAddressManager.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.dashboard.client; + + +import java.util.List; + +import org.apache.servicecomb.http.client.common.AbstractAddressManager; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + + +public class DashboardAddressManager extends AbstractAddressManager { + + public DashboardAddressManager(List addresses, EventBus eventBus, String region, String availableZone) { + super(addresses, region, availableZone); + eventBus.register(this); + } + + @Subscribe + public void onRefreshEndpointEvent(RefreshEndpointEvent event) { + refreshEndpoint(event, RefreshEndpointEvent.CSE_MONITORING_NAME); + } +} diff --git a/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardClient.java b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardClient.java new file mode 100644 index 00000000000..2fe84429cb7 --- /dev/null +++ b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardClient.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.dashboard.client; + +import org.apache.http.HttpStatus; +import org.apache.servicecomb.dashboard.client.model.MonitorData; +import org.apache.servicecomb.http.client.common.HttpRequest; +import org.apache.servicecomb.http.client.common.HttpResponse; +import org.apache.servicecomb.http.client.common.HttpTransport; +import org.apache.servicecomb.http.client.common.HttpUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DashboardClient implements DashboardOperation { + private static final Logger LOGGER = LoggerFactory.getLogger(DashboardClient.class); + + protected HttpTransport httpTransport; + + private final DashboardAddressManager addressManager; + + public DashboardClient(DashboardAddressManager addressManager, HttpTransport httpTransport) { + this.httpTransport = httpTransport; + this.addressManager = addressManager; + } + + @Override + public void sendData(String url, MonitorData data) { + String address = addressManager.address(); + try { + HttpRequest httpRequest = new HttpRequest(address + url, null, HttpUtils.serialize(data), HttpRequest.POST); + HttpResponse httpResponse = httpTransport.doRequest(httpRequest); + if (httpResponse.getStatusCode() != HttpStatus.SC_OK) { + LOGGER.error("send data to [{}] failed, status code [{}], message [{}]", url, httpResponse.getStatusCode() + , httpResponse.getContent()); + } + } catch (Exception e) { + LOGGER.error("send data to [{}] failed", url, e); + } + } +} diff --git a/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardOperation.java b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardOperation.java new file mode 100644 index 00000000000..733ebfc4676 --- /dev/null +++ b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/DashboardOperation.java @@ -0,0 +1,24 @@ +/* + * 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.dashboard.client; + +import org.apache.servicecomb.dashboard.client.model.MonitorData; + +public interface DashboardOperation { + void sendData(String url, MonitorData monitorData); +} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/InterfaceInfo.java b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/model/InterfaceInfo.java similarity index 98% rename from huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/InterfaceInfo.java rename to clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/model/InterfaceInfo.java index 23a35f0089d..1a72c8fe747 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/InterfaceInfo.java +++ b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/model/InterfaceInfo.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.huaweicloud.dashboard.monitor.data; +package org.apache.servicecomb.dashboard.client.model; public class InterfaceInfo { private String name; diff --git a/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/model/MonitorData.java b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/model/MonitorData.java new file mode 100644 index 00000000000..d02facd5daa --- /dev/null +++ b/clients/dashboard-client/src/main/java/org/apache/servicecomb/dashboard/client/model/MonitorData.java @@ -0,0 +1,188 @@ +/* + * 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.dashboard.client.model; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class MonitorData { + public static final double PERCENTAGE_995 = 99.5; + + public static final double PERCENTAGE_99 = 99; + + public static final double PERCENTAGE_90 = 90; + + public static final double PERCENTAGE_75 = 75; + + public static final double PERCENTAGE_50 = 50; + + public static final double PERCENTAGE_25 = 25; + + public static final double PERCENTAGE_5 = 5; + + public static final int SCALE_VAL = 1; + + public static final double DEFAULT_SUCCESS_RATE = 1.0d; + + public static final int CONVERSION = 1000; + + private String appId; + + private String version; + + private String name; + + private String serviceId; + + private String environment; + + private String instance; + + private String instanceId; + + private int thread; + + private double cpu; + + private double loadAverage; + + private long uptime; + + private Map memory; + + private List interfaces = new ArrayList<>(); + + private Map customs; + + public void addInterfaceInfo(InterfaceInfo interfaceInfo) { + interfaces.add(interfaceInfo); + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getInstanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + public int getThreadCount() { + return thread; + } + + public void setThreadCount(int threadCount) { + this.thread = threadCount; + } + + public double getCpu() { + return cpu; + } + + public void setCpu(double cpu) { + this.cpu = cpu; + } + + public double getLoadAverage() { + return loadAverage; + } + + public void setLoadAverage(double loadAverage) { + this.loadAverage = loadAverage; + } + + public long getUptime() { + return uptime; + } + + public void setUptime(long uptime) { + this.uptime = uptime; + } + + public Map getMemory() { + return memory; + } + + public void setMemory(Map memory) { + this.memory = memory; + } + + public List getInterfaces() { + return interfaces; + } + + public void setInterfaces(List interfaces) { + this.interfaces = interfaces; + } + + public Map getCustoms() { + return customs; + } + + public void setCustoms(Map customs) { + this.customs = customs; + } + + public String getEnvironment() { + return environment; + } + + public void setEnvironment(String environment) { + this.environment = environment; + } +} diff --git a/clients/dashboard-client/src/test/java/org/apache/servicecomb/dashboard/client/AddressManagerTest.java b/clients/dashboard-client/src/test/java/org/apache/servicecomb/dashboard/client/AddressManagerTest.java new file mode 100644 index 00000000000..fdb7a23922b --- /dev/null +++ b/clients/dashboard-client/src/test/java/org/apache/servicecomb/dashboard/client/AddressManagerTest.java @@ -0,0 +1,76 @@ +/* + * 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.dashboard.client; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import com.google.common.eventbus.EventBus; + +class AddressManagerTest { + + private static final List addresses = new ArrayList<>(); + + private static DashboardAddressManager addressManager1; + + @Test + public void kieAddressManagerTest() throws IllegalAccessException, NoSuchFieldException { + addresses.add("http://127.0.0.1:30103"); + addresses.add("https://127.0.0.2:30103"); + addressManager1 = new DashboardAddressManager(addresses, new EventBus(), "", ""); + Field addressManagerField = addressManager1.getClass().getSuperclass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager1, 0); + + Assertions.assertNotNull(addressManager1); + + List addresses = addressManager1.getAddresses(); + Assertions.assertEquals(2, addresses.size()); + Assertions.assertEquals("http://127.0.0.1:30103", addresses.get(0)); + + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + } + + @Test + public void onRefreshEndpointEvent() { + List addressAZ = new ArrayList<>(); + addressAZ.add("http://127.0.0.3:30100"); + List addressRG = new ArrayList<>(); + addressRG.add("http://127.0.0.4:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", addressRG); + addressManager1 = new DashboardAddressManager(addresses, new EventBus(), "", ""); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "CseMonitoring"); + addressManager1.refreshEndpoint(event, "CseMonitoring"); + + List availableZone = addressManager1.getAvailableZone(); + Assertions.assertEquals("http://127.0.0.3:30100", availableZone.get(0)); + + List availableRegion = addressManager1.getAvailableRegion(); + Assertions.assertEquals("http://127.0.0.4:30100", availableRegion.get(0)); + } +} diff --git a/clients/http-client-common/pom.xml b/clients/http-client-common/pom.xml index b53d66f3bd4..51d982e470c 100644 --- a/clients/http-client-common/pom.xml +++ b/clients/http-client-common/pom.xml @@ -22,7 +22,7 @@ clients org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -71,17 +71,5 @@ org.java-websocket Java-WebSocket - - - junit - junit - test - - - - org.mockito - mockito-core - test - - \ No newline at end of file + diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/AbstractAddressManager.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/AbstractAddressManager.java new file mode 100644 index 00000000000..3c5d6214be8 --- /dev/null +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/AbstractAddressManager.java @@ -0,0 +1,348 @@ +/* + * 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.http.client.common; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.http.client.event.EngineConnectChangedEvent; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.eventbus.EventBus; + +public class AbstractAddressManager { + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractAddressManager.class); + + public static final String DEFAULT_PROJECT = "default"; + + public static final String V4_PREFIX = "/v4/"; + + private static final String V3_PREFIX = "/v3/"; + + private static final String ZONE = "availableZone"; + + private static final String REGION = "region"; + + private static final int ISOLATION_THRESHOLD = 3; + + private volatile List addresses = new ArrayList<>(); + + // when all addresses are isolation, it will use this for polling. + private final List defaultAddress = new ArrayList<>(); + + private final List defaultIsolationAddress = new ArrayList<>(); + + private int index; + + private String projectName; + + // recording continuous times of failure of an address. + private final Map addressFailureStatus = new ConcurrentHashMap<>(); + + private volatile List availableZone = new ArrayList<>(); + + private final List isolationZoneAddress = new ArrayList<>(); + + private volatile List availableRegion = new ArrayList<>(); + + private final List isolationRegionAddress = new ArrayList<>(); + + private volatile boolean addressAutoRefreshed = false; + + private final Object lock = new Object(); + + private final Random random = new Random(); + + private EventBus eventBus; + + public AbstractAddressManager(List addresses, String ownRegion, String ownAvailableZone) { + this.projectName = DEFAULT_PROJECT; + parseAndInitAddresses(addresses, ownRegion, ownAvailableZone, false); + this.index = !addresses.isEmpty() ? getRandomIndex() : 0; + } + + /** + * address support config with region/availableZone info, to enable engine affinity calls during startup + * address may be like: + * https://192.168.20.13:30110?region=region1&availableZone=az + * https://192.168.20.13:30100?region=region1&availableZone=az + * When address have no datacenter information, roundRobin using address + * + * @param addresses engine addresses + * @param ownRegion microservice region + * @param ownAvailableZone microservice zone + * @param isFormat is need format + */ + private void parseAndInitAddresses(List addresses, String ownRegion, String ownAvailableZone, + boolean isFormat) { + if (CollectionUtils.isEmpty(addresses)) { + return; + } + List tempList = new ArrayList<>(); + addressAutoRefreshed = addresses.stream().anyMatch(addr -> addr.contains(ZONE) || addr.contains(REGION)); + for (String address : addresses) { + // Compatible IpPortManager init address is 127.0.0.1:30100 + if (!address.startsWith("http")) { + tempList.add(address); + continue; + } + URLEndPoint endpoint = new URLEndPoint(address); + tempList.add(endpoint.toString()); + buildAffinityAddress(endpoint, ownRegion, ownAvailableZone); + } + this.addresses.addAll(isFormat ? this.transformAddress(tempList) : tempList); + this.defaultAddress.addAll(isFormat ? this.transformAddress(tempList) : tempList); + } + + private void buildAffinityAddress(URLEndPoint endpoint, String ownRegion, String ownAvailableZone) { + if (addressAutoRefreshed) { + if (regionAndAZMatch(ownRegion, ownAvailableZone, endpoint.getFirst(REGION), endpoint.getFirst(ZONE))) { + availableZone.add(endpoint.toString()); + } else { + availableRegion.add(endpoint.toString()); + } + } + } + + private boolean regionAndAZMatch(String ownRegion, String ownAvailableZone, String engineRegion, + String engineAvailableZone) { + return ownRegion.equalsIgnoreCase(engineRegion) && ownAvailableZone.equals(engineAvailableZone); + } + + public AbstractAddressManager(String projectName, List addresses, String ownRegion, String ownAvailableZone) { + this.projectName = StringUtils.isEmpty(projectName) ? DEFAULT_PROJECT : projectName; + parseAndInitAddresses(addresses, ownRegion, ownAvailableZone, true); + this.index = !addresses.isEmpty() ? getRandomIndex() : 0; + } + + private int getRandomIndex() { + return random.nextInt(addresses.size()); + } + + public void refreshEndpoint(RefreshEndpointEvent event, String key) { + if (null == event || !event.getName().equals(key)) { + return; + } + + availableZone = event.getSameZone().stream().map(this::normalizeUri).collect(Collectors.toList()); + availableRegion = event.getSameRegion().stream().map(this::normalizeUri).collect(Collectors.toList()); + addressAutoRefreshed = true; + } + + protected String normalizeUri(String endpoint) { + return new URLEndPoint(endpoint).toString(); + } + + @VisibleForTesting + Map getAddressFailureStatus() { + return addressFailureStatus; + } + + public List getAddresses() { + return addresses; + } + + public List getAvailableZone() { + return availableZone; + } + + public List getAvailableRegion() { + return availableRegion; + } + + public String formatUrl(String url, boolean absoluteUrl, String address) { + return absoluteUrl ? address + url : formatAddress(address) + url; + } + + public boolean sslEnabled() { + return address().startsWith("https://"); + } + + protected List transformAddress(List addresses) { + return addresses.stream().map(this::formatAddress).collect(Collectors.toList()); + } + + protected String formatAddress(String address) { + try { + return getUrlPrefix(address) + HttpUtils.encodeURLParam(this.projectName); + } catch (Exception e) { + throw new IllegalStateException("not possible"); + } + } + + protected String getUrlPrefix(String address) { + return address + V3_PREFIX; + } + + public String address() { + if (!addressAutoRefreshed) { + return getDefaultAddress(); + } else { + return getAvailableZoneAddress(); + } + } + + private String getDefaultAddress() { + if (!addresses.isEmpty()) { + return getCurrentAddress(addresses); + } + LOGGER.warn("all addresses are isolation, please check server status."); + // when all addresses are isolation, it will use all default address for polling. + return getCurrentAddress(defaultAddress); + } + + private String getAvailableZoneAddress() { + List zoneOrRegionAddress = getZoneOrRegionAddress(); + if (!zoneOrRegionAddress.isEmpty()) { + return getCurrentAddress(zoneOrRegionAddress); + } + LOGGER.warn("all auto discovery addresses are isolation, please check server status."); + // when all available address are isolation, it will use config addresses for polling. + return getCurrentAddress(addresses); + } + + private String getCurrentAddress(List addresses) { + synchronized (this) { + this.index++; + if (this.index >= addresses.size()) { + this.index = 0; + } + return addresses.get(index); + } + } + + private List getZoneOrRegionAddress() { + List results = new ArrayList<>(); + if (!availableZone.isEmpty()) { + results.addAll(availableZone); + } else { + results.addAll(availableRegion); + } + return results; + } + + public void recordSuccessState(String address) { + resetFailureStatus(address); + if (addressAutoRefreshed) { + if (isolationZoneAddress.remove(address)) { + LOGGER.warn("restore same region address [{}]", address); + if (eventBus != null && availableZone.isEmpty()) { + eventBus.post(new EngineConnectChangedEvent()); + } + availableZone.add(address); + return; + } + if (isolationRegionAddress.remove(address)) { + LOGGER.warn("restore same zone address [{}]", address); + availableRegion.add(address); + } + return; + } + if (defaultIsolationAddress.remove(address)) { + LOGGER.warn("restore default address [{}]", address); + addresses.add(address); + } + } + + public void resetFailureStatus(String address) { + addressFailureStatus.put(address, 0); + } + + public void recordFailState(String address) { + synchronized (lock) { + if (!addressFailureStatus.containsKey(address)) { + addressFailureStatus.put(address, 1); + return; + } + int number = addressFailureStatus.get(address) + 1; + if (number < ISOLATION_THRESHOLD) { + addressFailureStatus.put(address, number); + } else { + removeAddress(address); + } + } + } + + //Query whether the current address belongs to the same AZ or the same region through AZMap, + // and delete it from the record. At the same time, add records in history and cache + @VisibleForTesting + void removeAddress(String address) { + if (!addressAutoRefreshed) { + if (addresses.remove(address)) { + LOGGER.warn("isolation default address [{}]", address); + defaultIsolationAddress.add(address); + } + return; + } + if (availableZone.remove(address)) { + LOGGER.warn("isolation same zone address [{}]", address); + isolationZoneAddress.add(address); + if (eventBus != null && availableZone.isEmpty() && !availableRegion.isEmpty()) { + eventBus.post(new EngineConnectChangedEvent()); + } + return; + } + if (availableRegion.remove(address)) { + LOGGER.warn("isolation same region address [{}]", address); + isolationRegionAddress.add(address); + } + } + + public void setEventBus(EventBus eventBus) { + this.eventBus = eventBus; + } + + public List getIsolationAddresses() { + List isolationAddresses = new ArrayList<>(defaultIsolationAddress); + isolationAddresses.addAll(isolationZoneAddress); + isolationAddresses.addAll(isolationRegionAddress); + return isolationAddresses; + } + + public String compareAndGetAddress(String host) { + for (String address : defaultAddress) { + if (isAddressHostSame(address, host)) { + return address; + } + } + return ""; + } + + private boolean isAddressHostSame(String address, String host) { + if (StringUtils.isEmpty(host)) { + return false; + } + try { + URI uri = new URI(address); + return host.equals(uri.getHost()); + } catch (Exception e) { + LOGGER.warn("Exception occurred while constructing URI using the address [{}]", address); + } + return false; + } +} diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpRequest.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpRequest.java index 08d7a06d681..35e14df06c1 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpRequest.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpRequest.java @@ -41,11 +41,11 @@ public class HttpRequest { private String method; - private String url; + private final String url; private Map headers; - private String content; + private final String content; public HttpRequest(String url, Map headers, String content, String method) { this.url = url; diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java index 429f5bd7f38..507d8d1c556 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpTransportImpl.java @@ -18,17 +18,21 @@ package org.apache.servicecomb.http.client.common; import java.io.IOException; +import java.net.URI; import java.util.Map; import org.apache.http.client.HttpClient; import org.apache.http.util.EntityUtils; import org.apache.servicecomb.foundation.auth.SignRequest; import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Created by on 2019/10/16. */ public class HttpTransportImpl implements HttpTransport { + private static final Logger LOGGER = LoggerFactory.getLogger(HttpTransportImpl.class); private static final String HEADER_CONTENT_TYPE = "Content-Type"; @@ -38,7 +42,7 @@ public class HttpTransportImpl implements HttpTransport { private Map globalHeaders; - private RequestAuthHeaderProvider requestAuthHeaderProvider; + private final RequestAuthHeaderProvider requestAuthHeaderProvider; public HttpTransportImpl(HttpClient httpClient, RequestAuthHeaderProvider requestAuthHeaderProvider) { this.httpClient = httpClient; @@ -87,7 +91,7 @@ public HttpResponse doRequest(HttpRequest httpRequest) throws IOException { globalHeaders.forEach(httpRequest::addHeader); } - httpRequest.getHeaders().putAll(requestAuthHeaderProvider.loadAuthHeader(createSignRequest())); + httpRequest.getHeaders().putAll(requestAuthHeaderProvider.loadAuthHeader(createSignRequest(httpRequest.getUrl()))); //get Http response org.apache.http.HttpResponse response = httpClient.execute(httpRequest.getRealRequest()); @@ -98,13 +102,20 @@ public HttpResponse doRequest(HttpRequest httpRequest) throws IOException { response.getAllHeaders()); } - private static SignRequest createSignRequest() { - // Now the implementations do not process SignRequest, so return null. Maybe future will use it. - return null; + private static SignRequest createSignRequest(String url) { + try { + URI uri = URI.create(url); + SignRequest signRequest = new SignRequest(); + signRequest.setEndpoint(uri); + return signRequest; + } catch (Exception e) { + LOGGER.error("create signRequest failed!", e); + return null; + } } @Override public void addHeaders(Map headers) { this.globalHeaders = headers; } -} \ No newline at end of file +} diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java index 37d5c207473..5f259cc3053 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/HttpUtils.java @@ -18,6 +18,7 @@ package org.apache.servicecomb.http.client.common; import java.io.IOException; +import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -55,7 +56,14 @@ public static String encodeURLParam(String value) throws IOException { if (value == null) { return ""; } - return URLEncoder.encode(value, "UTF-8"); + return URLEncoder.encode(value, StandardCharsets.UTF_8); + } + + public static String decodeURLParam(String value) throws IOException { + if (value == null) { + return null; + } + return URLDecoder.decode(value, StandardCharsets.UTF_8); } public static String sha256Encode(String key, String data) throws Exception { diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/MessageObjectMapper.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/MessageObjectMapper.java index 3cb7f21ac7d..4eb85472643 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/MessageObjectMapper.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/MessageObjectMapper.java @@ -33,7 +33,8 @@ public MessageObjectMapper() { disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // no view annotations shouldn't be included in JSON - disable(MapperFeature.DEFAULT_VIEW_INCLUSION); + this._deserializationConfig = this._deserializationConfig.without(MapperFeature.DEFAULT_VIEW_INCLUSION); + this._serializationConfig = this._serializationConfig.without(MapperFeature.DEFAULT_VIEW_INCLUSION); disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/SSLSocketFactoryExt.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/SSLSocketFactoryExt.java index cd9f9413f82..db5f18afee7 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/SSLSocketFactoryExt.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/SSLSocketFactoryExt.java @@ -24,11 +24,11 @@ import java.net.UnknownHostException; public class SSLSocketFactoryExt extends SSLSocketFactory { - private SSLSocketFactory sslSocketFactory; + private final SSLSocketFactory sslSocketFactory; - private String host; + private final String host; - private int port; + private final int port; public SSLSocketFactoryExt(SSLSocketFactory factory, String host, int port) { this.sslSocketFactory = factory; diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/URLEndPoint.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/URLEndPoint.java new file mode 100644 index 00000000000..e3e53bad06a --- /dev/null +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/URLEndPoint.java @@ -0,0 +1,85 @@ +/* + * 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.http.client.common; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.NameValuePair; +import org.apache.http.client.utils.URLEncodedUtils; + +public class URLEndPoint { + private static final String SSL_ENABLED_KEY = "sslEnabled"; + + private static final String HTTP_KEY = "http://"; + + private static final String HTTPS_KEY = "https://"; + + private final boolean sslEnabled; + + private final Map> queries; + + private final String hostOrIp; + + private final int port; + + public URLEndPoint(String endpoint) { + URI uri = URI.create(endpoint); + hostOrIp = uri.getHost(); + if (uri.getPort() < 0) { + throw new IllegalArgumentException("port not specified."); + } + port = uri.getPort(); + queries = splitQuery(uri); + if (endpoint.contains(HTTPS_KEY)) { + sslEnabled = true; + } else { + sslEnabled = Boolean.parseBoolean(getFirst(SSL_ENABLED_KEY)); + } + } + + public static Map> splitQuery(URI uri) { + final Map> queryPairs = new LinkedHashMap<>(); + List pairs = URLEncodedUtils.parse(uri, StandardCharsets.UTF_8); + for (NameValuePair pair : pairs) { + List list = queryPairs.computeIfAbsent(pair.getName(), name -> new ArrayList<>()); + list.add(pair.getValue()); + } + return queryPairs; + } + + public String getFirst(String key) { + List values = queries.get(key); + if (values == null) { + return null; + } + return values.get(0); + } + + @Override + public String toString() { + if (sslEnabled) { + return HTTPS_KEY + hostOrIp + ":" + port; + } + return HTTP_KEY + hostOrIp + ":" + port; + } +} diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/WebSocketTransport.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/WebSocketTransport.java index 7d36e288527..ab630c609be 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/WebSocketTransport.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/common/WebSocketTransport.java @@ -31,7 +31,7 @@ public class WebSocketTransport extends WebSocketClient { public static final int CONNECT_TIMEOUT = 5000; - private WebSocketListener webSocketListener; + private final WebSocketListener webSocketListener; public WebSocketTransport(String serverUri, HttpConfiguration.SSLProperties sslProperties, Map headers, WebSocketListener webSocketListener) diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/EngineConnectChangedEvent.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/EngineConnectChangedEvent.java new file mode 100644 index 00000000000..b2029f5c38c --- /dev/null +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/EngineConnectChangedEvent.java @@ -0,0 +1,21 @@ +/* + * 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.http.client.event; + +public class EngineConnectChangedEvent { +} diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/OperationEvents.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/OperationEvents.java similarity index 79% rename from clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/OperationEvents.java rename to clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/OperationEvents.java index 62274519ea4..69896f750ec 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/OperationEvents.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/OperationEvents.java @@ -15,10 +15,18 @@ * limitations under the License. */ -package org.apache.servicecomb.service.center.client; +package org.apache.servicecomb.http.client.event; public abstract class OperationEvents { public static class UnAuthorizedOperationEvent extends OperationEvents { + private final String address; + public UnAuthorizedOperationEvent(String address) { + this.address = address; + } + + public String getAddress() { + return address; + } } } diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/RefreshEndpointEvent.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/RefreshEndpointEvent.java new file mode 100644 index 00000000000..4e4f1be648e --- /dev/null +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/event/RefreshEndpointEvent.java @@ -0,0 +1,77 @@ +/* + * 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.http.client.event; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RefreshEndpointEvent { + + public static final String SERVICE_CENTER_NAME = "SERVICECENTER"; + + public static final String KIE_NAME = "KIE"; + + public static final String CONFIG_CENTER_NAME = "CseConfigCenter"; + + public static final String CSE_MONITORING_NAME = "CseMonitoring"; + + private static final String SAME_ZONE = "sameZone"; + + private static final String SAME_REGION = "sameRegion"; + + private Map> zoneAndRegion = new HashMap<>(); + + private String name; + + public RefreshEndpointEvent(Map> zoneAndRegion, String name) { + this.zoneAndRegion = zoneAndRegion; + this.name = name; + } + + public List getSameZone() { + if (zoneAndRegion.get(SAME_ZONE).isEmpty()) { + return new ArrayList<>(); + } + return zoneAndRegion.get(SAME_ZONE); + } + + public List getSameRegion() { + if (zoneAndRegion.get(SAME_REGION).isEmpty()) { + return new ArrayList<>(); + } + return zoneAndRegion.get(SAME_REGION); + } + + public Map> getZoneAndRegion() { + return zoneAndRegion; + } + + public void setZoneAndRegion(Map> zoneAndRegion) { + this.zoneAndRegion = zoneAndRegion; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java index c33c04a96f8..cc10ae8e142 100644 --- a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/task/AbstractTask.java @@ -20,23 +20,25 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AbstractTask { public class BackOffSleepTask implements Task { - final long base = 3000; + private static final long BASE = 3000; - final long max = 10 * 60 * 10000; + private static final long MAX = 10 * 60 * 1000; long waitTime; Task nextTask; public BackOffSleepTask(int failedCount, Task nextTask) { - this.waitTime = failedCount * failedCount * base; + this.waitTime = failedCount * failedCount * BASE; this.nextTask = nextTask; } @@ -47,7 +49,7 @@ public BackOffSleepTask(long waitTime, Task nextTask) { @Override public void execute() { - long time = Math.min(max, waitTime); + long time = Math.min(MAX, waitTime); try { Thread.sleep(time); } catch (InterruptedException e) { @@ -63,19 +65,25 @@ public void execute() { private volatile boolean running = true; + public static AtomicInteger taskCounter = new AtomicInteger(0); + + private ScheduledExecutorService addrCheckExecutor; + protected AbstractTask(String taskName) { initTaskPool(taskName); - Runtime.getRuntime().addShutdownHook(new Thread(taskName + "-shutdown-hook") { - @Override - public void run() { - AbstractTask.this.stop(); - } - }); + Runtime.getRuntime().addShutdownHook(new Thread(AbstractTask.this::stop, taskName + "-shutdown-hook")); } protected void initTaskPool(String taskName) { this.taskPool = Executors.newSingleThreadExecutor((task) -> - new Thread(task, taskName)); + new Thread(task, taskName + "-" + taskCounter.getAndIncrement())); + } + + protected void schedulerCheckAddressAvailable(String taskName, Runnable task, long delayTime) { + if (addrCheckExecutor == null) { + addrCheckExecutor = Executors.newScheduledThreadPool(1, (t) -> new Thread(t, taskName)); + } + addrCheckExecutor.scheduleWithFixedDelay(task, delayTime, delayTime, TimeUnit.MILLISECONDS); } protected void startTask(Task task) { @@ -101,6 +109,10 @@ public void stop() { running = false; this.taskPool.shutdown(); this.taskPool.awaitTermination(10, TimeUnit.SECONDS); + if (addrCheckExecutor != null) { + this.addrCheckExecutor.shutdown(); + this.addrCheckExecutor.awaitTermination(10, TimeUnit.SECONDS); + } } catch (InterruptedException e) { LOGGER.warn("tasks not shutdown in time {}", e.getMessage()); } diff --git a/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/utils/ServiceCombServiceAvailableUtils.java b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/utils/ServiceCombServiceAvailableUtils.java new file mode 100644 index 00000000000..9139e65f96a --- /dev/null +++ b/clients/http-client-common/src/main/java/org/apache/servicecomb/http/client/utils/ServiceCombServiceAvailableUtils.java @@ -0,0 +1,80 @@ +/* + * 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.http.client.utils; + +import org.apache.http.HttpStatus; +import org.apache.servicecomb.http.client.common.AbstractAddressManager; +import org.apache.servicecomb.http.client.common.HttpRequest; +import org.apache.servicecomb.http.client.common.HttpResponse; +import org.apache.servicecomb.http.client.common.HttpTransport; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; + +public class ServiceCombServiceAvailableUtils { + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCombServiceAvailableUtils.class); + + public static void checkAddressAvailable(AbstractAddressManager addressManager, String address, + HttpTransport httpTransport, String path) { + String formatUrl = addressManager.formatUrl(path, true, address); + HttpRequest httpRequest = new HttpRequest(formatUrl, null, null, HttpRequest.GET); + try { + HttpResponse response = httpTransport.doRequest(httpRequest); + if (response.getStatusCode() == HttpStatus.SC_OK) { + addressManager.recordSuccessState(address); + return; + } + + // old server does not provide the check api, using TCP checks whether the server is ready. + if (response.getStatusCode() == HttpStatus.SC_NOT_FOUND && telnetCheckAddress(address)) { + LOGGER.warn("[{}] path does not provide, tcp check address ready!", path); + addressManager.recordSuccessState(address); + } + } catch (IOException e) { + LOGGER.error("check isolation address [{}] available error!", address); + } + } + + private static boolean telnetCheckAddress(String address) { + URI ipPort = parseIpPortFromURI(address); + if (ipPort == null) { + return false; + } + try (Socket s = new Socket()) { + s.connect(new InetSocketAddress(ipPort.getHost(), ipPort.getPort()), 3000); + return true; + } catch (IOException e) { + LOGGER.warn("ping endpoint {} failed, It will be quarantined again.", address); + } + return false; + } + + private static URI parseIpPortFromURI(String address) { + try { + return new URI(address); + } catch (URISyntaxException e) { + LOGGER.error("build uri error with address [{}].", address); + return null; + } + } +} diff --git a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/AbstractAddressManagerTest.java b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/AbstractAddressManagerTest.java new file mode 100644 index 00000000000..b14d6827cb8 --- /dev/null +++ b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/AbstractAddressManagerTest.java @@ -0,0 +1,328 @@ +/* + * 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.http.client.common; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class AbstractAddressManagerTest { + + private static final List addresses = new ArrayList<>(); + + private static AbstractAddressManager addressManager1; + + private static AbstractAddressManager addressManager2; + + private static AbstractAddressManager addressManager3; + + @BeforeEach + public void setUp() throws NoSuchFieldException, IllegalAccessException { + addresses.add("http://127.0.0.1:30103"); + addresses.add("https://127.0.0.2:30103"); + addressManager1 = new AbstractAddressManager(addresses, "", ""); + addressManager2 = new AbstractAddressManager("project", addresses, "", ""); + addressManager3 = new AbstractAddressManager(null, addresses, "", ""); + Field addressManagerField = addressManager1.getClass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager1, 0); + addressManagerField = addressManager2.getClass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager2, 0); + addressManagerField = addressManager3.getClass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager3, 0); + } + + @AfterEach + public void tearDown() { + addresses.clear(); + addressManager1 = null; + addressManager2 = null; + addressManager3 = null; + } + + @Test + public void abstractAddressManagerTest() { + Assertions.assertNotNull(addressManager1); + Assertions.assertNotNull(addressManager2); + Assertions.assertNotNull(addressManager3); + + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + } + + @Test + public void recordStateTest() throws ExecutionException { + List addressAZ = new ArrayList<>(); + addressAZ.add("http://127.0.0.3:30100"); + List addressRG = new ArrayList<>(); + addressRG.add("http://127.0.0.4:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", addressRG); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST"); + AbstractAddressManager addressManager = new AbstractAddressManager(addresses, "", "") {}; + + addressManager.refreshEndpoint(event, "TEST"); + + String address = "http://127.0.0.3:30100"; + addressManager.recordFailState(address); + + Assertions.assertEquals("http://127.0.0.3:30100", addressManager.address()); + + addressManager.recordFailState(address); + Assertions.assertEquals("http://127.0.0.3:30100", addressManager.address()); + + // test fail 2 times ,it will not be isolated + addressManager.resetFailureStatus(address); + Assertions.assertEquals("http://127.0.0.3:30100", addressManager.address()); + + // test recodeStatus times + Map recodeStatus = addressManager.getAddressFailureStatus(); + Assertions.assertEquals(0, (int) recodeStatus.get("http://127.0.0.3:30100")); + + // test fail 3 times ,it will be isolated + addressManager.recordFailState(address); + addressManager.recordFailState(address); + addressManager.recordFailState(address); + Assertions.assertEquals("http://127.0.0.4:30100", addressManager.address()); + + // test restore isolation + addressManager.recordSuccessState("http://127.0.0.3:30100"); + Assertions.assertEquals("http://127.0.0.3:30100", addressManager.address()); + Assertions.assertEquals("http://127.0.0.3:30100", addressManager.address()); + } + + + @Test + public void testMultipleThread() throws Exception { + + AbstractAddressManager addressManager = new AbstractAddressManager(addresses, "", ""); + String address = "http://127.0.0.3:30100"; + + CountDownLatch latch = new CountDownLatch(2); + for (int i = 0; i < 2; i++) { + new Thread(() -> { + addressManager.recordFailState(address); + latch.countDown(); + }).start(); + } + latch.await(30, TimeUnit.SECONDS); + + Map recodeStatus = addressManager.getAddressFailureStatus(); + Assertions.assertEquals(2, (int) recodeStatus.get("http://127.0.0.3:30100")); + } + + @Test + public void addressForOnlyDefaultTest() { + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + + Assertions.assertEquals("https://127.0.0.2:30103/v3/project", addressManager2.address()); + Assertions.assertEquals("http://127.0.0.1:30103/v3/project", addressManager2.address()); + + Assertions.assertEquals("https://127.0.0.2:30103/v3/default", addressManager3.address()); + Assertions.assertEquals("http://127.0.0.1:30103/v3/default", addressManager3.address()); + } + + @Test + public void addressForOnlyAzTest() { + List addressAZ = new ArrayList<>(); + addressAZ.add("http://127.0.0.1:30100"); + addressAZ.add("https://127.0.0.2:30100"); + addressAZ.add("rest://127.0.0.1:30100?sslEnabled=true"); + addressAZ.add("rest://127.0.0.2:30100?sslEnabled=false"); + + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", new ArrayList<>()); + RefreshEndpointEvent event1 = new RefreshEndpointEvent(zoneAndRegion, "TEST"); + addressManager1.refreshEndpoint(event1, "TEST"); + + Assertions.assertEquals("https://127.0.0.2:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.1:30100", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.2:30100", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.2:30100", addressManager1.address()); + } + + @Test + public void addressForOnlyRegionTest() { + List addressRG = new ArrayList<>(); + addressRG.add("rest://127.0.0.5:30100?sslEnabled=true"); + addressRG.add("rest://127.0.0.6:30100"); + addressRG.add("http://127.0.0.7:30100"); + addressRG.add("https://127.0.0.8:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", new ArrayList<>()); + zoneAndRegion.put("sameRegion", addressRG); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST"); + addressManager1.refreshEndpoint(event, "TEST"); + + Assertions.assertEquals("http://127.0.0.6:30100", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.7:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.8:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.5:30100", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.6:30100", addressManager1.address()); + } + + @Test + public void addressForAzAndRegionTest() { + List addressAZ = new ArrayList<>(); + addressAZ.add("rest://127.0.0.1:30100?sslEnabled=true"); + addressAZ.add("https://127.0.0.2:30100"); + List addressRG = new ArrayList<>(); + addressRG.add("rest://127.0.0.3:30100?sslEnabled=true"); + addressRG.add("https://127.0.0.4:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", addressRG); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST"); + addressManager1.refreshEndpoint(event, "TEST"); + + Assertions.assertEquals("https://127.0.0.2:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.1:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.2:30100", addressManager1.address()); + + addressManager1.removeAddress("https://127.0.0.2:30100"); + addressManager1.removeAddress("https://127.0.0.1:30100"); + Assertions.assertEquals("https://127.0.0.3:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.4:30100", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.3:30100", addressManager1.address()); + + addressManager1.removeAddress("https://127.0.0.4:30100"); + addressManager1.removeAddress("https://127.0.0.3:30100"); + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + } + + @Test + public void sslEnabledTest() { + Assertions.assertTrue(addressManager1.sslEnabled()); + Assertions.assertFalse(addressManager1.sslEnabled()); + Assertions.assertTrue(addressManager1.sslEnabled()); + + Assertions.assertTrue(addressManager2.sslEnabled()); + Assertions.assertFalse(addressManager2.sslEnabled()); + Assertions.assertTrue(addressManager2.sslEnabled()); + } + + @Test + public void transformAddressTest() { + List address = new ArrayList<>(); + address.add("rest://127.0.0.1:30100?sslEnabled=true"); + address.add("rest://127.0.0.2:30100"); + address.add("http://127.0.0.3:30100"); + address.add("https://127.0.0.4:30100"); + + List formAddress = addressManager2.transformAddress(address); + + Assertions.assertEquals("rest://127.0.0.1:30100?sslEnabled=true/v3/project", formAddress.get(0)); + Assertions.assertEquals("rest://127.0.0.2:30100/v3/project", formAddress.get(1)); + Assertions.assertEquals("http://127.0.0.3:30100/v3/project", formAddress.get(2)); + Assertions.assertEquals("https://127.0.0.4:30100/v3/project", formAddress.get(3)); + + formAddress = addressManager3.transformAddress(address); + Assertions.assertEquals("rest://127.0.0.1:30100?sslEnabled=true/v3/default", formAddress.get(0)); + Assertions.assertEquals("rest://127.0.0.2:30100/v3/default", formAddress.get(1)); + Assertions.assertEquals("http://127.0.0.3:30100/v3/default", formAddress.get(2)); + Assertions.assertEquals("https://127.0.0.4:30100/v3/default", formAddress.get(3)); + } + + @Test + public void getUrlPrefixTest() { + Assertions.assertEquals("http://127.0.0.3:30100/v3/", addressManager2.getUrlPrefix("http://127.0.0.3:30100")); + Assertions.assertEquals("http://127.0.0.3:30100/v3/", addressManager3.getUrlPrefix("http://127.0.0.3:30100")); + } + + @Test + public void refreshEndpointTest() { + List addressAZ = new ArrayList<>(); + addressAZ.add("rest://127.0.0.1:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", new ArrayList<>()); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "TEST"); + + addressManager1.refreshEndpoint(event, "KIE"); + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.2:30103", addressManager1.address()); + + addressManager2.refreshEndpoint(event, "TEST"); + Assertions.assertEquals("http://127.0.0.1:30100", addressManager2.address()); + Assertions.assertEquals("http://127.0.0.1:30100", addressManager2.address()); + } + + @Test + public void normalizeIPV4Test() { + String uri = addressManager1.normalizeUri("rest://127.0.0.1:30100?sslEnabled=true"); + Assertions.assertEquals("https://127.0.0.1:30100", uri); + + uri = addressManager1.normalizeUri("rest://127.0.0.1:30100?sslEnabled=false"); + Assertions.assertEquals("http://127.0.0.1:30100", uri); + + uri = addressManager1.normalizeUri("rest://127.0.0.1:30100"); + Assertions.assertEquals("http://127.0.0.1:30100", uri); + } + + @Test + public void normalizeIPV6Test() { + String uri = addressManager1.normalizeUri("rest://[2008::7:957f:b2d6:1af4:a1f8]:30100?sslEnabled=true"); + Assertions.assertEquals("https://[2008::7:957f:b2d6:1af4:a1f8]:30100", uri); + + uri = addressManager1.normalizeUri("rest://[2008::7:957f:b2d6:1af4:a1f8]:30100"); + Assertions.assertEquals("http://[2008::7:957f:b2d6:1af4:a1f8]:30100", uri); + } + + @Test + public void compareAndGetAddressTest() { + List testAddr = new ArrayList<>(); + testAddr.add("https://192.168.20.160:30100"); + testAddr.add("https://127.0.0.1:30100"); + testAddr.add("https://127.0.0.3:30100"); + AbstractAddressManager manager = new AbstractAddressManager(testAddr, "", ""); + Assertions.assertTrue(manager.compareAndGetAddress("192.168.20.16").isEmpty()); + Assertions.assertEquals("https://192.168.20.160:30100", manager.compareAndGetAddress("192.168.20.160")); + } + + @Test + public void AddressAffinityTest() { + List testAddr = new ArrayList<>(); + testAddr.add("https://192.168.20.160:30100?region=region1&availableZone=zone1"); + testAddr.add("https://127.0.0.1:30100"); + AbstractAddressManager manager = new AbstractAddressManager(testAddr, "region1", "zone1"); + Assertions.assertEquals("https://192.168.20.160:30100", manager.address()); + + AbstractAddressManager manager2 = new AbstractAddressManager("default", testAddr, "region1", "zone1"); + Assertions.assertEquals("https://192.168.20.160:30100", manager2.address()); + } +} diff --git a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java index 15095745fae..2530b80145a 100644 --- a/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java +++ b/clients/http-client-common/src/test/java/org/apache/servicecomb/http/client/common/HttpTransportImplTest.java @@ -30,8 +30,8 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class HttpTransportImplTest { @@ -59,9 +59,9 @@ public void TestHttpTransport() throws IOException { HttpRequest httpRequest = new HttpRequest("111", null, null, HttpRequest.GET); HttpResponse actualResponse = httpTransport.get(httpRequest); - Assert.assertNotNull(actualResponse); - Assert.assertEquals(200, actualResponse.getStatusCode()); - Assert.assertEquals("OK", actualResponse.getMessage()); - Assert.assertEquals("Test", actualResponse.getContent()); + Assertions.assertNotNull(actualResponse); + Assertions.assertEquals(200, actualResponse.getStatusCode()); + Assertions.assertEquals("OK", actualResponse.getMessage()); + Assertions.assertEquals("Test", actualResponse.getContent()); } } diff --git a/clients/pom.xml b/clients/pom.xml index e5c4626ad53..49f481934cc 100644 --- a/clients/pom.xml +++ b/clients/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default 4.0.0 @@ -37,6 +37,7 @@ config-common config-kie-client config-center-client + dashboard-client diff --git a/clients/service-center-client/README.md b/clients/service-center-client/README.md index efa5e388a4a..a6b4c6d4936 100644 --- a/clients/service-center-client/README.md +++ b/clients/service-center-client/README.md @@ -1,15 +1,15 @@ ## ServiceComb-Service-Center Client for Java - Sample Java client for ServiceComb-Service-Center HTTP API. - If you want more information about the ServiceComb-Service-Center HTTP API, go [here](https://github.com/apache/servicecomb-service-center/blob/master/server/core/swagger/v4.yaml). - + Sample Java client for ServiceComb-Service-Center HTTP API. + If you want more information about the ServiceComb-Service-Center HTTP API, go [here](https://github.com/apache/servicecomb-service-center/blob/master/docs/openapi/v4.yaml). + ### Build & Install - + local Build from source : ``` maven clean install ``` - + add dependency to maven ``` @@ -79,14 +79,14 @@ MicroservicesResponse services = client.getMicroserviceList(); for(Microservice microservice : services.getServices()) { for (MicroserviceInstance instance: client.getMicroserviceInstanceList(microservice.getServiceId()).getInstances()) - { - client.sendHeartBeats(new HeartbeatsRequest(microservice.getServiceId(),instance.getInstanceId())); + { + client.sendHeartBeats(new HeartbeatsRequest(microservice.getServiceId(),instance.getInstanceId())); } } ``` #### Other API -You can see client API code and tests, go [here](https://github.com/apache/servicecomb-java-chassis/blob/master/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java) +You can see client API code and tests, go [here](https://github.com/apache/servicecomb-java-chassis/blob/master/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java) ### More development diff --git a/clients/service-center-client/pom.xml b/clients/service-center-client/pom.xml index ac6d6038535..ccc3900e9db 100755 --- a/clients/service-center-client/pom.xml +++ b/clients/service-center-client/pom.xml @@ -22,7 +22,7 @@ clients org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -38,15 +38,9 @@ - junit - junit - test - - - - org.mockito - mockito-core + com.google.guava + failureaccess test - \ No newline at end of file + diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java deleted file mode 100644 index df3e96c6fb6..00000000000 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/AddressManager.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.service.center.client; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.servicecomb.http.client.common.HttpUtils; - -public class AddressManager { - private final String projectName; - - private final List addresses; - - private int index = 0; - - public AddressManager(String projectName, List addresses) { - this.projectName = projectName; - this.addresses = new ArrayList<>(addresses.size()); - this.addresses.addAll(addresses); - } - - private String formatAddress(String address) { - try { - return address + "/v4/" + HttpUtils.encodeURLParam(this.projectName); - } catch (Exception e) { - throw new IllegalStateException("not possible"); - } - } - - public boolean sslEnabled() { - return address().startsWith("https://"); - } - - public String address() { - synchronized (this) { - index++; - if (index >= addresses.size()) { - index = 0; - } - return addresses.get(index); - } - } - - public String formatUrl(String url, boolean absoluteUrl) { - return absoluteUrl ? address() + url : formatAddress(address()) + url; - } -} diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/DiscoveryEvents.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/DiscoveryEvents.java index eac6880d52e..e45720f5ebb 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/DiscoveryEvents.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/DiscoveryEvents.java @@ -23,11 +23,11 @@ public abstract class DiscoveryEvents { public static class InstanceChangedEvent extends DiscoveryEvents { - private String appName; + private final String appName; - private String serviceName; + private final String serviceName; - private List instances; + private final List instances; public InstanceChangedEvent(String appName, String serviceName, List instances) { this.appName = appName; diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/RegistrationEvents.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/RegistrationEvents.java index 0da3ad6da66..d411913dfed 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/RegistrationEvents.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/RegistrationEvents.java @@ -17,38 +17,56 @@ package org.apache.servicecomb.service.center.client; +import org.apache.servicecomb.service.center.client.model.Microservice; +import org.apache.servicecomb.service.center.client.model.MicroserviceInstance; + public abstract class RegistrationEvents { - protected boolean success; + protected final boolean success; + + protected final Microservice microservice; - protected RegistrationEvents(boolean success) { + protected RegistrationEvents(boolean success, Microservice microservice) { this.success = success; + this.microservice = microservice; } public boolean isSuccess() { return this.success; } + public Microservice getMicroservice() { + return microservice; + } + public static class MicroserviceRegistrationEvent extends RegistrationEvents { - public MicroserviceRegistrationEvent(boolean success) { - super(success); + public MicroserviceRegistrationEvent(boolean success, Microservice microservice) { + super(success, microservice); } } public static class SchemaRegistrationEvent extends RegistrationEvents { - public SchemaRegistrationEvent(boolean success) { - super(success); + public SchemaRegistrationEvent(boolean success, Microservice microservice) { + super(success, microservice); } } public static class MicroserviceInstanceRegistrationEvent extends RegistrationEvents { - public MicroserviceInstanceRegistrationEvent(boolean success) { - super(success); + protected final MicroserviceInstance microserviceInstance; + + public MicroserviceInstanceRegistrationEvent(boolean success, Microservice microservice, + MicroserviceInstance microserviceInstance) { + super(success, microservice); + this.microserviceInstance = microserviceInstance; } } public static class HeartBeatEvent extends RegistrationEvents { - public HeartBeatEvent(boolean success) { - super(success); + protected final MicroserviceInstance microserviceInstance; + + public HeartBeatEvent(boolean success, Microservice microservice, + MicroserviceInstance microserviceInstance) { + super(success, microservice); + this.microserviceInstance = microserviceInstance; } } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterAddressManager.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterAddressManager.java new file mode 100644 index 00000000000..b19db919e81 --- /dev/null +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterAddressManager.java @@ -0,0 +1,49 @@ +/* + * 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.service.center.client; + +import java.util.List; + +import org.apache.servicecomb.http.client.common.AbstractAddressManager; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +public class ServiceCenterAddressManager extends AbstractAddressManager { + public ServiceCenterAddressManager(String projectName, List addresses, EventBus eventBus, String region, + String availableZone) { + super(projectName, addresses, region, availableZone); + eventBus.register(this); + } + + @Override + protected List transformAddress(List addresses) { + return addresses; + } + + @Override + protected String getUrlPrefix(String address) { + return address + V4_PREFIX; + } + + @Subscribe + public void onRefreshEndpointEvent(RefreshEndpointEvent event) { + refreshEndpoint(event, RefreshEndpointEvent.SERVICE_CENTER_NAME); + } +} diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java index 4dca259d348..97aeaa9931a 100755 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterClient.java @@ -25,6 +25,7 @@ import java.util.Map; import org.apache.http.HttpStatus; +import org.apache.http.client.config.RequestConfig; import org.apache.http.client.utils.URIBuilder; import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; @@ -32,13 +33,13 @@ import org.apache.servicecomb.http.client.common.HttpTransport; import org.apache.servicecomb.http.client.common.HttpTransportFactory; import org.apache.servicecomb.http.client.common.HttpUtils; -import org.apache.servicecomb.service.center.client.OperationEvents.UnAuthorizedOperationEvent; import org.apache.servicecomb.service.center.client.exception.OperationException; import org.apache.servicecomb.service.center.client.model.CreateMicroserviceInstanceRequest; import org.apache.servicecomb.service.center.client.model.CreateMicroserviceRequest; import org.apache.servicecomb.service.center.client.model.CreateSchemaRequest; import org.apache.servicecomb.service.center.client.model.ErrorMessage; import org.apache.servicecomb.service.center.client.model.FindMicroserviceInstancesResponse; +import org.apache.servicecomb.service.center.client.model.Framework; import org.apache.servicecomb.service.center.client.model.GetSchemaListResponse; import org.apache.servicecomb.service.center.client.model.GetSchemaResponse; import org.apache.servicecomb.service.center.client.model.HeartbeatsRequest; @@ -55,8 +56,10 @@ import org.apache.servicecomb.service.center.client.model.RegisteredMicroserviceInstanceResponse; import org.apache.servicecomb.service.center.client.model.RegisteredMicroserviceResponse; import org.apache.servicecomb.service.center.client.model.SchemaInfo; +import org.apache.servicecomb.service.center.client.model.UpdatePropertiesRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; import com.google.common.eventbus.EventBus; @@ -64,31 +67,53 @@ public class ServiceCenterClient implements ServiceCenterOperation { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCenterClient.class); - private ServiceCenterRawClient httpClient; + private static final String CLIENT_CONNECT_TIMEOUT = "servicecomb.registry.sc.client.timeout.connect"; - private EventBus eventBus; + private static final String CLIENT_REQUEST_TIMEOUT = "servicecomb.registry.sc.client.timeout.request"; - public ServiceCenterClient(ServiceCenterRawClient httpClient) { + private static final String CLIENT_SOCKET_TIMEOUT = "servicecomb.registry.sc.client.timeout.socket"; + + private final ServiceCenterRawClient httpClient; + + private final ServiceCenterAddressManager addressManager; + + public ServiceCenterClient(ServiceCenterRawClient httpClient, ServiceCenterAddressManager addressManager) { this.httpClient = httpClient; + this.addressManager = addressManager; } public ServiceCenterClient setEventBus(EventBus eventBus) { - this.eventBus = eventBus; + addressManager.setEventBus(eventBus); + this.httpClient.setEventBus(eventBus); return this; } - public ServiceCenterClient(AddressManager addressManager, + public ServiceCenterClient(ServiceCenterAddressManager addressManager, SSLProperties sslProperties, RequestAuthHeaderProvider requestAuthHeaderProvider, String tenantName, - Map extraGlobalHeaders) { - HttpTransport httpTransport = HttpTransportFactory.createHttpTransport(sslProperties, requestAuthHeaderProvider); + Map extraGlobalHeaders, + Environment environment) { + HttpTransport httpTransport = HttpTransportFactory.createHttpTransport(sslProperties, requestAuthHeaderProvider, + buildRequestConfig(environment)); httpTransport.addHeaders(extraGlobalHeaders); this.httpClient = new ServiceCenterRawClient.Builder() .setTenantName(tenantName) .setAddressManager(addressManager) .setHttpTransport(httpTransport).build(); + this.addressManager = addressManager; + } + + private RequestConfig buildRequestConfig(Environment environment) { + RequestConfig.Builder builder = HttpTransportFactory.defaultRequestConfig(); + if (environment == null) { + return builder.build(); + } + builder.setConnectTimeout(environment.getProperty(CLIENT_CONNECT_TIMEOUT, int.class, 5000)); + builder.setConnectionRequestTimeout(environment.getProperty(CLIENT_REQUEST_TIMEOUT, int.class, 5000)); + builder.setSocketTimeout(environment.getProperty(CLIENT_SOCKET_TIMEOUT, int.class, 5000)); + return builder.build(); } @Override @@ -98,7 +123,6 @@ public MicroserviceInstancesResponse getServiceCenterInstances() { if (response.getStatusCode() == HttpStatus.SC_OK) { return HttpUtils.deserialize(response.getContent(), MicroserviceInstancesResponse.class); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service-center instances fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -119,7 +143,6 @@ public RegisteredMicroserviceResponse registerMicroservice(Microservice microser if (response.getStatusCode() == HttpStatus.SC_OK) { return HttpUtils.deserialize(response.getContent(), RegisteredMicroserviceResponse.class); } - sendUnAuthorizedEvent(response); throw new OperationException( "register service fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -137,7 +160,6 @@ public MicroservicesResponse getMicroserviceList() { if (response.getStatusCode() == HttpStatus.SC_OK) { return HttpUtils.deserialize(response.getContent(), MicroservicesResponse.class); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service List fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -162,7 +184,6 @@ public RegisteredMicroserviceResponse queryServiceId(Microservice microservice) if (response.getStatusCode() == HttpStatus.SC_OK) { return HttpUtils.deserialize(response.getContent(), RegisteredMicroserviceResponse.class); } - sendUnAuthorizedEvent(response); LOGGER.info("Query serviceId fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() + "; content = " + response.getContent()); @@ -185,7 +206,6 @@ public Microservice getMicroserviceByServiceId(String serviceId) { .deserialize(response.getContent(), MicroserviceResponse.class); return microserviceResponse.getService(); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service message fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -207,7 +227,6 @@ public RegisteredMicroserviceInstanceResponse registerMicroserviceInstance(Micro if (response.getStatusCode() == HttpStatus.SC_OK) { return HttpUtils.deserialize(response.getContent(), RegisteredMicroserviceInstanceResponse.class); } - sendUnAuthorizedEvent(response); throw new OperationException( "register service instance fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -243,7 +262,11 @@ public FindMicroserviceInstancesResponse findMicroserviceInstance(String consume result.setModified(false); return result; } - sendUnAuthorizedEvent(response); + if (response.getStatusCode() == HttpStatus.SC_TOO_MANY_REQUESTS) { + LOGGER.warn("rate limited, keep the local service {}#{} instance cache unchanged.", appId, serviceName); + result.setModified(false); + return result; + } throw new OperationException( "get service instances list fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -262,7 +285,6 @@ public MicroserviceInstancesResponse getMicroserviceInstanceList(String serviceI if (response.getStatusCode() == HttpStatus.SC_OK) { return HttpUtils.deserialize(response.getContent(), MicroserviceInstancesResponse.class); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service instances list fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -283,7 +305,6 @@ public MicroserviceInstance getMicroserviceInstance(String serviceId, String ins .deserialize(response.getContent(), MicroserviceInstanceResponse.class); return instanceResponse.getInstance(); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service instance message fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -303,7 +324,6 @@ public void deleteMicroserviceInstance(String serviceId, String instanceId) { LOGGER.info("Delete service instance successfully."); return; } - sendUnAuthorizedEvent(response); throw new OperationException( "delete service instance fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -323,7 +343,6 @@ public boolean updateMicroserviceInstanceStatus(String serviceId, String instanc if (response.getStatusCode() == HttpStatus.SC_OK) { return true; } - sendUnAuthorizedEvent(response); throw new OperationException( "update service instance status fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -342,7 +361,6 @@ public void sendHeartBeats(HeartbeatsRequest heartbeatsRequest) { if (response.getStatusCode() == HttpStatus.SC_OK) { return; } - sendUnAuthorizedEvent(response); throw new OperationException( "heartbeats fails, statusCode = " + response.getStatusCode() + "; message = " + response.getMessage() + "; content = " + response.getContent()); @@ -362,7 +380,6 @@ public boolean sendHeartBeat(String serviceId, String instanceId) { if (response.getStatusCode() == HttpStatus.SC_OK) { return true; } - sendUnAuthorizedEvent(response); throw new OperationException( "heartbeats fails, statusCode = " + response.getStatusCode() + "; message = " + response.getMessage() + "; content = " + response.getContent()); @@ -387,7 +404,6 @@ public List getServiceSchemasList(String serviceId, boolean withCont .deserialize(response.getContent(), GetSchemaListResponse.class); return getSchemaResponse.getSchemas(); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service schemas list fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -414,7 +430,6 @@ public String getServiceSchemaContext(String serviceId, String schemaId) { GetSchemaResponse getSchemaResponse = HttpUtils.deserialize(response.getContent(), GetSchemaResponse.class); return getSchemaResponse.getSchema(); } - sendUnAuthorizedEvent(response); throw new OperationException( "get service schema context fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -434,7 +449,6 @@ public boolean registerSchema(String serviceId, String schemaId, CreateSchemaReq if (response.getStatusCode() == HttpStatus.SC_OK) { return true; } - sendUnAuthorizedEvent(response); throw new OperationException( "update service schema fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -457,7 +471,6 @@ public boolean updateServiceSchemaContext(String serviceId, SchemaInfo schemaInf if (response.getStatusCode() == HttpStatus.SC_OK) { return true; } - sendUnAuthorizedEvent(response); throw new OperationException( "update service schema fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -477,7 +490,6 @@ public boolean batchUpdateServiceSchemaContext(String serviceId, ModifySchemasRe if (response.getStatusCode() == HttpStatus.SC_OK) { return true; } - sendUnAuthorizedEvent(response); throw new OperationException( "update service schema fails, statusCode = " + response.getStatusCode() + "; message = " + response .getMessage() @@ -488,18 +500,12 @@ public boolean batchUpdateServiceSchemaContext(String serviceId, ModifySchemasRe } } - private void sendUnAuthorizedEvent(HttpResponse response) { - if (this.eventBus != null && response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { - this.eventBus.post(new UnAuthorizedOperationEvent()); - } - } - @Override - public RbacTokenResponse queryToken(RbacTokenRequest request) { + public RbacTokenResponse queryToken(RbacTokenRequest request, String host) { try { + String queryAddress = addressManager.compareAndGetAddress(host); HttpResponse response = httpClient - .postHttpRequestAbsoluteUrl("/v4/token", null, - HttpUtils.serialize(request)); + .postHttpRequestAbsoluteUrl("/v4/token", null, HttpUtils.serialize(request), queryAddress); if (response.getStatusCode() == HttpStatus.SC_OK) { RbacTokenResponse result = HttpUtils.deserialize(response.getContent(), RbacTokenResponse.class); result.setStatusCode(HttpStatus.SC_OK); @@ -527,4 +533,37 @@ public RbacTokenResponse queryToken(RbacTokenRequest request) { "query token failed", e); } } + + @Override + public boolean updateMicroserviceProperties(String serviceId, Map serviceProperties, + Framework framework) { + try { + UpdatePropertiesRequest request = new UpdatePropertiesRequest(); + request.setProperties(serviceProperties); + request.setFramework(framework); + HttpResponse response = httpClient.putHttpRequest( + "/registry/microservices/" + serviceId + "/properties", null, HttpUtils.serialize(request)); + if (response.getStatusCode() == HttpStatus.SC_OK) { + return true; + } + throw new OperationException( + "update service properties fails, statusCode = " + response.getStatusCode() + "; message = " + response + .getMessage() + + "; content = " + response.getContent()); + } catch (IOException e) { + throw new OperationException( + "update service properties fails", e); + } + } + + @Override + public void checkIsolationAddressAvailable() { + List isolationAddresses = addressManager.getIsolationAddresses(); + if (isolationAddresses.isEmpty()) { + return; + } + for (String address : isolationAddresses) { + httpClient.checkAddressAvailable(address); + } + } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java index 43a9f9a5387..a1ab524c187 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterDiscovery.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import org.apache.servicecomb.http.client.task.AbstractTask; @@ -45,6 +46,8 @@ public class ServiceCenterDiscovery extends AbstractTask { private static final String ALL_VERSION = "0+"; + private static volatile boolean pullInstanceTaskOnceInProgress = false; + public static class SubscriptionKey { final String appId; @@ -80,7 +83,7 @@ public static class SubscriptionValue { List instancesCache; } - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCenterRegistration.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCenterDiscovery.class); private final ServiceCenterClient serviceCenterClient; @@ -90,8 +93,6 @@ public static class SubscriptionValue { private final Map instancesCache = new ConcurrentHashMap<>(); - private List failedInstances = new ArrayList<>(); - private final Map microserviceCache = new ConcurrentHashMap<>(); private long pollInterval = 15000; @@ -100,6 +101,8 @@ public static class SubscriptionValue { private final Object lock = new Object(); + private final Random random = new Random(); + public ServiceCenterDiscovery(ServiceCenterClient serviceCenterClient, EventBus eventBus) { super("service-center-discovery-task"); this.serviceCenterClient = serviceCenterClient; @@ -131,7 +134,7 @@ public void registerIfNotPresent(SubscriptionKey subscriptionKey) { synchronized (lock) { if (this.instancesCache.get(subscriptionKey) == null) { SubscriptionValue value = new SubscriptionValue(); - pullInstance(subscriptionKey, value); + pullInstance(subscriptionKey, value, false); this.instancesCache.put(subscriptionKey, value); } } @@ -144,14 +147,20 @@ public List getInstanceCache(SubscriptionKey key) { @Subscribe public void onPullInstanceEvent(PullInstanceEvent event) { - pullAllInstance(); + // to avoid too many pulls queued. + if (pullInstanceTaskOnceInProgress) { + return; + } + pullInstanceTaskOnceInProgress = true; + startTask(new PullInstanceOnceTask()); } - private void pullInstance(SubscriptionKey k, SubscriptionValue v) { + private void pullInstance(SubscriptionKey k, SubscriptionValue v, boolean sendChangedEvent) { if (myselfServiceId == null) { // registration not ready return; } + try { FindMicroserviceInstancesResponse instancesResponse = serviceCenterClient .findMicroserviceInstance(myselfServiceId, k.appId, k.serviceName, ALL_VERSION, v.revision); @@ -159,10 +168,10 @@ private void pullInstance(SubscriptionKey k, SubscriptionValue v) { List instances = instancesResponse.getMicroserviceInstancesResponse().getInstances() == null ? Collections.emptyList() : instancesResponse.getMicroserviceInstancesResponse().getInstances(); setMicroserviceInfo(instances); - LOGGER.info("Instance changed event, " - + "current: revision={}, instances={}; " - + "origin: revision={}, instances={}; " - + "appId={}, serviceName={}", + LOGGER.info("Instance changed event. " + + "Current: revision={}, instances={}. " + + "Origin: revision={}, instances={}. " + + "appId={}, serviceName={}.", instancesResponse.getRevision(), instanceToString(instances), v.revision, @@ -172,12 +181,14 @@ private void pullInstance(SubscriptionKey k, SubscriptionValue v) { ); v.instancesCache = instances; v.revision = instancesResponse.getRevision(); - eventBus.post(new InstanceChangedEvent(k.appId, k.serviceName, - v.instancesCache)); + if (sendChangedEvent) { + eventBus.post(new InstanceChangedEvent(k.appId, k.serviceName, + v.instancesCache)); + } } } catch (Exception e) { - LOGGER.error("find service {}#{} instance failed.", k.appId, k.serviceName, e); - failedInstances.add(k); + LOGGER.warn("find service {}#{} instance failed, remaining local instances cache [{}], cause message: {}", + k.appId, k.serviceName, instanceToString(v.instancesCache), e.getMessage()); } } @@ -201,19 +212,38 @@ class PullInstanceTask implements Task { public void execute() { pullAllInstance(); - startTask(new BackOffSleepTask(pollInterval, new PullInstanceTask())); + startTask(new BackOffSleepTask(buildPollIntervalWithSalt(), new PullInstanceTask())); + } + } + + private long buildPollIntervalWithSalt() { + int positive = random.nextInt(5); + int sign = random.nextBoolean() ? 1 : -1; + long currentPollInterval = pollInterval + sign * positive * 1000; + return currentPollInterval > 0 ? currentPollInterval : pollInterval; + } + + class PullInstanceOnceTask implements Task { + @Override + public void execute() { + try { + pullAllInstance(); + } finally { + pullInstanceTaskOnceInProgress = false; + } } } private synchronized void pullAllInstance() { + List emptyInstancesCache = new ArrayList<>(); instancesCache.forEach((k, v) -> { - pullInstance(k, v); + pullInstance(k, v, true); + if (v.instancesCache.isEmpty()) { + emptyInstancesCache.add(k); + } }); - if (failedInstances.isEmpty()) { - return; - } - failedInstances.forEach(item -> instancesCache.remove(item)); - failedInstances.clear(); + emptyInstancesCache.forEach(instancesCache::remove); + emptyInstancesCache.clear(); } private static String instanceToString(List instances) { @@ -227,10 +257,9 @@ private static String instanceToString(List instances) { sb.append(endpoint.length() > 64 ? endpoint.substring(0, 64) : endpoint); sb.append("|"); } - sb.append(instance.getServiceName()); + sb.append(instance.getStatus()); sb.append("|"); } - sb.append("#"); return sb.toString(); } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterOperation.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterOperation.java index 9c28ac36a8d..fd39a4ce963 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterOperation.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterOperation.java @@ -18,10 +18,12 @@ package org.apache.servicecomb.service.center.client; import java.util.List; +import java.util.Map; import org.apache.servicecomb.service.center.client.exception.OperationException; import org.apache.servicecomb.service.center.client.model.CreateSchemaRequest; import org.apache.servicecomb.service.center.client.model.FindMicroserviceInstancesResponse; +import org.apache.servicecomb.service.center.client.model.Framework; import org.apache.servicecomb.service.center.client.model.HeartbeatsRequest; import org.apache.servicecomb.service.center.client.model.Microservice; import org.apache.servicecomb.service.center.client.model.MicroserviceInstance; @@ -158,7 +160,6 @@ boolean updateMicroserviceInstanceStatus(String serviceId, String instanceId, * Batch send heartbeats to service-center * * @param heartbeatsRequest - * @return * @throws OperationException */ void sendHeartBeats(HeartbeatsRequest heartbeatsRequest); @@ -183,5 +184,19 @@ boolean updateMicroserviceInstanceStatus(String serviceId, String instanceId, * @return if heartbeat is successful * @throws OperationException If some problems happened to contact service center or non http 200 returned. */ - RbacTokenResponse queryToken(RbacTokenRequest request); + RbacTokenResponse queryToken(RbacTokenRequest request, String host); + + /** + * Update properties of microservice + * + * @return if update is successful + * @throws OperationException If some problems happened to contact service center or non http 200 returned. + */ + boolean updateMicroserviceProperties(String microserviceId, Map serviceProperties, + Framework framework); + + /** + * Check serviceCenter isolation address available + */ + void checkIsolationAddressAvailable(); } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java index 3b9a48bfe1b..e233f15fb52 100755 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClient.java @@ -21,84 +21,121 @@ import java.util.HashMap; import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpStatus; import org.apache.servicecomb.http.client.common.HttpRequest; import org.apache.servicecomb.http.client.common.HttpResponse; import org.apache.servicecomb.http.client.common.HttpTransport; +import org.apache.servicecomb.http.client.event.OperationEvents.UnAuthorizedOperationEvent; +import org.apache.servicecomb.http.client.utils.ServiceCombServiceAvailableUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.eventbus.EventBus; + public class ServiceCenterRawClient { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCenterRawClient.class); private static final String HEADER_TENANT_NAME = "x-domain-name"; - private String tenantName; + private static final String ADDRESS_CHECK_PATH = "/v4/default/registry/health/readiness"; + + private final String tenantName; + + private final HttpTransport httpTransport; - private HttpTransport httpTransport; + private final ServiceCenterAddressManager addressManager; - private AddressManager addressManager; + private EventBus eventBus; private ServiceCenterRawClient(String tenantName, HttpTransport httpTransport, - AddressManager addressManager) { + ServiceCenterAddressManager addressManager) { this.httpTransport = httpTransport; this.tenantName = tenantName; this.addressManager = addressManager; } + public void setEventBus(EventBus eventBus) { + this.eventBus = eventBus; + } + public HttpResponse getHttpRequest(String url, Map headers, String content) throws IOException { - return doHttpRequest(url, false, headers, content, HttpRequest.GET); + return doHttpRequest(url, false, headers, content, HttpRequest.GET, ""); } - public HttpResponse postHttpRequestAbsoluteUrl(String url, Map headers, String content) - throws IOException { - return doHttpRequest(url, true, headers, content, HttpRequest.POST); + public HttpResponse postHttpRequestAbsoluteUrl(String url, Map headers, String content, + String address) throws IOException { + return doHttpRequest(url, true, headers, content, HttpRequest.POST, address); } public HttpResponse postHttpRequest(String url, Map headers, String content) throws IOException { - return doHttpRequest(url, false, headers, content, HttpRequest.POST); + return doHttpRequest(url, false, headers, content, HttpRequest.POST, ""); } public HttpResponse putHttpRequest(String url, Map headers, String content) throws IOException { - return doHttpRequest(url, false, headers, content, HttpRequest.PUT); + return doHttpRequest(url, false, headers, content, HttpRequest.PUT, ""); } public HttpResponse deleteHttpRequest(String url, Map headers, String content) throws IOException { - return doHttpRequest(url, false, headers, content, HttpRequest.DELETE); + return doHttpRequest(url, false, headers, content, HttpRequest.DELETE, ""); } private HttpResponse doHttpRequest(String url, boolean absoluteUrl, Map headers, String content, - String method) - throws IOException { - - String address = addressManager.formatUrl(url, absoluteUrl); - if (headers == null) { - headers = new HashMap<>(); - } - headers.put(HEADER_TENANT_NAME, tenantName); - HttpRequest httpRequest = new HttpRequest(address, headers, content, method); - + String method, String queryAddress) throws IOException { + String address = StringUtils.isEmpty(queryAddress) ? addressManager.address() : queryAddress; + String formatUrl = addressManager.formatUrl(url, absoluteUrl, address); + HttpRequest httpRequest = buildHttpRequest(formatUrl, headers, content, method); + HttpResponse httpResponse; try { - return httpTransport.doRequest(httpRequest); + httpResponse = httpTransport.doRequest(httpRequest); + recordAndSendUnAuthorizedEvent(httpResponse, address); + return httpResponse; } catch (IOException e) { - String retryAddress = addressManager.formatUrl(url, absoluteUrl); - LOGGER.warn("send request to {} failed and retry to {} once. ", address, - retryAddress, e); - httpRequest = new HttpRequest(retryAddress, headers, content, method); + addressManager.recordFailState(address); + String retryAddress = addressManager.address(); + formatUrl = addressManager.formatUrl(url, absoluteUrl, retryAddress); + LOGGER.warn("send request to {} failed and retry to {} once. ", address, retryAddress, e); + httpRequest = new HttpRequest(formatUrl, headers, content, method); try { - return httpTransport.doRequest(httpRequest); + httpResponse = httpTransport.doRequest(httpRequest); + recordAndSendUnAuthorizedEvent(httpResponse, retryAddress); + return httpResponse; } catch (IOException ioException) { + addressManager.recordFailState(retryAddress); LOGGER.warn("retry to {} failed again. ", retryAddress, e); throw ioException; } } } + private void recordAndSendUnAuthorizedEvent(HttpResponse response, String address) { + if (this.eventBus != null && response.getStatusCode() == HttpStatus.SC_UNAUTHORIZED) { + LOGGER.warn("request unauthorized from server [{}], message [{}]", address, response.getMessage()); + addressManager.recordFailState(address); + this.eventBus.post(new UnAuthorizedOperationEvent(address)); + } else { + addressManager.recordSuccessState(address); + } + } + + public void checkAddressAvailable(String address) { + ServiceCombServiceAvailableUtils.checkAddressAvailable(addressManager, address, httpTransport, ADDRESS_CHECK_PATH); + } + + private HttpRequest buildHttpRequest(String url, Map headers, String content, String method) { + if (headers == null) { + headers = new HashMap<>(); + } + headers.put(HEADER_TENANT_NAME, tenantName); + return new HttpRequest(url, headers, content, method); + } + public static class Builder { private String tenantName; private HttpTransport httpTransport; - private AddressManager addressManager; + private ServiceCenterAddressManager addressManager; public Builder() { } @@ -113,7 +150,7 @@ public Builder setHttpTransport(HttpTransport httpTransport) { return this; } - public Builder setAddressManager(AddressManager addressManager) { + public Builder setAddressManager(ServiceCenterAddressManager addressManager) { this.addressManager = addressManager; return this; } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java index 0786feb7c79..93988ea8948 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterRegistration.java @@ -17,7 +17,9 @@ package org.apache.servicecomb.service.center.client; +import java.util.ArrayList; import java.util.List; +import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.http.client.task.AbstractTask; @@ -54,9 +56,9 @@ public class ServiceCenterRegistration extends AbstractTask { private MicroserviceInstance microserviceInstance; - private List schemaInfos; + private List schemaInfos = new ArrayList<>(); - private ServiceCenterConfiguration serviceCenterConfiguration; + private final ServiceCenterConfiguration serviceCenterConfiguration; private long heartBeatInterval = 15000; @@ -101,8 +103,18 @@ public ServiceCenterRegistration setSchemaInfos(List schemaInfos) { return this; } + public ServiceCenterRegistration addSchemaInfo(SchemaInfo schemaInfo) { + this.schemaInfos.add(schemaInfo); + return this; + } + + public List getSchemaInfos() { + return this.schemaInfos; + } + public void startRegistration() { startTask(new RegisterMicroserviceTask(0)); + schedulerCheckAddressAvailable("sc-addr-check", new CheckAddressTask(), heartBeatInterval); } class RegisterMicroserviceTask implements Task { @@ -120,46 +132,64 @@ public void execute() { RegisteredMicroserviceResponse response = serviceCenterClient.registerMicroservice(microservice); if (StringUtils.isEmpty(response.getServiceId())) { LOGGER.error("register microservice failed, and will try again."); - eventBus.post(new MicroserviceRegistrationEvent(false)); + eventBus.post(new MicroserviceRegistrationEvent(false, microservice)); startTask(new BackOffSleepTask(failedCount + 1, new RegisterMicroserviceTask(failedCount + 1))); return; } microservice.setServiceId(response.getServiceId()); microserviceInstance.setServiceId(response.getServiceId()); microserviceInstance.setMicroservice(microservice); - eventBus.post(new MicroserviceRegistrationEvent(true)); + eventBus.post(new MicroserviceRegistrationEvent(true, microservice)); startTask(new RegisterSchemaTask(0)); } else { Microservice newMicroservice = serviceCenterClient.getMicroserviceByServiceId(serviceResponse.getServiceId()); - dealIsSwaggerDifferent(newMicroservice); + + Map propertiesTemp = microservice.getProperties(); + microservice.setProperties(newMicroservice.getProperties()); + microservice.getProperties().putAll(propertiesTemp); + if (serviceCenterClient.updateMicroserviceProperties(serviceResponse.getServiceId(), + microservice.getProperties(), microservice.getFramework())) { + LOGGER.info( + "microservice is already registered. Update microservice properties successfully. properties=[{}], " + + "frameworkVersion [{}]", microservice.getProperties(), microservice.getFramework().getVersion()); + } else { + LOGGER.error("microservice is already registered. Update microservice properties failed. properties=[{}], " + + "frameworkVersion [{}]", microservice.getProperties(), microservice.getFramework().getVersion()); + } + microservice.setServiceId(serviceResponse.getServiceId()); microserviceInstance.setServiceId(serviceResponse.getServiceId()); microserviceInstance.setMicroservice(microservice); - eventBus.post(new MicroserviceRegistrationEvent(true)); - LOGGER.info("microservice is already registered, meta info like swagger contents will not be updated."); + if (isSwaggerDifferent(newMicroservice)) { + if (serviceCenterConfiguration.isCanOverwriteSwagger()) { + LOGGER.warn("Service has already registered, but schema ids not equal, try to register it again"); + eventBus.post(new MicroserviceRegistrationEvent(true, microservice)); + startTask(new RegisterSchemaTask(0)); + return; + } + if (serviceCenterConfiguration.isIgnoreSwaggerDifferent()) { + LOGGER.warn("Service has already registered, but schema ids not equal. Ignore and continue to register"); + } else { + throw new IllegalStateException( + "Service has already registered, but schema ids not equal, stop register. " + + "Change the microservice version or delete the old microservice info and try again."); + } + } + eventBus.post(new MicroserviceRegistrationEvent(true, microservice)); startTask(new RegisterMicroserviceInstanceTask(0)); } } catch (IllegalStateException e) { throw e; } catch (Exception e) { LOGGER.error("register microservice failed, and will try again.", e); - eventBus.post(new MicroserviceRegistrationEvent(false)); + eventBus.post(new MicroserviceRegistrationEvent(false, microservice)); startTask(new BackOffSleepTask(failedCount + 1, new RegisterMicroserviceTask(failedCount + 1))); } } } - private void dealIsSwaggerDifferent(Microservice newMicroservice) { - if (isListEquals(newMicroservice.getSchemas(), microservice.getSchemas())) { - return; - } - if (!serviceCenterConfiguration.isIgnoreSwaggerDifferent()) { - throw new IllegalStateException("Service has already registered, but schema ids not equal, stop register. " - + "Change the microservice version or delete the old microservice info and try again."); - } - LOGGER.warn("Service has already registered, but schema ids not equal. However, it will continue to register. " - + "If you want to eliminate this warning. you can Change the microservice version or delete the old " + - "microservice info and try again. eg: version:1.0.0 -> 1.0.1"); + private boolean isSwaggerDifferent(Microservice newMicroservice) { + return !isListEquals(newMicroservice.getSchemas(), microservice.getSchemas()); } private boolean isListEquals(List one, List two) { @@ -178,7 +208,7 @@ public void execute() { try { if (schemaInfos == null || schemaInfos.isEmpty()) { LOGGER.warn("no schemas defined for this microservice."); - eventBus.post(new SchemaRegistrationEvent(true)); + eventBus.post(new SchemaRegistrationEvent(true, microservice)); startTask(new RegisterMicroserviceInstanceTask(0)); return; } @@ -189,18 +219,18 @@ public void execute() { request.setSummary(schemaInfo.getSummary()); if (!serviceCenterClient.registerSchema(microservice.getServiceId(), schemaInfo.getSchemaId(), request)) { LOGGER.error("register schema content failed, and will try again."); - eventBus.post(new SchemaRegistrationEvent(false)); + eventBus.post(new SchemaRegistrationEvent(false, microservice)); // back off by multiply startTask(new BackOffSleepTask(failedCount + 1, new RegisterSchemaTask((failedCount + 1) * 2))); return; } } - eventBus.post(new SchemaRegistrationEvent(true)); + eventBus.post(new SchemaRegistrationEvent(true, microservice)); startTask(new RegisterMicroserviceInstanceTask(0)); } catch (Exception e) { LOGGER.error("register schema content failed, and will try again.", e); - eventBus.post(new SchemaRegistrationEvent(false)); + eventBus.post(new SchemaRegistrationEvent(false, microservice)); // back off by multiply startTask(new BackOffSleepTask(failedCount + 1, new RegisterSchemaTask((failedCount + 1) * 2))); } @@ -221,25 +251,25 @@ public void execute() { .registerMicroserviceInstance(microserviceInstance); if (instance == null) { LOGGER.error("register microservice instance failed, and will try again."); - eventBus.post(new MicroserviceInstanceRegistrationEvent(false)); + eventBus.post(new MicroserviceInstanceRegistrationEvent(false, microservice, microserviceInstance)); startTask(new BackOffSleepTask(failedCount + 1, new RegisterMicroserviceInstanceTask(failedCount + 1))); } else { microserviceInstance.setInstanceId(instance.getInstanceId()); LOGGER.info("register microservice successfully, service id={}, instance id={}", microservice.getServiceId(), microserviceInstance.getInstanceId()); - eventBus.post(new MicroserviceInstanceRegistrationEvent(true)); + eventBus.post(new MicroserviceInstanceRegistrationEvent(true, microservice, microserviceInstance)); startTask(new SendHeartBeatTask(0)); } } catch (Exception e) { LOGGER.error("register microservice instance failed, and will try again.", e); - eventBus.post(new MicroserviceInstanceRegistrationEvent(false)); + eventBus.post(new MicroserviceInstanceRegistrationEvent(false, microservice, microserviceInstance)); startTask(new BackOffSleepTask(failedCount + 1, new RegisterMicroserviceInstanceTask(failedCount + 1))); } } } class SendHeartBeatTask implements Task { - final int failedRetry = 3; + private static final int FAILED_RETRY = 3; int failedCount; @@ -250,27 +280,39 @@ class SendHeartBeatTask implements Task { @Override public void execute() { try { - if (failedCount >= failedRetry) { - eventBus.post(new HeartBeatEvent(false)); + if (failedCount >= FAILED_RETRY) { + eventBus.post(new HeartBeatEvent(false, microservice, microserviceInstance)); startTask(new RegisterMicroserviceTask(0)); return; } if (!serviceCenterClient.sendHeartBeat(microservice.getServiceId(), microserviceInstance.getInstanceId())) { - LOGGER.error("send heart failed, and will try again."); - eventBus.post(new HeartBeatEvent(false)); + LOGGER.warn("send heart failed, and will try again."); + eventBus.post(new HeartBeatEvent(false, microservice, microserviceInstance)); startTask(new BackOffSleepTask(failedCount + 1, new SendHeartBeatTask(failedCount + 1))); } else { // wait 10 * 3000 ms and send heart beat again. - eventBus.post(new HeartBeatEvent(true)); + eventBus.post(new HeartBeatEvent(true, microservice, microserviceInstance)); startTask( new BackOffSleepTask(Math.max(heartBeatInterval, heartBeatRequestTimeout), new SendHeartBeatTask(0))); } } catch (Exception e) { - LOGGER.error("send heart failed, and will try again.", e); - eventBus.post(new HeartBeatEvent(false)); + // If heartbeat failures three times, log error stack help troubleshooting. Others just log message as warn. + if (failedCount == 2) { + LOGGER.error("send heart failed, and will try again.", e); + } else { + LOGGER.warn("send heart failed, and will try again. message [{}]", e.getMessage()); + } + eventBus.post(new HeartBeatEvent(false, microservice, microserviceInstance)); startTask(new BackOffSleepTask(failedCount + 1, new SendHeartBeatTask(failedCount + 1))); } } } + + class CheckAddressTask implements Runnable { + @Override + public void run() { + serviceCenterClient.checkIsolationAddressAvailable(); + } + } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java index d8faafabe1b..9f24a74a55a 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/ServiceCenterWatch.java @@ -17,12 +17,15 @@ package org.apache.servicecomb.service.center.client; +import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.servicecomb.foundation.auth.SignRequest; import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; import org.apache.servicecomb.http.client.common.WebSocketListener; @@ -51,7 +54,7 @@ public class ServiceCenterWatch implements WebSocketListener { private static final long SLEEP_MAX = 10 * 60 * 10000; - private final AddressManager addressManager; + private final ServiceCenterAddressManager addressManager; private final SSLProperties sslProperties; @@ -67,7 +70,7 @@ public class ServiceCenterWatch implements WebSocketListener { private String serviceId; - private int continuousError = 0; + private AtomicInteger continuousError = new AtomicInteger(0); private final AtomicBoolean reconnecting = new AtomicBoolean(false); @@ -78,7 +81,7 @@ public class ServiceCenterWatch implements WebSocketListener { private final ExecutorService connector = Executors.newFixedThreadPool(1, (r) -> new Thread(r, "web-socket-connector")); - public ServiceCenterWatch(AddressManager addressManager, + public ServiceCenterWatch(ServiceCenterAddressManager addressManager, SSLProperties sslProperties, RequestAuthHeaderProvider requestAuthHeaderProvider, String tenantName, @@ -102,25 +105,37 @@ public void startWatch(String project, String serviceId) { private void startWatch() { connector.submit(() -> { backOff(); - + String address = addressManager.address(); try { Map headers = new HashMap<>(); headers.put("x-domain-name", this.tenantName); headers.putAll(this.extraGlobalHeaders); - headers.putAll(this.requestAuthHeaderProvider.loadAuthHeader(null)); - currentServerUri = convertAddress(); + headers.putAll(this.requestAuthHeaderProvider.loadAuthHeader(createSignRequest(address))); + currentServerUri = convertAddress(address); LOGGER.info("start watch to address {}", currentServerUri); webSocketTransport = new WebSocketTransport(currentServerUri, sslProperties, headers, this); webSocketTransport.connectBlocking(); + addressManager.recordSuccessState(address); } catch (Exception e) { + addressManager.recordFailState(address); LOGGER.error("start watch failed. ", e); } }); } - private String convertAddress() { - String address = addressManager.address(); + private SignRequest createSignRequest(String url) { + try { + URI uri = URI.create(url); + SignRequest signRequest = new SignRequest(); + signRequest.setEndpoint(uri); + return signRequest; + } catch (Exception e) { + return null; + } + } + + private String convertAddress(String address) { String url = String.format(WATCH, project, serviceId); if (address.startsWith(HTTP)) { return WS + address.substring(HTTP.length()) + url; @@ -129,7 +144,6 @@ private String convertAddress() { if (address.startsWith(HTTPS)) { return WSS + address.substring(HTTPS.length()) + url; } - return address + url; } @@ -143,7 +157,7 @@ private void reconnect() { if (reconnecting.getAndSet(true)) { return; } - continuousError++; + continuousError.incrementAndGet(); if (webSocketTransport != null) { webSocketTransport.close(); } @@ -151,11 +165,11 @@ private void reconnect() { } private void backOff() { - if (this.continuousError <= 0) { + if (this.continuousError.get() <= 0) { return; } try { - Thread.sleep(Math.min(SLEEP_MAX, this.continuousError * this.continuousError * SLEEP_BASE)); + Thread.sleep(Math.min(SLEEP_MAX, this.continuousError.get() * this.continuousError.get() * SLEEP_BASE)); } catch (InterruptedException e) { // do not care } @@ -183,7 +197,7 @@ public void onOpen(ServerHandshake serverHandshake) { LOGGER.info("web socket connected to server {}, status={}, message={}", currentServerUri, serverHandshake.getHttpStatus(), serverHandshake.getHttpStatusMessage()); - continuousError = 0; + continuousError.set(0); reconnecting.set(false); } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/HeartbeatsRequest.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/HeartbeatsRequest.java index 9235523c3b6..9f4ea115cfe 100755 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/HeartbeatsRequest.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/HeartbeatsRequest.java @@ -24,7 +24,7 @@ public class HeartbeatsRequest { private List Instances; public HeartbeatsRequest(String serviceId, String instanceId) { - List instances = new ArrayList(); + List instances = new ArrayList<>(); instances.add(new InstancesRequest(serviceId, instanceId)); this.Instances = instances; } @@ -41,7 +41,7 @@ public void addInstances(InstancesRequest instancesRequest) { if (this.Instances != null) { this.Instances.add(instancesRequest); } else { - this.Instances = new ArrayList(); + this.Instances = new ArrayList<>(); this.Instances.add(instancesRequest); } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java index 1c2fc88a1db..a034e57569f 100755 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/Microservice.java @@ -208,4 +208,8 @@ public List getPaths() { public void setPaths(List paths) { this.paths = paths; } + + public void addSchema(String schema) { + this.schemas.add(schema); + } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java index 068501a84ba..7f03c314043 100755 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/MicroserviceInstance.java @@ -36,13 +36,13 @@ public class MicroserviceInstance { private String version; - private List endpoints = new ArrayList(); + private List endpoints = new ArrayList<>(); private String hostName; private MicroserviceInstanceStatus status; - private Map properties = new HashMap(); // reserved key list: region|az|stage|group + private Map properties = new HashMap<>(); // reserved key list: region|az|stage|group private HealthCheck healthCheck; @@ -147,6 +147,11 @@ public void setMicroservice(Microservice microservice) { this.microservice = microservice; } + @JsonIgnore + public Microservice getMicroservice() { + return this.microservice; + } + @JsonIgnore public String getServiceName() { return this.microservice.getServiceName(); @@ -156,4 +161,12 @@ public String getServiceName() { public String getApplicationName() { return this.microservice.getAppId(); } + + public void addEndpoint(String endpoint) { + this.endpoints.add(endpoint); + } + + public void addProperty(String key, String value) { + this.properties.put(key, value); + } } diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/SchemaInfo.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/SchemaInfo.java index 720e0e98b0e..40180433d0b 100755 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/SchemaInfo.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/SchemaInfo.java @@ -57,4 +57,4 @@ public String getSummary() { public void setSummary(String summary) { this.summary = summary; } -} \ No newline at end of file +} diff --git a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java index a452259809e..bc7618aa0f5 100644 --- a/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/ServiceCenterConfiguration.java @@ -24,14 +24,25 @@ public class ServiceCenterConfiguration { * when swagger is different between local with remote serviceCenter. if ignoreSwaggerDifferent is true. * it will ignore the different and continue the program. otherwise, the program will be stop. */ - private Boolean ignoreSwaggerDifferent; + private boolean ignoreSwaggerDifferent; - public Boolean isIgnoreSwaggerDifferent() { + private boolean canOverwriteSwagger = true; + + public boolean isIgnoreSwaggerDifferent() { return ignoreSwaggerDifferent; } - public ServiceCenterConfiguration setIgnoreSwaggerDifferent(Boolean ignoreSwaggerDifferent) { + public boolean isCanOverwriteSwagger(){ + return canOverwriteSwagger; + } + + public ServiceCenterConfiguration setIgnoreSwaggerDifferent(boolean ignoreSwaggerDifferent) { this.ignoreSwaggerDifferent = ignoreSwaggerDifferent; return this; } + + public ServiceCenterConfiguration setCanOverwriteSwagger(boolean canOverwriteSwagger) { + this.canOverwriteSwagger = canOverwriteSwagger; + return this; + } } diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/request/UpdatePropertiesRequest.java b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/UpdatePropertiesRequest.java similarity index 81% rename from service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/request/UpdatePropertiesRequest.java rename to clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/UpdatePropertiesRequest.java index 5e08a22a9b4..d7d4b093930 100644 --- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/api/request/UpdatePropertiesRequest.java +++ b/clients/service-center-client/src/main/java/org/apache/servicecomb/service/center/client/model/UpdatePropertiesRequest.java @@ -15,16 +15,15 @@ * limitations under the License. */ -package org.apache.servicecomb.serviceregistry.api.request; +package org.apache.servicecomb.service.center.client.model; import java.util.Map; -/** - * 更新微服务和实例properties的request - */ public class UpdatePropertiesRequest { private Map properties; + private Framework framework; + public Map getProperties() { return properties; } @@ -32,4 +31,12 @@ public Map getProperties() { public void setProperties(Map properties) { this.properties = properties; } + + public Framework getFramework() { + return framework; + } + + public void setFramework(Framework framework) { + this.framework = framework; + } } diff --git a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterAddressManagerTest.java b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterAddressManagerTest.java new file mode 100644 index 00000000000..a2888cfad1b --- /dev/null +++ b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterAddressManagerTest.java @@ -0,0 +1,89 @@ +/* + * 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.service.center.client; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; + +import com.google.common.eventbus.EventBus; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ServiceCenterAddressManagerTest { + + private static final List addresses = new ArrayList<>(); + + private static ServiceCenterAddressManager addressManager1; + + private static ServiceCenterAddressManager addressManager2; + + + @Test + public void getUrlPrefix() { + addresses.add("http://127.0.0.1:30103"); + addressManager1 = new ServiceCenterAddressManager("project", addresses, new EventBus(), "", ""); + + Assertions.assertNotNull(addressManager1); + + List addresses = addressManager1.getAddresses(); + Assertions.assertEquals(1, addresses.size()); + Assertions.assertEquals("http://127.0.0.1:30103", addresses.get(0)); + Assertions.assertEquals("http://127.0.0.1:30103", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103/v4/", addressManager1.getUrlPrefix("http://127.0.0.1:30103")); + } + + @Test + public void formatUrlTest() { + addresses.add("http://127.0.0.1:30103"); + addressManager1 = new ServiceCenterAddressManager("project", addresses, new EventBus(), "", ""); + Assertions.assertNotNull(addressManager1); + + String address = addressManager1.address(); + Assertions.assertEquals("http://127.0.0.1:30103", address); + String url = addressManager1.formatUrl("/test/", false, address); + Assertions.assertEquals("http://127.0.0.1:30103/v4/project/test/", url); + + url = addressManager1.formatUrl("/test/", true, address); + Assertions.assertEquals("http://127.0.0.1:30103/test/", url); + } + + @Test + public void onRefreshEndpointEvent() { + List addressAZ = new ArrayList<>(); + addressAZ.add("http://127.0.0.3:30100"); + List addressRG = new ArrayList<>(); + addressRG.add("http://127.0.0.4:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", addressRG); + addressManager1 = new ServiceCenterAddressManager("project", addresses, new EventBus(), "", ""); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "SERVICECENTER"); + addressManager1.refreshEndpoint(event, "SERVICECENTER"); + + List availableZone = addressManager1.getAvailableZone(); + Assertions.assertEquals("http://127.0.0.3:30100", availableZone.get(0)); + + List availableRegion = addressManager1.getAvailableRegion(); + Assertions.assertEquals("http://127.0.0.4:30100", availableRegion.get(0)); + } +} diff --git a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterClientTest.java b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterClientTest.java index 6b6791eee01..c486b2bd6ce 100755 --- a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterClientTest.java +++ b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterClientTest.java @@ -19,9 +19,12 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import org.apache.servicecomb.http.client.common.HttpResponse; +import org.apache.servicecomb.service.center.client.model.Framework; import org.apache.servicecomb.service.center.client.model.HeartbeatsRequest; import org.apache.servicecomb.service.center.client.model.InstancesRequest; import org.apache.servicecomb.service.center.client.model.Microservice; @@ -32,18 +35,26 @@ import org.apache.servicecomb.service.center.client.model.RegisteredMicroserviceInstanceResponse; import org.apache.servicecomb.service.center.client.model.RegisteredMicroserviceResponse; import org.apache.servicecomb.service.center.client.model.SchemaInfo; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.mockito.ArgumentMatchers; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; +import com.google.common.eventbus.EventBus; /** * Created by on 2019/10/17. */ public class ServiceCenterClientTest { + private final ServiceCenterAddressManager addressManager; + + public ServiceCenterClientTest() { + this.addressManager = new ServiceCenterAddressManager("default", Arrays.asList("http://127.0.0.1:30100"), + new EventBus(), "", ""); + } @Test public void TestGetServiceCenterInstances() throws IOException { @@ -90,13 +101,13 @@ public void TestGetServiceCenterInstances() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest("/registry/health", null, null)).thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); MicroserviceInstancesResponse serviceCenterInstances = serviceCenterClient.getServiceCenterInstances(); - Assert.assertNotNull(serviceCenterInstances); - Assert.assertEquals(1, serviceCenterInstances.getInstances().size()); - Assert.assertEquals("111111", serviceCenterInstances.getInstances().get(0).getInstanceId()); - Assert.assertEquals("222222", serviceCenterInstances.getInstances().get(0).getServiceId()); + Assertions.assertNotNull(serviceCenterInstances); + Assertions.assertEquals(1, serviceCenterInstances.getInstances().size()); + Assertions.assertEquals("111111", serviceCenterInstances.getInstances().get(0).getInstanceId()); + Assertions.assertEquals("222222", serviceCenterInstances.getInstances().get(0).getServiceId()); } @Test @@ -115,14 +126,15 @@ public void TestRegistryService() throws IOException { objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); Mockito.when(serviceCenterRawClient - .postHttpRequest("/registry/microservices", null, objectMapper.writeValueAsString(microservice))) + .postHttpRequest(ArgumentMatchers.eq("/registry/microservices"), ArgumentMatchers.eq(null), + Mockito.anyString())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); RegisteredMicroserviceResponse actualResponse = serviceCenterClient.registerMicroservice(microservice); - Assert.assertNotNull(actualResponse); - Assert.assertEquals("111111", actualResponse.getServiceId()); + Assertions.assertNotNull(actualResponse); + Assertions.assertEquals("111111", actualResponse.getServiceId()); } @Test @@ -176,11 +188,11 @@ public void TestGetServiceMessage() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest("/registry/microservices/111111", null, null)) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); Microservice microservices = serviceCenterClient.getMicroserviceByServiceId("111111"); - Assert.assertNotNull(microservices); - Assert.assertEquals("111111", microservices.getServiceId()); + Assertions.assertNotNull(microservices); + Assertions.assertEquals("111111", microservices.getServiceId()); } @Test @@ -193,7 +205,7 @@ public void TestGetServiceList() throws IOException { httpResponse.setMessage("ok"); MicroservicesResponse microservicesResponse = new MicroservicesResponse(); - List microserviceList = new ArrayList(); + List microserviceList = new ArrayList<>(); microserviceList.add(new Microservice("Test1")); microserviceList.add(new Microservice("Test2")); microserviceList.add(new Microservice("Test3")); @@ -204,12 +216,12 @@ public void TestGetServiceList() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); MicroservicesResponse actualMicroservicesResponse = serviceCenterClient.getMicroserviceList(); - Assert.assertNotNull(actualMicroservicesResponse); - Assert.assertEquals(3, actualMicroservicesResponse.getServices().size()); - Assert.assertEquals("Test1", actualMicroservicesResponse.getServices().get(0).getServiceName()); + Assertions.assertNotNull(actualMicroservicesResponse); + Assertions.assertEquals(3, actualMicroservicesResponse.getServices().size()); + Assertions.assertEquals("Test1", actualMicroservicesResponse.getServices().get(0).getServiceName()); } @Test @@ -225,12 +237,12 @@ public void TestQueryServiceId() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); Microservice microservice = new Microservice("Test111"); RegisteredMicroserviceResponse actualServiceId = serviceCenterClient.queryServiceId(microservice); - Assert.assertNotNull(actualServiceId); - Assert.assertEquals("111111", actualServiceId.getServiceId()); + Assertions.assertNotNull(actualServiceId); + Assertions.assertEquals("111111", actualServiceId.getServiceId()); } @Test @@ -249,15 +261,16 @@ public void TestRegisterServiceInstance() throws IOException { ObjectMapper mapper = new ObjectMapper(); mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true); - Mockito.when(serviceCenterRawClient.postHttpRequest("/registry/microservices/222222/instances", null, - mapper.writeValueAsString(instance))) + Mockito.when(serviceCenterRawClient.postHttpRequest(ArgumentMatchers.eq("/registry/microservices/222222/instances"), + ArgumentMatchers.eq(null), + Mockito.anyString())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); RegisteredMicroserviceInstanceResponse actualResponse = serviceCenterClient.registerMicroserviceInstance(instance); - Assert.assertNotNull(actualResponse); - Assert.assertEquals("111111", actualResponse.getInstanceId()); + Assertions.assertNotNull(actualResponse); + Assertions.assertEquals("111111", actualResponse.getInstanceId()); } @Test @@ -272,7 +285,7 @@ public void TestDeleteServiceInstance() throws IOException { Mockito.when(serviceCenterRawClient.deleteHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); serviceCenterClient.deleteMicroserviceInstance("111", "222"); } @@ -306,14 +319,14 @@ public void TestGetServiceInstanceList() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest("/registry/microservices/222222/instances", null, null)) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); MicroserviceInstancesResponse serviceCenterInstances = serviceCenterClient .getMicroserviceInstanceList("222222"); - Assert.assertNotNull(serviceCenterInstances); - Assert.assertEquals(1, serviceCenterInstances.getInstances().size()); - Assert.assertEquals("111111", serviceCenterInstances.getInstances().get(0).getInstanceId()); - Assert.assertEquals("222222", serviceCenterInstances.getInstances().get(0).getServiceId()); + Assertions.assertNotNull(serviceCenterInstances); + Assertions.assertEquals(1, serviceCenterInstances.getInstances().size()); + Assertions.assertEquals("111111", serviceCenterInstances.getInstances().get(0).getInstanceId()); + Assertions.assertEquals("222222", serviceCenterInstances.getInstances().get(0).getServiceId()); } @Test @@ -360,13 +373,13 @@ public void TestGetServiceInstanceMessage() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); MicroserviceInstance responseInstance = serviceCenterClient .getMicroserviceInstance("111", "222"); - Assert.assertNotNull(responseInstance); - Assert.assertEquals("111", responseInstance.getInstanceId()); - Assert.assertEquals("Test", responseInstance.getHostName()); + Assertions.assertNotNull(responseInstance); + Assertions.assertEquals("111", responseInstance.getInstanceId()); + Assertions.assertEquals("Test", responseInstance.getHostName()); } @Test @@ -386,10 +399,11 @@ public void TestSendHeartBeats() throws IOException { .when(serviceCenterRawClient.putHttpRequest("/registry/microservices/111/instances/222/heartbeat", null, null)) .thenReturn(httpResponse); Mockito.when(serviceCenterRawClient - .putHttpRequest("/registry/heartbeats", null, mapper.writeValueAsString(heartbeatsRequest))) + .putHttpRequest(ArgumentMatchers.eq("/registry/heartbeats"), ArgumentMatchers.eq(null), + Mockito.anyString())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); serviceCenterClient.sendHeartBeats(heartbeatsRequest); } @@ -405,12 +419,12 @@ public void TestUpdateServicesInstanceStatus() throws IOException { Mockito.when(serviceCenterRawClient.putHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); Boolean result = serviceCenterClient .updateMicroserviceInstanceStatus("111", "222", MicroserviceInstanceStatus.UP); - Assert.assertNotNull(result); - Assert.assertEquals(true, result); + Assertions.assertNotNull(result); + Assertions.assertEquals(true, result); } @Test @@ -435,16 +449,16 @@ public void TestGetServiceSchemas() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); List schemaResponse = serviceCenterClient .getServiceSchemasList("111", false); ObjectMapper mapper = new ObjectMapper(); JsonNode jsonNode = mapper.readTree(mapper.writeValueAsString(schemaResponse)); - Assert.assertNotNull(jsonNode); - Assert.assertEquals("111111", jsonNode.get(0).get("schemaId").textValue()); - Assert.assertEquals("test", jsonNode.get(0).get("schema").textValue()); + Assertions.assertNotNull(jsonNode); + Assertions.assertEquals("111111", jsonNode.get(0).get("schemaId").textValue()); + Assertions.assertEquals("test", jsonNode.get(0).get("schema").textValue()); } @Test @@ -463,12 +477,12 @@ public void TestGetServiceSchemasContext() throws IOException { Mockito.when(serviceCenterRawClient.getHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); String schemaContext = serviceCenterClient .getServiceSchemaContext("111", "222"); - Assert.assertNotNull(schemaContext); - Assert.assertEquals("test context", schemaContext); + Assertions.assertNotNull(schemaContext); + Assertions.assertEquals("test context", schemaContext); } @Test @@ -483,11 +497,28 @@ public void TestUpdateServiceSchema() throws IOException { Mockito.when(serviceCenterRawClient.putHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) .thenReturn(httpResponse); - ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient); + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); boolean result = serviceCenterClient .updateServiceSchemaContext("111", new SchemaInfo()); - Assert.assertNotNull(result); - Assert.assertEquals(true, result); + Assertions.assertTrue(result); + } + + @Test + public void testUpdateMicroserviceProperties() throws IOException { + ServiceCenterRawClient serviceCenterRawClient = Mockito.mock(ServiceCenterRawClient.class); + + HttpResponse httpResponse = new HttpResponse(); + httpResponse.setStatusCode(200); + httpResponse.setMessage("ok"); + + Mockito.when(serviceCenterRawClient.putHttpRequest(Mockito.any(), Mockito.any(), Mockito.any())) + .thenReturn(httpResponse); + + ServiceCenterClient serviceCenterClient = new ServiceCenterClient(serviceCenterRawClient, addressManager); + boolean result = serviceCenterClient + .updateMicroserviceProperties("111", new HashMap(), new Framework()); + + Assertions.assertTrue(result); } } diff --git a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java index f7a3f7b74a1..48f3bd914c6 100755 --- a/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java +++ b/clients/service-center-client/src/test/java/org/apache/servicecomb/service/center/client/ServiceCenterRawClientTest.java @@ -22,19 +22,17 @@ import org.apache.servicecomb.http.client.common.HttpResponse; import org.apache.servicecomb.http.client.common.HttpTransport; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import com.google.common.eventbus.EventBus; + /** * Created by on 2019/10/16. */ public class ServiceCenterRawClientTest { - private static final String DEFAULT_HOST = "localhost"; - - private static final int DEFAULT_PORT = 30100; - private static final String PROJECT_NAME = "default"; private static final String TENANT_NAME = "default"; @@ -43,8 +41,8 @@ public class ServiceCenterRawClientTest { public void TestDefaultParameter() throws IOException { HttpTransport httpTransport = Mockito.mock(HttpTransport.class); - - AddressManager addressManager = new AddressManager(PROJECT_NAME, Arrays.asList("http://127.0.0.1:30100")); + ServiceCenterAddressManager addressManager = new ServiceCenterAddressManager(PROJECT_NAME, + Arrays.asList("http://127.0.0.1:30100"), new EventBus(), "", ""); ServiceCenterRawClient client = new ServiceCenterRawClient.Builder() .setHttpTransport(httpTransport) .setAddressManager(addressManager) @@ -62,13 +60,13 @@ public void TestDefaultParameter() throws IOException { HttpResponse actualPutResponse = client.putHttpRequest(null, null, null); HttpResponse actualDeleteResponse = client.putHttpRequest(null, null, null); - Assert.assertNotNull(actualGetResponse); - Assert.assertEquals("ok", actualGetResponse.getContent()); - Assert.assertNotNull(actualPostResponse); - Assert.assertEquals("ok", actualPostResponse.getContent()); - Assert.assertNotNull(actualPutResponse); - Assert.assertEquals("ok", actualPutResponse.getContent()); - Assert.assertNotNull(actualDeleteResponse); - Assert.assertEquals("ok", actualDeleteResponse.getContent()); + Assertions.assertNotNull(actualGetResponse); + Assertions.assertEquals("ok", actualGetResponse.getContent()); + Assertions.assertNotNull(actualPostResponse); + Assertions.assertEquals("ok", actualPostResponse.getContent()); + Assertions.assertNotNull(actualPutResponse); + Assertions.assertEquals("ok", actualPutResponse.getContent()); + Assertions.assertNotNull(actualDeleteResponse); + Assertions.assertEquals("ok", actualDeleteResponse.getContent()); } } diff --git a/common/common-access-log/pom.xml b/common/common-access-log/pom.xml index 1fd97f59bcf..e572e6bfd94 100644 --- a/common/common-access-log/pom.xml +++ b/common/common-access-log/pom.xml @@ -21,7 +21,7 @@ common org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -41,5 +41,14 @@ org.apache.servicecomb common-rest + + org.apache.servicecomb + transport-rest-client + + + io.vertx + vertx-codegen + test + - \ No newline at end of file + diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootListener.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootListener.java index e84724c049a..54becedcbf0 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootListener.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootListener.java @@ -22,7 +22,7 @@ public class AccessLogBootListener implements BootListener { - private AccessLogBootstrap accessLogBootstrap = new AccessLogBootstrap(); + private final AccessLogBootstrap accessLogBootstrap = new AccessLogBootstrap(); @Override public void onAfterRegistry(BootEvent event) { diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootstrap.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootstrap.java index e46542e3a24..56cc12ef0e0 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootstrap.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogBootstrap.java @@ -22,12 +22,9 @@ import com.google.common.eventbus.EventBus; public class AccessLogBootstrap { - private static AccessLogConfig config = AccessLogConfig.INSTANCE; - - private EventBus eventBus; + private static final AccessLogConfig config = AccessLogConfig.INSTANCE; public void start(EventBus eventBus) { - this.eventBus = eventBus; SPIServiceUtils.getSortedService(AccessLogInitializer.class) .forEach(initializer -> initializer.init(eventBus, config)); } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfig.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfig.java index ce2dc58856e..e2f204b3cad 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfig.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfig.java @@ -17,64 +17,60 @@ package org.apache.servicecomb.common.accessLog; -import com.netflix.config.DynamicPropertyFactory; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; public class AccessLogConfig { - private static final String SERVER_BASE = "servicecomb.accesslog."; + public static final String SERVER_BASE = "servicecomb.accesslog."; - private static final String CLIENT_BASE = "servicecomb.accesslog.request."; + public static final String CLIENT_BASE = "servicecomb.accesslog.request."; - private static final String SERVER_LOG_ENABLED = SERVER_BASE + "enabled"; + public static final String SERVER_LOG_ENABLED = SERVER_BASE + "enabled"; - private static final String SERVER_LOG_PATTERN = SERVER_BASE + "pattern"; + public static final String SERVER_LOG_PATTERN = SERVER_BASE + "pattern"; - private static final String CLIENT_LOG_ENABLED = CLIENT_BASE + "enabled"; + public static final String CLIENT_LOG_ENABLED = CLIENT_BASE + "enabled"; - private static final String CLIENT_LOG_PATTERN = CLIENT_BASE + "pattern"; + public static final String CLIENT_LOG_PATTERN = CLIENT_BASE + "pattern"; - private static final String DEFAULT_SERVER_PATTERN = "%h - - %t %r %s %B %D"; + public static final String DEFAULT_SERVER_PATTERN = "%h - - %t %r %s %B %D"; - private static final String DEFAULT_CLIENT_PATTERN = "%h %SCB-transport - - %t %r %s %D"; + public static final String DEFAULT_CLIENT_PATTERN = "%h %SCB-transport - - %t %r %s %D"; - public static final AccessLogConfig INSTANCE = new AccessLogConfig(); + public static final AccessLogConfig INSTANCE = new AccessLogConfig(); - private boolean serverLogEnabled; + private boolean serverLogEnabled; - private boolean clientLogEnabled; + private boolean clientLogEnabled; - private String serverLogPattern; + private String serverLogPattern; - private String clientLogPattern; + private String clientLogPattern; - private AccessLogConfig() { - init(); - } + private AccessLogConfig() { + init(); + } - private void init() { - clientLogEnabled = DynamicPropertyFactory - .getInstance().getBooleanProperty(CLIENT_LOG_ENABLED, false).get(); - serverLogEnabled = DynamicPropertyFactory - .getInstance().getBooleanProperty(SERVER_LOG_ENABLED, false).get(); - clientLogPattern = DynamicPropertyFactory - .getInstance().getStringProperty(CLIENT_LOG_PATTERN, DEFAULT_CLIENT_PATTERN).get(); - serverLogPattern = DynamicPropertyFactory - .getInstance().getStringProperty(SERVER_LOG_PATTERN, DEFAULT_SERVER_PATTERN).get(); - } + private void init() { + clientLogEnabled = LegacyPropertyFactory.getBooleanProperty(CLIENT_LOG_ENABLED, false); + serverLogEnabled = LegacyPropertyFactory.getBooleanProperty(SERVER_LOG_ENABLED, false); + clientLogPattern = LegacyPropertyFactory.getStringProperty(CLIENT_LOG_PATTERN, DEFAULT_CLIENT_PATTERN); + serverLogPattern = LegacyPropertyFactory.getStringProperty(SERVER_LOG_PATTERN, DEFAULT_SERVER_PATTERN); + } - public boolean isServerLogEnabled() { - return serverLogEnabled; - } + public boolean isServerLogEnabled() { + return serverLogEnabled; + } - public boolean isClientLogEnabled() { - return clientLogEnabled; - } + public boolean isClientLogEnabled() { + return clientLogEnabled; + } - public String getServerLogPattern() { - return serverLogPattern; - } + public String getServerLogPattern() { + return serverLogPattern; + } - public String getClientLogPattern() { - return clientLogPattern; - } + public String getClientLogPattern() { + return clientLogPattern; + } } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfiguration.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfiguration.java new file mode 100644 index 00000000000..abbb90adc19 --- /dev/null +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/AccessLogConfiguration.java @@ -0,0 +1,28 @@ +/* + * 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.common.accessLog; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AccessLogConfiguration { + @Bean + public AccessLogBootListener scbAccessLogBootListener() { + return new AccessLogBootListener(); + } +} diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/client/ClientDefaultInitializer.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/client/ClientDefaultInitializer.java index 0f419a1ba4e..43e5ad9b191 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/client/ClientDefaultInitializer.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/client/ClientDefaultInitializer.java @@ -21,7 +21,6 @@ import org.apache.servicecomb.common.accessLog.AccessLogInitializer; import org.apache.servicecomb.common.accessLog.core.AccessLogGenerator; import org.apache.servicecomb.core.event.InvocationFinishEvent; - import org.apache.servicecomb.swagger.invocation.InvocationType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,7 +30,7 @@ import com.google.common.eventbus.Subscribe; public class ClientDefaultInitializer implements AccessLogInitializer { - private static Logger LOGGER = LoggerFactory.getLogger("requestlog"); + private static final Logger LOGGER = LoggerFactory.getLogger("scb-access"); private AccessLogGenerator accessLogGenerator; @@ -48,7 +47,7 @@ public void init(EventBus eventBus, AccessLogConfig accessLogConfig) { @AllowConcurrentEvents public void onRequestOut(InvocationFinishEvent finishEvent) { if (InvocationType.CONSUMER.equals(finishEvent.getInvocation().getInvocationType())) { - LOGGER.info(accessLogGenerator.generateClientLog(finishEvent)); + LOGGER.info(accessLogGenerator.generateClientLog(finishEvent)); } } } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/AccessLogGenerator.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/AccessLogGenerator.java index cd462095342..d67247d9257 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/AccessLogGenerator.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/AccessLogGenerator.java @@ -19,6 +19,7 @@ import java.util.List; +import com.google.common.annotations.VisibleForTesting; import org.apache.servicecomb.common.accessLog.core.element.AccessLogItem; import org.apache.servicecomb.common.accessLog.core.parser.AccessLogPatternParser; import org.apache.servicecomb.common.accessLog.core.parser.impl.VertxRestAccessLogPatternParser; @@ -38,9 +39,9 @@ public class AccessLogGenerator { /* * traversal this array to generate access log segment. */ - private AccessLogItem[] accessLogItems; + private final AccessLogItem[] accessLogItems; - private AccessLogPatternParser logPatternParser = new VertxRestAccessLogPatternParser(); + private final AccessLogPatternParser logPatternParser = new VertxRestAccessLogPatternParser(); @SuppressWarnings("unchecked") public AccessLogGenerator(String rawPattern) { @@ -64,7 +65,8 @@ public String generateClientLog(InvocationFinishEvent finishEvent) { return log.toString(); } - private AccessLogItem[] getAccessLogItems() { + @VisibleForTesting + AccessLogItem[] getAccessLogItems() { return accessLogItems; } } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/ConfigurableDatetimeAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/ConfigurableDatetimeAccessItem.java index c522927dd1f..9c759ca2cb5 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/ConfigurableDatetimeAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/ConfigurableDatetimeAccessItem.java @@ -22,10 +22,10 @@ import java.util.Locale; import java.util.TimeZone; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.common.accessLog.core.element.AccessLogItem; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.springframework.util.StringUtils; import io.vertx.ext.web.RoutingContext; @@ -58,7 +58,7 @@ public ConfigurableDatetimeAccessItem() { * @param config the format of configuration is "PATTERN|TIMEZONE|LOCALE" or "PATTERN". It depends on whether the config contains the separator "|" */ public ConfigurableDatetimeAccessItem(String config) { - String[] configArr = null; + String[] configArr; if (config.contains("|")) { configArr = splitConfig(config); } else { @@ -71,14 +71,14 @@ public ConfigurableDatetimeAccessItem(String config) { "wrong format of configuration, \"PATTERN|TIMEZONE|LOCALE\" is expected, but actually is \"" + config + "\""); } - setConfigruations(configArr); + setConfigurations(configArr); } private String[] splitConfig(String config) { return config.split("\\|{1}?", -1); } - private void setConfigruations(String[] configArr) { + private void setConfigurations(String[] configArr) { this.pattern = StringUtils.isEmpty(configArr[0]) ? DEFAULT_DATETIME_PATTERN : configArr[0]; this.timezone = StringUtils.isEmpty(configArr[1]) ? TimeZone.getDefault() : TimeZone.getTimeZone(configArr[1]); this.locale = StringUtils.isEmpty(configArr[2]) ? DEFAULT_LOCALE : Locale.forLanguageTag(configArr[2]); @@ -91,10 +91,9 @@ public void appendServerFormattedItem(ServerAccessLogEvent accessLogEvent, Strin @Override public void appendClientFormattedItem(InvocationFinishEvent finishEvent, StringBuilder builder) { - long milliDuration = (finishEvent.getInvocation().getInvocationStageTrace().getStartSend() - - finishEvent.getInvocation().getInvocationStageTrace().getStart()) / 1000_000; + long milliDuration = finishEvent.getInvocation().getInvocationStageTrace().calcTotal() / 1000_000; doAppendFormattedItem( - finishEvent.getInvocation().getInvocationStageTrace().getStartTimeMillis() + milliDuration, builder); + finishEvent.getInvocation().getInvocationStageTrace().getStartInMillis() + milliDuration, builder); } private void doAppendFormattedItem(long milliStartTime, StringBuilder builder) { diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieAccessItem.java index 01b32188b52..e15179acc69 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieAccessItem.java @@ -17,14 +17,14 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.apache.servicecomb.common.accessLog.core.element.AccessLogItem; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; import io.vertx.core.http.Cookie; import io.vertx.ext.web.RoutingContext; @@ -41,12 +41,12 @@ public CookieAccessItem(String varName) { @Override public void appendServerFormattedItem(ServerAccessLogEvent accessLogEvent, StringBuilder builder) { - Map cookieMap = accessLogEvent.getRoutingContext().cookieMap(); - if (null == cookieMap) { + Set cookies = accessLogEvent.getRoutingContext().request().cookies(); + if (null == cookies) { builder.append(RESULT_NOT_FOUND); return; } - for (Cookie cookie : cookieMap.values()) { + for (Cookie cookie : cookies) { if (varName.equals(cookie.getName())) { builder.append(cookie.getValue()); return; @@ -57,8 +57,8 @@ public void appendServerFormattedItem(ServerAccessLogEvent accessLogEvent, Strin @Override public void appendClientFormattedItem(InvocationFinishEvent finishEvent, StringBuilder builder) { - RestClientRequestImpl restRequestImpl = (RestClientRequestImpl) finishEvent.getInvocation().getHandlerContext() - .get(RestConst.INVOCATION_HANDLER_REQUESTCLIENT); + RestClientRequestParameters restRequestImpl = (RestClientRequestParameters) finishEvent.getInvocation().getHandlerContext() + .get(RestConst.INVOCATION_HANDLER_REQUESTCLIENT); if (null == restRequestImpl || null == restRequestImpl.getCookieMap()) { builder.append(RESULT_NOT_FOUND); return; diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondAccessItem.java index e0bde4ad306..49ecda73d94 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondAccessItem.java @@ -31,7 +31,6 @@ public void appendServerFormattedItem(ServerAccessLogEvent accessLogEvent, Strin @Override public void appendClientFormattedItem(InvocationFinishEvent finishEvent, StringBuilder builder) { - builder.append((finishEvent.getInvocation().getInvocationStageTrace().getFinish() - - finishEvent.getInvocation().getInvocationStageTrace().getStartSend()) / 1000_000); + builder.append(finishEvent.getInvocation().getInvocationStageTrace().calcTotal() / 1000_000); } } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondAccessItem.java index 2da34026d5e..68d2ba0d411 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondAccessItem.java @@ -33,7 +33,6 @@ public void appendServerFormattedItem(ServerAccessLogEvent accessLogEvent, Strin @Override public void appendClientFormattedItem(InvocationFinishEvent finishEvent, StringBuilder builder) { - builder.append((finishEvent.getInvocation().getInvocationStageTrace().getFinish() - - finishEvent.getInvocation().getInvocationStageTrace().getStartSend()) / 1000_000_000); + builder.append(finishEvent.getInvocation().getInvocationStageTrace().calcTotal() / 1000_000_000); } } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodAccessItem.java index 8a59112b89a..8c8b61583e3 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodAccessItem.java @@ -21,7 +21,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.common.accessLog.core.element.AccessLogItem; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; +import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; @@ -53,13 +53,13 @@ public void appendClientFormattedItem(InvocationFinishEvent finishEvent, StringB builder.append(operationMeta.getHttpMethod()); return; } - RestClientRequestImpl restRequestImpl = (RestClientRequestImpl) finishEvent.getInvocation().getHandlerContext() + RestClientRequest restRequestImpl = (RestClientRequest) finishEvent.getInvocation().getHandlerContext() .get(RestConst.INVOCATION_HANDLER_REQUESTCLIENT); - if (null == restRequestImpl || null == restRequestImpl.getRequest() - || null == restRequestImpl.getRequest().getMethod()) { + if (null == restRequestImpl || null == restRequestImpl.getHttpClientRequest() + || null == restRequestImpl.getHttpClientRequest().getMethod()) { builder.append(EMPTY_RESULT); return; } - builder.append(restRequestImpl.getRequest().getMethod().toString()); + builder.append(restRequestImpl.getHttpClientRequest().getMethod().toString()); } } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusAccessItem.java index 3f9e657ce68..61be5a790a6 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusAccessItem.java @@ -21,15 +21,11 @@ import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.RoutingContext; public class HttpStatusAccessItem implements AccessLogItem { - private static Logger LOGGER = LoggerFactory.getLogger(HttpStatusAccessItem.class); - public static final String EMPTY_RESULT = "-"; @Override @@ -40,9 +36,6 @@ public void appendServerFormattedItem(ServerAccessLogEvent accessLogEvent, Strin return; } if (response.closed() && !response.ended()) { - LOGGER.warn( - "Response is closed before sending any data. " - + "Please check idle connection timeout for provider is properly configured."); builder.append(EMPTY_RESULT); return; } diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextAccessItem.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextAccessItem.java index b357bb34285..d3a206aa803 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextAccessItem.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextAccessItem.java @@ -19,12 +19,13 @@ import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.common.accessLog.core.element.AccessLogItem; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.springframework.util.StringUtils; + import io.vertx.ext.web.RoutingContext; @@ -32,7 +33,7 @@ public class InvocationContextAccessItem implements AccessLogItem metaList = new ArrayList<>(); + private final List metaList = new ArrayList<>(); public VertxRestAccessLogPatternParser() { List loadedMeta = loadVertxRestLogItemMeta(); @@ -78,7 +80,13 @@ public VertxRestAccessLogPatternParser() { sortAccessLogItemMeta(this.metaList); } - private List loadVertxRestLogItemMeta() { + @VisibleForTesting + List getMetaList() { + return metaList; + } + + @VisibleForTesting + List loadVertxRestLogItemMeta() { return SPIServiceUtils.getOrLoadSortedService(VertxRestAccessLogItemMeta.class); } @@ -166,7 +174,6 @@ private List matchAccessLogItem(String rawPattern) { AccessLogItemLocation candidate = null; for (VertxRestAccessLogItemMeta meta : metaList) { if (null != candidate && null == meta.getSuffix()) { - // TODO: // if user define item("%{","}ab") and item("%{_","}abc") and the pattern is "%{_var}ab}abc" // currently the result is item("%{","_var","}ab"), plaintext("}abc") // is this acceptable? @@ -289,17 +296,17 @@ private static class AccessLogItemLocation { /** * prefixIndex = rawPattern.indexOf(prefix) */ - int prefixIndex; + final int prefixIndex; /** * suffixIndex = rawPattern.indexOf(suffix) */ - int suffixIndex; + final int suffixIndex; /** * tail = suffixIndex + suffix.length() */ - int tail; + final int tail; VertxRestAccessLogItemMeta accessLogItemMeta; diff --git a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/server/ServerDefaultInitializer.java b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/server/ServerDefaultInitializer.java index 9b10ac46381..7baf69dd8aa 100644 --- a/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/server/ServerDefaultInitializer.java +++ b/common/common-access-log/src/main/java/org/apache/servicecomb/common/accessLog/server/ServerDefaultInitializer.java @@ -31,7 +31,7 @@ public class ServerDefaultInitializer implements AccessLogInitializer { - private static Logger LOGGER = LoggerFactory.getLogger("accesslog"); + private static final Logger LOGGER = LoggerFactory.getLogger("scb-access"); private AccessLogGenerator accessLogGenerator; diff --git a/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta b/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta index 78f937b61fe..f793ca0f575 100644 --- a/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta +++ b/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.common.accessLog.core.parser.impl.DefaultCompositeVertxRestAccessLogItemMeta \ No newline at end of file +org.apache.servicecomb.common.accessLog.core.parser.impl.DefaultCompositeVertxRestAccessLogItemMeta diff --git a/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener b/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener deleted file mode 100644 index 7ab357ee11c..00000000000 --- a/common/common-access-log/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.common.accessLog.AccessLogBootListener \ No newline at end of file diff --git a/common/common-access-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/common/common-access-log/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..e6814e63814 --- /dev/null +++ b/common/common-access-log/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.servicecomb.common.accessLog.AccessLogConfiguration diff --git a/common/common-access-log/src/main/resources/config/base/log4j.properties b/common/common-access-log/src/main/resources/config/base/log4j.properties deleted file mode 100644 index 01fed5bffb6..00000000000 --- a/common/common-access-log/src/main/resources/config/base/log4j.properties +++ /dev/null @@ -1,43 +0,0 @@ -# -# 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. -# - -# access log default configuration -paas.logs.accesslog.dir=${paas.logs.dir} -paas.logs.requestlog.dir=${paas.logs.dir} - -paas.logs.accesslog.file=access.log -paas.logs.requestlog.file=request.log -#request log File appender -log4j.logger.requestlog=INFO,request -log4j.appender.request=org.apache.servicecomb.foundation.common.utils.RollingFileAppenderExt -log4j.appender.request.MaxBackupIndex=10 -log4j.appender.request.MaxFileSize=20MB -log4j.appender.request.file=${paas.logs.requestlog.dir}${paas.logs.requestlog.file} -log4j.appender.request.layout=org.apache.log4j.PatternLayout -log4j.appender.request.layout.ConversionPattern=%m%n -log4j.appender.request.logPermission=rw------- -log4j.additivity.requestlog=false -# access log File appender -log4j.logger.accesslog=INFO,access -log4j.appender.access=org.apache.servicecomb.foundation.common.utils.RollingFileAppenderExt -log4j.appender.access.MaxBackupIndex=10 -log4j.appender.access.MaxFileSize=20MB -log4j.appender.access.file=${paas.logs.accesslog.dir}${paas.logs.accesslog.file} -log4j.appender.access.layout=org.apache.log4j.PatternLayout -log4j.appender.access.layout.ConversionPattern=%m%n -log4j.appender.access.logPermission=rw------- -log4j.additivity.accesslog=false diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogConfigTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogConfigTest.java deleted file mode 100644 index 245b9393f11..00000000000 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogConfigTest.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.common.accessLog.core; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; - -import org.apache.servicecomb.common.accessLog.AccessLogConfig; -import org.junit.Test; - -public class AccessLogConfigTest { - - @Test - public void getAccessLogEnabled() { - boolean serverEnabled = AccessLogConfig.INSTANCE.isServerLogEnabled(); - boolean clientEnabled = AccessLogConfig.INSTANCE.isClientLogEnabled(); - assertFalse(serverEnabled); - assertFalse(clientEnabled); - } - - @Test - public void getAccesslogPattern() { - String clientLogPattern = AccessLogConfig.INSTANCE.getClientLogPattern(); - String serverLogPattern = AccessLogConfig.INSTANCE.getServerLogPattern(); - - assertEquals("%h - - %t %r %s %B %D", serverLogPattern); - assertEquals("%h %SCB-transport - - %t %r %s %D", clientLogPattern); - } -} diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogGeneratorTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogGeneratorTest.java index bd0e880de8d..e8c7cf38500 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogGeneratorTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/AccessLogGeneratorTest.java @@ -17,7 +17,6 @@ package org.apache.servicecomb.common.accessLog.core; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.text.SimpleDateFormat; @@ -34,14 +33,13 @@ import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.core.invocation.InvocationStageTrace; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.HttpServerRequest; import io.vertx.ext.web.RoutingContext; -import mockit.Deencapsulation; public class AccessLogGeneratorTest { @@ -52,11 +50,11 @@ public class AccessLogGeneratorTest { @Test public void testConstructor() { - AccessLogItem[] elements = Deencapsulation.getField(LOG_GENERATOR, "accessLogItems"); - assertEquals(3, elements.length); - assertEquals(HttpMethodAccessItem.class, elements[0].getClass()); - assertEquals(PlainTextAccessItem.class, elements[1].getClass()); - assertEquals(ConfigurableDatetimeAccessItem.class, elements[2].getClass()); + AccessLogItem[] elements = LOG_GENERATOR.getAccessLogItems(); + Assertions.assertEquals(3, elements.length); + Assertions.assertEquals(HttpMethodAccessItem.class, elements[0].getClass()); + Assertions.assertEquals(PlainTextAccessItem.class, elements[1].getClass()); + Assertions.assertEquals(ConfigurableDatetimeAccessItem.class, elements[2].getClass()); } @Test @@ -74,7 +72,7 @@ public void testServerLog() { when(request.method()).thenReturn(HttpMethod.DELETE); String log = LOG_GENERATOR.generateServerLog(serverAccessLogEvent); - Assert.assertEquals("DELETE" + " - " + simpleDateFormat.format(startMillisecond), log); + Assertions.assertEquals("DELETE" + " - " + simpleDateFormat.format(startMillisecond), log); } @Test @@ -83,10 +81,8 @@ public void testClientLog() { InvocationStageTrace stageTrace = Mockito.mock(InvocationStageTrace.class); OperationMeta operationMeta = Mockito.mock(OperationMeta.class); long startMillisecond = 1416863450581L; - when(stageTrace.getStartSend()).thenReturn(0L); - when(stageTrace.getStart()).thenReturn(0L); - when(stageTrace.getFinish()).thenReturn(0L); - when(stageTrace.getStartTimeMillis()).thenReturn(startMillisecond); + when(stageTrace.getStartInMillis()).thenReturn(startMillisecond); + when(stageTrace.calcTotal()).thenReturn(0L); when(invocation.getOperationMeta()).thenReturn(operationMeta); when(invocation.getInvocationStageTrace()).thenReturn(stageTrace); @@ -96,15 +92,15 @@ public void testClientLog() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); when(operationMeta.getHttpMethod()).thenReturn(HttpMethod.DELETE.toString()); String log = LOG_GENERATOR.generateClientLog(finishEvent); - Assert.assertEquals("DELETE" + " - " + simpleDateFormat.format(startMillisecond), log); + Assertions.assertEquals("DELETE" + " - " + simpleDateFormat.format(startMillisecond), log); } @Test public void testUserDefinedLogGenerator() { - AccessLogItem[] elements = Deencapsulation.getField(USER_DEFINED_LOG_GENERATOR, "accessLogItems"); - assertEquals(3, elements.length); - assertEquals(RemoteHostAccessItem.class, elements[0].getClass()); - assertEquals(PlainTextAccessItem.class, elements[1].getClass()); - assertEquals(UserDefinedAccessLogItem.class, elements[2].getClass()); + AccessLogItem[] elements = USER_DEFINED_LOG_GENERATOR.getAccessLogItems(); + Assertions.assertEquals(3, elements.length); + Assertions.assertEquals(RemoteHostAccessItem.class, elements[0].getClass()); + Assertions.assertEquals(PlainTextAccessItem.class, elements[1].getClass()); + Assertions.assertEquals(UserDefinedAccessLogItem.class, elements[2].getClass()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieItemTest.java index 7c4ad16585f..f1d37e9681f 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/CookieItemTest.java @@ -20,19 +20,21 @@ import static org.mockito.Mockito.when; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.Cookie; +import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.impl.CookieImpl; import io.vertx.ext.web.RoutingContext; @@ -52,16 +54,19 @@ public class CookieItemTest { private RoutingContext mockContext; + private HttpServerRequest httpServerRequest; + private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; - @Before + @BeforeEach public void initStrBuilder() { mockContext = Mockito.mock(RoutingContext.class); + httpServerRequest = Mockito.mock(HttpServerRequest.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); accessLogEvent = new ServerAccessLogEvent(); strBuilder = new StringBuilder(); @@ -69,16 +74,16 @@ public void initStrBuilder() { @Test public void serverFormattedElement() { - HashMap cookieSet = new HashMap<>(); + HashSet cookieSet = new HashSet<>(); CookieImpl cookie = new CookieImpl(COOKIE_NAME, COOKIE_VALUE); - cookieSet.put(cookie.getName(), cookie); - when(mockContext.cookieCount()).thenReturn(1); - when(mockContext.cookieMap()).thenReturn(cookieSet); + cookieSet.add(cookie); + Mockito.when(mockContext.request()).thenReturn(httpServerRequest); + Mockito.when(httpServerRequest.cookies()).thenReturn(cookieSet); accessLogEvent.setRoutingContext(mockContext); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals(COOKIE_VALUE, strBuilder.toString()); + Assertions.assertEquals(COOKIE_VALUE, strBuilder.toString()); } @Test @@ -94,18 +99,18 @@ public void clientFormattedElement() { when(restClientRequest.getCookieMap()).thenReturn(cookieMap); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals(COOKIE_VALUE, strBuilder.toString()); + Assertions.assertEquals(COOKIE_VALUE, strBuilder.toString()); } @Test public void serverFormattedElementOnCookieCountIsZero() { - HashMap cookieSet = new HashMap<>(); - Mockito.when(mockContext.cookieCount()).thenReturn(0); - Mockito.when(mockContext.cookieMap()).thenReturn(cookieSet); + HashSet cookieSet = new HashSet<>(); + Mockito.when(mockContext.request()).thenReturn(httpServerRequest); + Mockito.when(httpServerRequest.cookies()).thenReturn(cookieSet); accessLogEvent.setRoutingContext(mockContext); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -119,18 +124,18 @@ public void clientFormattedElementOnCookieCountIsZero() { when(restClientRequest.getCookieMap()).thenReturn(cookieMap); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void serverFormattedElementOnCookieSetIsNull() { - Mockito.when(mockContext.cookieCount()).thenReturn(1); - Mockito.when(mockContext.cookieMap()).thenReturn(null); + Mockito.when(mockContext.request()).thenReturn(httpServerRequest); + Mockito.when(httpServerRequest.cookies()).thenReturn(null); accessLogEvent.setRoutingContext(mockContext); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -143,21 +148,21 @@ public void clientFormattedElementOnCookieSetIsNull() { when(restClientRequest.getCookieMap()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void serverFormattedElementOnNotFound() { - HashMap cookieSet = new HashMap<>(); + HashSet cookieSet = new HashSet<>(); CookieImpl cookie = new CookieImpl("anotherCookieName", COOKIE_VALUE); - cookieSet.put(cookie.getName(), cookie); - Mockito.when(mockContext.cookieCount()).thenReturn(1); - Mockito.when(mockContext.cookieMap()).thenReturn(cookieSet); + cookieSet.add(cookie); + Mockito.when(mockContext.request()).thenReturn(httpServerRequest); + Mockito.when(httpServerRequest.cookies()).thenReturn(cookieSet); accessLogEvent.setRoutingContext(mockContext); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -172,6 +177,6 @@ public void clientFormattedElementOnNotFound() { when(restClientRequest.getCookieMap()).thenReturn(cookieMap); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DatetimeConfigurableItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DatetimeConfigurableItemTest.java index c46e803a11e..8f55eb0006c 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DatetimeConfigurableItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DatetimeConfigurableItemTest.java @@ -17,7 +17,6 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.text.SimpleDateFormat; @@ -28,8 +27,9 @@ import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.core.invocation.InvocationStageTrace; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class DatetimeConfigurableItemTest { @@ -46,7 +46,7 @@ public class DatetimeConfigurableItemTest { private InvocationStageTrace invocationStageTrace; - @Before + @BeforeEach public void initStrBuilder() { finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); @@ -54,48 +54,14 @@ public void initStrBuilder() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getInvocationStageTrace()).thenReturn(invocationStageTrace); - when(invocationStageTrace.getStartSend()).thenReturn(0L); - when(invocationStageTrace.getStart()).thenReturn(0L); - when(invocationStageTrace.getStartTimeMillis()).thenReturn(START_MILLISECOND); + when(invocationStageTrace.getStartInMillis()).thenReturn(START_MILLISECOND); + when(invocationStageTrace.calcTotal()).thenReturn(0L); accessLogEvent = new ServerAccessLogEvent(); accessLogEvent.setMilliStartTime(START_MILLISECOND); strBuilder = new StringBuilder(); } - @Test - public void serverFormattedElement() { - ConfigurableDatetimeAccessItem element = new ConfigurableDatetimeAccessItem( - "EEE, yyyy MMM dd HH:mm:ss zzz|GMT-08|zh-CN"); - element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("星期一, 2014 十一月 24 13:10:50 GMT-08:00", strBuilder.toString()); - } - - @Test - public void clientFormattedElement() { - ConfigurableDatetimeAccessItem element = new ConfigurableDatetimeAccessItem( - "EEE, yyyy MMM dd HH:mm:ss zzz|GMT-08|zh-CN"); - element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("星期一, 2014 十一月 24 13:10:50 GMT-08:00", strBuilder.toString()); - } - - @Test - public void serverFormattedElementOnNoPattern() { - ConfigurableDatetimeAccessItem element = new ConfigurableDatetimeAccessItem( - "|GMT+08|zh-CN"); - - element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("星期二, 25 十一月 2014 05:10:50 GMT+08:00", strBuilder.toString()); - } - - @Test - public void clientFormattedElementOnNoPattern() { - ConfigurableDatetimeAccessItem element = new ConfigurableDatetimeAccessItem( - "|GMT+08|zh-CN"); - - element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("星期二, 25 十一月 2014 05:10:50 GMT+08:00", strBuilder.toString()); - } @Test public void getFormattedElementOnNoTimezone() { @@ -105,7 +71,7 @@ public void getFormattedElementOnNoTimezone() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -116,7 +82,7 @@ public void clientFormattedElementOnNoTimezone() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -125,7 +91,7 @@ public void serverFormattedElementOnNoLocale() { "EEE, dd MMM yyyy HH:mm:ss zzz|GMT+08|"); element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("Tue, 25 Nov 2014 05:10:50 GMT+08:00", strBuilder.toString()); + Assertions.assertEquals("Tue, 25 Nov 2014 05:10:50 GMT+08:00", strBuilder.toString()); } @Test @@ -134,7 +100,7 @@ public void clientFormattedElementOnNoLocale() { "EEE, dd MMM yyyy HH:mm:ss zzz|GMT+08|"); element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("Tue, 25 Nov 2014 05:10:50 GMT+08:00", strBuilder.toString()); + Assertions.assertEquals("Tue, 25 Nov 2014 05:10:50 GMT+08:00", strBuilder.toString()); } @Test @@ -146,7 +112,7 @@ public void serverFormattedElementOnNoConfig() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -158,7 +124,7 @@ public void clientFormattedElementOnNoConfig() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -168,10 +134,10 @@ public void serverConstructorWithNoArg() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("EEE, dd MMM yyyy HH:mm:ss zzz", element.getPattern()); - assertEquals(Locale.US, element.getLocale()); - assertEquals(TimeZone.getDefault(), element.getTimezone()); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals("EEE, dd MMM yyyy HH:mm:ss zzz", element.getPattern()); + Assertions.assertEquals(Locale.US, element.getLocale()); + Assertions.assertEquals(TimeZone.getDefault(), element.getTimezone()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -181,10 +147,10 @@ public void clientConstructorWithNoArg() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("EEE, dd MMM yyyy HH:mm:ss zzz", element.getPattern()); - assertEquals(Locale.US, element.getLocale()); - assertEquals(TimeZone.getDefault(), element.getTimezone()); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals("EEE, dd MMM yyyy HH:mm:ss zzz", element.getPattern()); + Assertions.assertEquals(Locale.US, element.getLocale()); + Assertions.assertEquals(TimeZone.getDefault(), element.getTimezone()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -194,10 +160,10 @@ public void serverConstructorWithNoSeparator() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("yyyy/MM/dd HH:mm:ss zzz", element.getPattern()); - assertEquals(Locale.US, element.getLocale()); - assertEquals(TimeZone.getDefault(), element.getTimezone()); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals("yyyy/MM/dd HH:mm:ss zzz", element.getPattern()); + Assertions.assertEquals(Locale.US, element.getLocale()); + Assertions.assertEquals(TimeZone.getDefault(), element.getTimezone()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } @Test @@ -207,9 +173,9 @@ public void clientConstructorWithNoSeparator() { simpleDateFormat.setTimeZone(TimeZone.getDefault()); element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("yyyy/MM/dd HH:mm:ss zzz", element.getPattern()); - assertEquals(Locale.US, element.getLocale()); - assertEquals(TimeZone.getDefault(), element.getTimezone()); - assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); + Assertions.assertEquals("yyyy/MM/dd HH:mm:ss zzz", element.getPattern()); + Assertions.assertEquals(Locale.US, element.getLocale()); + Assertions.assertEquals(TimeZone.getDefault(), element.getTimezone()); + Assertions.assertEquals(simpleDateFormat.format(START_MILLISECOND), strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondItemTest.java index 1c4e3c2d4dc..1fdd3b4e0d0 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationMillisecondItemTest.java @@ -17,15 +17,15 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.core.invocation.InvocationStageTrace; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class DurationMillisecondItemTest { @@ -42,7 +42,7 @@ public class DurationMillisecondItemTest { private InvocationStageTrace invocationStageTrace; - @Before + @BeforeEach public void initStrBuilder() { finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); @@ -50,8 +50,7 @@ public void initStrBuilder() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getInvocationStageTrace()).thenReturn(invocationStageTrace); - when(invocationStageTrace.getStartSend()).thenReturn(0L); - when(invocationStageTrace.getFinish()).thenReturn(1000_000L); + when(invocationStageTrace.calcTotal()).thenReturn(1000_000L); accessLogEvent = new ServerAccessLogEvent(); accessLogEvent.setMilliStartTime(1L); @@ -62,10 +61,10 @@ public void initStrBuilder() { @Test public void testAppendFormattedElement() { ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("1", strBuilder.toString()); + Assertions.assertEquals("1", strBuilder.toString()); strBuilder = new StringBuilder(); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("1", strBuilder.toString()); + Assertions.assertEquals("1", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondItemTest.java index 37f84bbd9b7..9cbe7f28da5 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/DurationSecondItemTest.java @@ -17,15 +17,15 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.core.invocation.InvocationStageTrace; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class DurationSecondItemTest { @@ -42,7 +42,7 @@ public class DurationSecondItemTest { private InvocationStageTrace invocationStageTrace; - @Before + @BeforeEach public void initStrBuilder() { finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); @@ -50,7 +50,7 @@ public void initStrBuilder() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getInvocationStageTrace()).thenReturn(invocationStageTrace); - when(invocationStageTrace.getStartSend()).thenReturn(1000_000L); + when(invocationStageTrace.calcTotal()).thenReturn(1L); accessLogEvent = new ServerAccessLogEvent(); accessLogEvent.setMilliStartTime(1L); @@ -61,41 +61,41 @@ public void initStrBuilder() { public void serverFormattedElementOn999ms() { accessLogEvent.setMilliEndTime(1000L); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("0", strBuilder.toString()); + Assertions.assertEquals("0", strBuilder.toString()); } @Test public void clientFormattedElementOn999ms() { - when(invocationStageTrace.getFinish()).thenReturn(1000_000_000L); + when(invocationStageTrace.calcTotal()).thenReturn(0L); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("0", strBuilder.toString()); + Assertions.assertEquals("0", strBuilder.toString()); } @Test public void serverFormattedElementOn1000ms() { accessLogEvent.setMilliEndTime(1001L); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("1", strBuilder.toString()); + Assertions.assertEquals("1", strBuilder.toString()); } @Test public void clientFormattedElementOn1000ms() { - when(invocationStageTrace.getFinish()).thenReturn(1001_000_000L); + when(invocationStageTrace.calcTotal()).thenReturn(1000_000_000L); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("1", strBuilder.toString()); + Assertions.assertEquals("1", strBuilder.toString()); } @Test public void serverFormattedElementOn1001ms() { accessLogEvent.setMilliEndTime(1002L); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("1", strBuilder.toString()); + Assertions.assertEquals("1", strBuilder.toString()); } @Test public void clientFormattedElementOn1001ms() { - when(invocationStageTrace.getFinish()).thenReturn(1002_000_000L); + when(invocationStageTrace.calcTotal()).thenReturn(1000_000_000L); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("1", strBuilder.toString()); + Assertions.assertEquals("1", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/FirstLineOfRequestItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/FirstLineOfRequestItemTest.java index 8d0960d438e..54e1fccef33 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/FirstLineOfRequestItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/FirstLineOfRequestItemTest.java @@ -17,21 +17,21 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpClientRequest; @@ -54,7 +54,7 @@ public class FirstLineOfRequestItemTest { private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpClientRequest clientRequest; @@ -62,12 +62,12 @@ public class FirstLineOfRequestItemTest { private URIEndpointObject urlEndpoint; - @Before + @BeforeEach public void initStrBuilder() { mockContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); endpoint = Mockito.mock(Endpoint.class); urlEndpoint = Mockito.mock(URIEndpointObject.class); @@ -75,7 +75,7 @@ public void initStrBuilder() { handlerMap.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerMap); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(invocation.getEndpoint()).thenReturn(endpoint); when(endpoint.getAddress()).thenReturn(urlEndpoint); accessLogEvent = new ServerAccessLogEvent(); @@ -94,7 +94,7 @@ public void serverFormattedElement() { when(request.version()).thenReturn(HttpVersion.HTTP_1_1); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("\"DELETE " + uri + " HTTP/1.1\"", strBuilder.toString()); + Assertions.assertEquals("\"DELETE " + uri + " HTTP/1.1\"", strBuilder.toString()); } @Test @@ -105,6 +105,6 @@ public void clientFormattedElement() { when(urlEndpoint.isHttp2Enabled()).thenReturn(true); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("\"DELETE " + uri + " HTTP/2.0\"", strBuilder.toString()); + Assertions.assertEquals("\"DELETE " + uri + " HTTP/2.0\"", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodItemTest.java index 4b8261aabce..1dbeba59e9a 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpMethodItemTest.java @@ -23,15 +23,15 @@ import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpClientRequest; @@ -52,7 +52,7 @@ public class HttpMethodItemTest { private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpClientRequest clientRequest; @@ -60,12 +60,12 @@ public class HttpMethodItemTest { private URIEndpointObject urlEndpoint; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); endpoint = Mockito.mock(Endpoint.class); urlEndpoint = Mockito.mock(URIEndpointObject.class); @@ -87,15 +87,15 @@ public void serverFormattedElement() { Mockito.when(request.method()).thenReturn(HttpMethod.DELETE); accessLogEvent.setRoutingContext(routingContext); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("DELETE", strBuilder.toString()); + Assertions.assertEquals("DELETE", strBuilder.toString()); } @Test public void clientFormattedElement() { - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.getMethod()).thenReturn(HttpMethod.DELETE); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("DELETE", strBuilder.toString()); + Assertions.assertEquals("DELETE", strBuilder.toString()); } @Test @@ -103,14 +103,14 @@ public void serverFormattedElementOnRequestIsNull() { accessLogEvent.setRoutingContext(routingContext); Mockito.when(routingContext.request()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnRequestIsNull() { - when(restClientRequest.getRequest()).thenReturn(null); + when(restClientRequest.getHttpClientRequest()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @@ -122,13 +122,13 @@ public void serverFormattedElementOnMethodIsNull() { Mockito.when(routingContext.request()).thenReturn(request); Mockito.when(request.method()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnMethodIsNull() { when(clientRequest.getMethod()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusItemTest.java index 496c0f4a22a..749a38416d8 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/HttpStatusItemTest.java @@ -17,14 +17,14 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpServerResponse; @@ -46,7 +46,7 @@ public class HttpStatusItemTest { private HttpServerResponse serverResponse; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); @@ -65,7 +65,7 @@ public void serverFormattedElement() { when(serverResponse.getStatusCode()).thenReturn(statusCode); STATUS_ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("200", strBuilder.toString()); + Assertions.assertEquals("200", strBuilder.toString()); } @Test @@ -75,14 +75,14 @@ public void clientFormattedElement() { when(response.getStatusCode()).thenReturn(statusCode); STATUS_ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("200", strBuilder.toString()); + Assertions.assertEquals("200", strBuilder.toString()); } @Test public void serverFormattedElementOnResponseIsNull() { Mockito.when(routingContext.response()).thenReturn(null); STATUS_ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); Mockito.when(routingContext.response()).thenReturn(serverResponse); Mockito.when(serverResponse.closed()).thenReturn(true); @@ -90,13 +90,13 @@ public void serverFormattedElementOnResponseIsNull() { strBuilder = new StringBuilder(); STATUS_ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnResponseIsNull() { when(finishEvent.getResponse()).thenReturn(null); STATUS_ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextItemTest.java index 27b44497cdd..644ac99de8f 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/InvocationContextItemTest.java @@ -26,10 +26,10 @@ import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.ext.web.RoutingContext; @@ -40,7 +40,7 @@ public class InvocationContextItemTest { public static final String INVOCATION_CONTEXT_VALUE = "testValue"; - private static InvocationContextAccessItem ITEM = new InvocationContextAccessItem(INVOCATION_CONTEXT_KEY); + private static final InvocationContextAccessItem ITEM = new InvocationContextAccessItem(INVOCATION_CONTEXT_KEY); private StringBuilder strBuilder; @@ -52,7 +52,7 @@ public class InvocationContextItemTest { private Invocation invocation; - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); routingContext = Mockito.mock(RoutingContext.class); @@ -71,7 +71,7 @@ public void serverGetFormattedItem() { when(invocation.getContext(INVOCATION_CONTEXT_KEY)).thenReturn(INVOCATION_CONTEXT_VALUE); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(INVOCATION_CONTEXT_VALUE)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(INVOCATION_CONTEXT_VALUE)); } @Test @@ -82,7 +82,7 @@ public void clientGetFormattedItem() { context.put(INVOCATION_CONTEXT_KEY, INVOCATION_CONTEXT_VALUE); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(INVOCATION_CONTEXT_VALUE)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(INVOCATION_CONTEXT_VALUE)); } @Test @@ -94,7 +94,7 @@ public void serverGetFormattedItemOnInvocationContextValueNotFound() { when(invocation.getContext(INVOCATION_CONTEXT_KEY)).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } @Test @@ -105,7 +105,7 @@ public void clientGetFormattedItemOnInvocationContextValueNotFound() { context.put(INVOCATION_CONTEXT_KEY, null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } @Test @@ -114,7 +114,7 @@ public void serverGetFormattedItemOnInvocationNotFound() { when(routingContext.data()).thenReturn(routingContextData); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } @Test @@ -124,14 +124,14 @@ public void clientGetFormattedItemOnInvocationContextNotFound() { when(invocation.getContext()).thenReturn(context); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } @Test public void testGetFormattedItemOnRoutingContextDataNotFound() { when(routingContext.data()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } @Test @@ -139,13 +139,13 @@ public void clientGetFormattedItemOnRoutingContextDataNotFound() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getContext()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } @Test public void clientGetFormattedItemOnInvocationNotFound() { when(finishEvent.getInvocation()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); + MatcherAssert.assertThat(strBuilder.toString(), Matchers.is(InvocationContextAccessItem.NOT_FOUND)); } -} \ No newline at end of file +} diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalHostItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalHostItemTest.java index 9e780a08431..d1669f0316c 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalHostItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalHostItemTest.java @@ -17,20 +17,19 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpClientRequest; @@ -56,13 +55,13 @@ public class LocalHostItemTest { private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpClientRequest clientRequest; private HttpConnection connection; - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); routingContext = Mockito.mock(RoutingContext.class); @@ -70,7 +69,7 @@ public void initStrBuilder() { serverRequest = Mockito.mock(HttpServerRequest.class); socketAddress = Mockito.mock(SocketAddress.class); invocation = Mockito.mock(Invocation.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); connection = Mockito.mock(HttpConnection.class); Map handlerMap = new HashMap<>(); @@ -84,12 +83,12 @@ public void initStrBuilder() { @Test public void clientFormattedItem() { String localAddress = "192.168.0.1"; - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.connection()).thenReturn(connection); when(connection.localAddress()).thenReturn(socketAddress); when(socketAddress.host()).thenReturn(localAddress); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals(localAddress, strBuilder.toString()); + Assertions.assertEquals(localAddress, strBuilder.toString()); } @Test @@ -97,7 +96,7 @@ public void serverFormattedItem() { String localAddress = "192.168.0.1"; accessLogEvent.setLocalAddress(localAddress); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals(localAddress, strBuilder.toString()); + Assertions.assertEquals(localAddress, strBuilder.toString()); } @Test @@ -108,21 +107,21 @@ public void getLocalAddress() { Mockito.when(socketAddress.host()).thenReturn(localHost); String result = LocalHostAccessItem.getLocalAddress(routingContext); - assertEquals(localHost, result); + Assertions.assertEquals(localHost, result); } @Test public void serverLocalAddressOnRequestIsNull() { Mockito.when(routingContext.request()).thenReturn(null); String result = LocalHostAccessItem.getLocalAddress(routingContext); - assertEquals("-", result); + Assertions.assertEquals("-", result); } @Test public void clientLocalAddressOnRequestIsNull() { - when(restClientRequest.getRequest()).thenReturn(null); + when(restClientRequest.getHttpClientRequest()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -130,16 +129,16 @@ public void serverLocalAddressOnLocalAddressIsNull() { Mockito.when(routingContext.request()).thenReturn(serverRequest); Mockito.when(serverRequest.localAddress()).thenReturn(null); String result = LocalHostAccessItem.getLocalAddress(routingContext); - assertEquals("-", result); + Assertions.assertEquals("-", result); } @Test public void clientLocalAddressOnLocalAddressIsNull() { - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.connection()).thenReturn(connection); when(connection.localAddress()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -149,17 +148,17 @@ public void serverLocalAddressOnHostIsNull() { Mockito.when(socketAddress.host()).thenReturn(null); String result = LocalHostAccessItem.getLocalAddress(routingContext); - assertEquals("-", result); + Assertions.assertEquals("-", result); } @Test public void clientLocalAddressOnHostIsNull() { - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.connection()).thenReturn(connection); when(connection.localAddress()).thenReturn(socketAddress); when(socketAddress.host()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -170,16 +169,16 @@ public void serverLocalAddressIsEmpty() { Mockito.when(socketAddress.host()).thenReturn(localHost); String result = LocalHostAccessItem.getLocalAddress(routingContext); - assertEquals("-", result); + Assertions.assertEquals("-", result); } @Test public void clientLocalAddressIsEmpty() { - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.connection()).thenReturn(connection); when(connection.localAddress()).thenReturn(socketAddress); when(socketAddress.host()).thenReturn(""); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalPortItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalPortItemTest.java index 81e48fc4e34..f77c51fbe74 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalPortItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/LocalPortItemTest.java @@ -17,19 +17,19 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpClientRequest; @@ -55,13 +55,13 @@ public class LocalPortItemTest { private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpClientRequest clientRequest; private HttpConnection connection; - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); routingContext = Mockito.mock(RoutingContext.class); @@ -69,7 +69,7 @@ public void initStrBuilder() { serverRequest = Mockito.mock(HttpServerRequest.class); socketAddress = Mockito.mock(SocketAddress.class); invocation = Mockito.mock(Invocation.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); connection = Mockito.mock(HttpConnection.class); Map handlerMap = new HashMap<>(); @@ -87,31 +87,31 @@ public void serverFormattedElement() { Mockito.when(socketAddress.port()).thenReturn(8080); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("8080", strBuilder.toString()); + Assertions.assertEquals("8080", strBuilder.toString()); } @Test public void clientFormattedElement() { - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.connection()).thenReturn(connection); when(connection.localAddress()).thenReturn(socketAddress); when(socketAddress.port()).thenReturn(8080); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("8080", strBuilder.toString()); + Assertions.assertEquals("8080", strBuilder.toString()); } @Test public void serverFormattedElementOnRequestIsNull() { Mockito.when(routingContext.request()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnRequestIsNull() { - when(restClientRequest.getRequest()).thenReturn(null); + when(restClientRequest.getHttpClientRequest()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -119,15 +119,15 @@ public void serverFormattedElementOnLocalAddressIsNull() { Mockito.when(routingContext.request()).thenReturn(serverRequest); Mockito.when(serverRequest.localAddress()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnLocalAddressIsNull() { - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.connection()).thenReturn(connection); when(connection.localAddress()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/PlainTextItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/PlainTextItemTest.java index 305371ae7d5..b49b7562669 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/PlainTextItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/PlainTextItemTest.java @@ -17,12 +17,11 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; - import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class PlainTextItemTest { @@ -32,7 +31,7 @@ public class PlainTextItemTest { private StringBuilder strBuilder; - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); finishEvent = Mockito.mock(InvocationFinishEvent.class); @@ -43,13 +42,13 @@ public void initStrBuilder() { public void serverFormattedElement() { PlainTextAccessItem element = new PlainTextAccessItem("contentTest"); element.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("contentTest", strBuilder.toString()); + Assertions.assertEquals("contentTest", strBuilder.toString()); } @Test public void clientFormattedElement() { PlainTextAccessItem element = new PlainTextAccessItem("contentTest"); element.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("contentTest", strBuilder.toString()); + Assertions.assertEquals("contentTest", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/QueryStringItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/QueryStringItemTest.java index 60927f06515..ef472623d43 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/QueryStringItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/QueryStringItemTest.java @@ -17,19 +17,19 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpClientRequest; @@ -49,19 +49,19 @@ public class QueryStringItemTest { private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpServerRequest serverRequest; private HttpClientRequest clientRequest; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); serverRequest = Mockito.mock(HttpServerRequest.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); accessLogEvent = new ServerAccessLogEvent(); @@ -75,7 +75,7 @@ public void serverFormattedElement() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.query()).thenReturn(query); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(query, strBuilder.toString()); + Assertions.assertEquals(query, strBuilder.toString()); } @Test @@ -85,18 +85,18 @@ public void clientFormattedElement() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.query()).thenReturn(query); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(query, strBuilder.toString()); + Assertions.assertEquals(query, strBuilder.toString()); } @Test public void serverFormattedElementOnRequestIsNull() { when(routingContext.request()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -105,10 +105,10 @@ public void clientFormattedElementOnRequestIsNull() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(null); + when(restClientRequest.getHttpClientRequest()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -116,7 +116,7 @@ public void serverFormattedElementOnQueryIsNull() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.query()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -125,11 +125,11 @@ public void clientFormattedElementOnQueryIsNull() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.query()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -138,7 +138,7 @@ public void serverFormattedElementOnQueryIsEmpty() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.query()).thenReturn(query); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -148,10 +148,10 @@ public void clientFormattedElementOnQueryIsEmpty() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.query()).thenReturn(query); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RemoteHostItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RemoteHostItemTest.java index f6b442e3f26..096e40f805a 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RemoteHostItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RemoteHostItemTest.java @@ -17,7 +17,6 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -26,12 +25,13 @@ import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.junit.Before; -import org.junit.Test; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.net.SocketAddress; import io.vertx.ext.web.RoutingContext; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class RemoteHostItemTest { public static final RemoteHostAccessItem ELEMENT = new RemoteHostAccessItem(); @@ -54,7 +54,7 @@ public class RemoteHostItemTest { private SocketAddress socketAddress; - @Before + @BeforeEach public void initStrBuilder() { routingContext = mock(RoutingContext.class); finishEvent = mock(InvocationFinishEvent.class); @@ -76,7 +76,7 @@ public void serverFormattedElement() { when(socketAddress.host()).thenReturn(remoteHost); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(remoteHost, strBuilder.toString()); + Assertions.assertEquals(remoteHost, strBuilder.toString()); } @Test @@ -87,14 +87,14 @@ public void clientFormattedElement() { when(endpoint.getAddress()).thenReturn(uriEndpointObject); when(uriEndpointObject.getHostOrIp()).thenReturn(remoteHost); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(remoteHost, strBuilder.toString()); + Assertions.assertEquals(remoteHost, strBuilder.toString()); } @Test public void serverFormattedElementOnRequestIsNull() { when(routingContext.request()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -102,7 +102,7 @@ public void clientFormattedElementOnRequestIsNull() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getEndpoint()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -110,7 +110,7 @@ public void serverFormattedElementOnRemoteAddressIsNull() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.remoteAddress()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -119,7 +119,7 @@ public void clientFormattedElementOnRemoteAddressIsNull() { when(invocation.getEndpoint()).thenReturn(endpoint); when(endpoint.getAddress()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -128,7 +128,7 @@ public void serverFormattedElementOnHostIsNull() { when(serverRequest.remoteAddress()).thenReturn(socketAddress); when(socketAddress.host()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -138,7 +138,7 @@ public void clientFormattedElementOnHostIsNull() { when(endpoint.getAddress()).thenReturn(uriEndpointObject); when(uriEndpointObject.getHostOrIp()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -147,7 +147,7 @@ public void serverFormattedElementOnHostIsEmpty() { when(serverRequest.remoteAddress()).thenReturn(socketAddress); when(socketAddress.host()).thenReturn(""); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -157,6 +157,6 @@ public void clientFormattedElementOnHostIsEmpty() { when(endpoint.getAddress()).thenReturn(uriEndpointObject); when(uriEndpointObject.getHostOrIp()).thenReturn(""); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestHeaderItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestHeaderItemTest.java index b4949dfc52f..f2ae7004251 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestHeaderItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestHeaderItemTest.java @@ -17,19 +17,19 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import java.util.HashMap; import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.MultiMap; @@ -53,7 +53,7 @@ public class RequestHeaderItemTest { private Invocation invocation; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpServerRequest serverRequest; @@ -61,13 +61,13 @@ public class RequestHeaderItemTest { private MultiMap headers; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); serverRequest = Mockito.mock(HttpServerRequest.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); headers = Mockito.mock(MultiMap.class); @@ -78,15 +78,15 @@ public void initStrBuilder() { @Test public void serverFormattedElement() { - HeadersMultiMap headers = new HeadersMultiMap(); + HeadersMultiMap headers = HeadersMultiMap.httpHeaders(); String testValue = "testValue"; headers.add(VAR_NAME, testValue); when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.headers()).thenReturn(headers); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(testValue, strBuilder.toString()); - assertEquals(ELEMENT.getVarName(), VAR_NAME); + Assertions.assertEquals(testValue, strBuilder.toString()); + Assertions.assertEquals(ELEMENT.getVarName(), VAR_NAME); } @Test @@ -97,12 +97,12 @@ public void clientFormattedElement() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.headers()).thenReturn(headers); when(headers.get(VAR_NAME)).thenReturn(testValue); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(testValue, strBuilder.toString()); + Assertions.assertEquals(testValue, strBuilder.toString()); } @Test @@ -111,7 +111,7 @@ public void serverFormattedElementIfHeaderIsNull() { when(serverRequest.headers()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -120,22 +120,22 @@ public void clientFormattedElementIfHeaderIsNull() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.headers()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void serverFormattedElementIfNotFound() { - HeadersMultiMap headers = new HeadersMultiMap(); + HeadersMultiMap headers = HeadersMultiMap.httpHeaders(); String testValue = "testValue"; headers.add("anotherKey", testValue); when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.headers()).thenReturn(headers); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestProtocolItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestProtocolItemTest.java index d777883b916..020df94aeb2 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestProtocolItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/RequestProtocolItemTest.java @@ -17,7 +17,6 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.core.Endpoint; @@ -25,8 +24,9 @@ import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpServerRequest; @@ -52,7 +52,7 @@ public class RequestProtocolItemTest { private URIEndpointObject urlEndpoint; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); @@ -72,17 +72,17 @@ public void serverFormattedElement() { when(serverRequest.version()).thenReturn(HttpVersion.HTTP_1_1); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("HTTP/1.1", strBuilder.toString()); + Assertions.assertEquals("HTTP/1.1", strBuilder.toString()); strBuilder = new StringBuilder(); when(serverRequest.version()).thenReturn(HttpVersion.HTTP_1_0); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("HTTP/1.0", strBuilder.toString()); + Assertions.assertEquals("HTTP/1.0", strBuilder.toString()); strBuilder = new StringBuilder(); when(serverRequest.version()).thenReturn(HttpVersion.HTTP_2); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("HTTP/2.0", strBuilder.toString()); + Assertions.assertEquals("HTTP/2.0", strBuilder.toString()); } @Test @@ -92,7 +92,7 @@ public void clientFormattedElementOnRequestIsNull() { when(endpoint.getAddress()).thenReturn(urlEndpoint); when(urlEndpoint.isHttp2Enabled()).thenReturn(true); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("HTTP/2.0", strBuilder.toString()); + Assertions.assertEquals("HTTP/2.0", strBuilder.toString()); strBuilder = new StringBuilder(); when(finishEvent.getInvocation()).thenReturn(invocation); @@ -100,7 +100,7 @@ public void clientFormattedElementOnRequestIsNull() { when(endpoint.getAddress()).thenReturn(urlEndpoint); when(urlEndpoint.isHttp2Enabled()).thenReturn(false); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("HTTP/1.1", strBuilder.toString()); + Assertions.assertEquals("HTTP/1.1", strBuilder.toString()); } @Test @@ -109,7 +109,7 @@ public void serverFormattedElementOnVersionIsNull() { when(serverRequest.version()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -119,6 +119,6 @@ public void clientFormattedElementOnVersionIsNull() { when(endpoint.getAddress()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("HTTP/1.1", strBuilder.toString()); + Assertions.assertEquals("HTTP/1.1", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseHeaderItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseHeaderItemTest.java index 088a775d3d5..a8708172945 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseHeaderItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseHeaderItemTest.java @@ -17,14 +17,14 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.MultiMap; @@ -50,7 +50,7 @@ public class ResponseHeaderItemTest { private Response response; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); @@ -64,15 +64,15 @@ public void initStrBuilder() { @Test public void serverFormattedElement() { - HeadersMultiMap headers = new HeadersMultiMap(); + HeadersMultiMap headers = HeadersMultiMap.httpHeaders(); String headerValue = "headerValue"; headers.add(VAR_NAME, headerValue); when(routingContext.response()).thenReturn(serverResponse); when(serverResponse.headers()).thenReturn(headers); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(headerValue, strBuilder.toString()); - assertEquals(ELEMENT.getVarName(), VAR_NAME); + Assertions.assertEquals(headerValue, strBuilder.toString()); + Assertions.assertEquals(ELEMENT.getVarName(), VAR_NAME); } @Test @@ -84,8 +84,8 @@ public void clientFormattedElement() { when(finishEvent.getResponse()).thenReturn(response); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(headerValue, strBuilder.toString()); - assertEquals(ELEMENT.getVarName(), VAR_NAME); + Assertions.assertEquals(headerValue, strBuilder.toString()); + Assertions.assertEquals(ELEMENT.getVarName(), VAR_NAME); } @Test @@ -94,7 +94,7 @@ public void serverFormattedElementOnHeadersIsNull() { when(serverResponse.headers()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -103,33 +103,33 @@ public void clientFormattedElementOnHeadersIsNull() { when(response.getHeaders()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void serverFormattedElementOnResponseIsNull() { when(routingContext.response()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnResponseIsNull() { when(finishEvent.getResponse()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void serverFormattedElementOnNotFound() { - HeadersMultiMap headers = new HeadersMultiMap(); + HeadersMultiMap headers = HeadersMultiMap.httpHeaders(); String headerValue = "headerValue"; headers.add("anotherHeader", headerValue); when(routingContext.response()).thenReturn(serverResponse); when(serverResponse.headers()).thenReturn(headers); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -141,6 +141,6 @@ public void clientFormattedElementOnNotFound() { when(response.getHeaders()).thenReturn(headers); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseSizeItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseSizeItemTest.java index 55a1b094e11..e5f6e6ae17f 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseSizeItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/ResponseSizeItemTest.java @@ -17,13 +17,13 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpServerResponse; @@ -42,7 +42,7 @@ public class ResponseSizeItemTest { private HttpServerResponse serverResponse; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); finishEvent = Mockito.mock(InvocationFinishEvent.class); @@ -60,20 +60,20 @@ public void serverFormattedElement() { when(serverResponse.bytesWritten()).thenReturn(bytesWritten); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(String.valueOf(bytesWritten), strBuilder.toString()); + Assertions.assertEquals(String.valueOf(bytesWritten), strBuilder.toString()); } @Test public void clientFormattedElement() { ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("0", strBuilder.toString()); + Assertions.assertEquals("0", strBuilder.toString()); } @Test public void getFormattedElementOnResponseIsNull() { when(routingContext.response()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("0", strBuilder.toString()); + Assertions.assertEquals("0", strBuilder.toString()); } @Test @@ -82,6 +82,6 @@ public void getFormattedElementOnBytesWrittenIsZero() { when(routingContext.response()).thenReturn(serverResponse); when(serverResponse.bytesWritten()).thenReturn(bytesWritten); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("0", strBuilder.toString()); + Assertions.assertEquals("0", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TraceIdItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TraceIdItemTest.java index 96cb04ac851..b21dc7dfbaf 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TraceIdItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TraceIdItemTest.java @@ -24,13 +24,13 @@ import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpServerRequest; @@ -51,9 +51,9 @@ public class TraceIdItemTest { private Invocation invocation; - private Map clientContext = new HashMap<>(); + private final Map clientContext = new HashMap<>(); - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); routingContext = Mockito.mock(RoutingContext.class); @@ -70,74 +70,74 @@ public void initStrBuilder() { public void serverGetFormattedElementFromInvocationContext() { Map data = new HashMap<>(); String traceIdTest = "traceIdTest"; - when(invocation.getContext(Const.TRACE_ID_NAME)).thenReturn(traceIdTest); + when(invocation.getContext(CoreConst.TRACE_ID_NAME)).thenReturn(traceIdTest); when(routingContext.data()).thenReturn(data); data.put(RestConst.REST_INVOCATION_CONTEXT, invocation); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is(traceIdTest)); + MatcherAssert.assertThat(strBuilder.toString(), is(traceIdTest)); } @Test public void clientGetFormattedElementFromInvocationContext() { String traceIdTest = "traceIdTest"; - clientContext.put(Const.TRACE_ID_NAME, traceIdTest); + clientContext.put(CoreConst.TRACE_ID_NAME, traceIdTest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getContext()).thenReturn(clientContext); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is(traceIdTest)); + MatcherAssert.assertThat(strBuilder.toString(), is(traceIdTest)); } @Test public void serverGetFormattedElementFromRequestHeader() { Map data = new HashMap<>(); String traceIdTest = "traceIdTest"; - when(invocation.getContext(Const.TRACE_ID_NAME)).thenReturn(null); + when(invocation.getContext(CoreConst.TRACE_ID_NAME)).thenReturn(null); when(routingContext.data()).thenReturn(data); data.put(RestConst.REST_INVOCATION_CONTEXT, invocation); - when(serverRequest.getHeader(Const.TRACE_ID_NAME)).thenReturn(traceIdTest); + when(serverRequest.getHeader(CoreConst.TRACE_ID_NAME)).thenReturn(traceIdTest); when(routingContext.request()).thenReturn(serverRequest); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is(traceIdTest)); + MatcherAssert.assertThat(strBuilder.toString(), is(traceIdTest)); } @Test public void serverGetFormattedElementOnTraceIdNotFound() { Map data = new HashMap<>(); - when(invocation.getContext(Const.TRACE_ID_NAME)).thenReturn(""); + when(invocation.getContext(CoreConst.TRACE_ID_NAME)).thenReturn(""); when(routingContext.data()).thenReturn(data); data.put(RestConst.REST_INVOCATION_CONTEXT, invocation); - when(serverRequest.getHeader(Const.TRACE_ID_NAME)).thenReturn(null); + when(serverRequest.getHeader(CoreConst.TRACE_ID_NAME)).thenReturn(null); when(routingContext.request()).thenReturn(serverRequest); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is("-")); + MatcherAssert.assertThat(strBuilder.toString(), is("-")); strBuilder = new StringBuilder(); - when(invocation.getContext(Const.TRACE_ID_NAME)).thenReturn(null); + when(invocation.getContext(CoreConst.TRACE_ID_NAME)).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is("-")); + MatcherAssert.assertThat(strBuilder.toString(), is("-")); } @Test public void clientGetFormattedElementOnTraceIdNotFound() { - clientContext.put(Const.TRACE_ID_NAME, null); + clientContext.put(CoreConst.TRACE_ID_NAME, null); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getContext()).thenReturn(clientContext); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is("-")); + MatcherAssert.assertThat(strBuilder.toString(), is("-")); } @Test public void serverGetFormattedElementOnInvocationContextIsNull() { when(routingContext.data()).thenReturn(null); when(routingContext.request()).thenReturn(serverRequest); - when(serverRequest.getHeader(Const.TRACE_ID_NAME)).thenReturn(null); + when(serverRequest.getHeader(CoreConst.TRACE_ID_NAME)).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is("-")); + MatcherAssert.assertThat(strBuilder.toString(), is("-")); } @Test @@ -146,15 +146,15 @@ public void clientGetFormattedElementOnInvocationContextIsNull() { when(invocation.getContext()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is("-")); + MatcherAssert.assertThat(strBuilder.toString(), is("-")); } @Test public void serverGetFormattedElementOnDataIsNull() { - when(serverRequest.getHeader(Const.TRACE_ID_NAME)).thenReturn(null); + when(serverRequest.getHeader(CoreConst.TRACE_ID_NAME)).thenReturn(null); when(routingContext.request()).thenReturn(serverRequest); when(routingContext.data()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertThat(strBuilder.toString(), is("-")); + MatcherAssert.assertThat(strBuilder.toString(), is("-")); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TransportItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TransportItemTest.java index 0f1c980b9c3..02a111b94c0 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TransportItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/TransportItemTest.java @@ -23,9 +23,9 @@ import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class TransportItemTest { @@ -41,7 +41,7 @@ public class TransportItemTest { private Endpoint endpoint; - @Before + @BeforeEach public void initStrBuilder() { finishEvent = Mockito.mock(InvocationFinishEvent.class); invocation = Mockito.mock(Invocation.class); @@ -55,20 +55,20 @@ public void clientFormattedElement() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getConfigTransportName()).thenReturn("rest"); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("rest", strBuilder.toString()); + Assertions.assertEquals("rest", strBuilder.toString()); strBuilder = new StringBuilder(); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getEndpoint()).thenReturn(endpoint); when(endpoint.getEndpoint()).thenReturn("rest:xxx:30100"); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("rest", strBuilder.toString()); + Assertions.assertEquals("rest", strBuilder.toString()); } @Test public void serverFormattedElement() { ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("rest", strBuilder.toString()); + Assertions.assertEquals("rest", strBuilder.toString()); } @Test @@ -81,7 +81,7 @@ public void clientConfigTransportNameIsNull() { when(invocation.getEndpoint()).thenReturn(endpoint); when(endpoint.getEndpoint()).thenReturn("rest:xxx:30100"); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("rest", strBuilder.toString()); + Assertions.assertEquals("rest", strBuilder.toString()); } @Test @@ -93,7 +93,7 @@ public void clientConfigTransportNameIsEmpty() { when(invocation.getEndpoint()).thenReturn(endpoint); when(endpoint.getEndpoint()).thenReturn("rest:xxx:30100"); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("rest", strBuilder.toString()); + Assertions.assertEquals("rest", strBuilder.toString()); } @Test @@ -104,6 +104,6 @@ public void clientALLIsEmpty() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getEndpoint()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathItemTest.java index 1d5d0638a66..d1601609a28 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathItemTest.java @@ -23,18 +23,18 @@ import java.util.Map; import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.transport.rest.client.RestClientRequestParameters; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpServerRequest; import io.vertx.ext.web.RoutingContext; @@ -58,13 +58,13 @@ public class UrlPathItemTest { private SchemaMeta schemaMeta; - private Swagger swagger; + private OpenAPI swagger; - private RestClientRequestImpl restClientRequest; + private RestClientRequestParameters restClientRequest; private HttpClientRequest clientRequest; - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); routingContext = Mockito.mock(RoutingContext.class); @@ -73,8 +73,8 @@ public void initStrBuilder() { serverRequest = Mockito.mock(HttpServerRequest.class); operationMeta = Mockito.mock(OperationMeta.class); schemaMeta = Mockito.mock(SchemaMeta.class); - swagger = Mockito.mock(Swagger.class); - restClientRequest = Mockito.mock(RestClientRequestImpl.class); + swagger = Mockito.mock(OpenAPI.class); + restClientRequest = Mockito.mock(RestClientRequestParameters.class); clientRequest = Mockito.mock(HttpClientRequest.class); accessLogEvent.setRoutingContext(routingContext); @@ -83,16 +83,15 @@ public void initStrBuilder() { @Test public void clientFormattedElement() { - String uri = "/base/test"; + String uri = "/test"; when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getOperationMeta()).thenReturn(operationMeta); when(invocation.getSchemaMeta()).thenReturn(schemaMeta); when(schemaMeta.getSwagger()).thenReturn(swagger); - when(swagger.getBasePath()).thenReturn("/base"); when(operationMeta.getOperationPath()).thenReturn("/test"); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals(uri, strBuilder.toString()); + Assertions.assertEquals(uri, strBuilder.toString()); strBuilder = new StringBuilder(); Map handlerContext = new HashMap<>(); @@ -101,10 +100,10 @@ public void clientFormattedElement() { when(invocation.getSchemaMeta()).thenReturn(null); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.path()).thenReturn(uri); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals(uri, strBuilder.toString()); + Assertions.assertEquals(uri, strBuilder.toString()); } @Test @@ -113,14 +112,14 @@ public void serverFormattedElement() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.path()).thenReturn(uri); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals(uri, strBuilder.toString()); + Assertions.assertEquals(uri, strBuilder.toString()); } @Test public void serverFormattedElementOnRequestIsNull() { when(routingContext.request()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -129,9 +128,9 @@ public void clientFormattedElementOnRequestIsNull() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(null); + when(restClientRequest.getHttpClientRequest()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -139,7 +138,7 @@ public void serverFormattedElementOnMethodIsNull() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.path()).thenReturn(null); ITEM.appendServerFormattedItem(accessLogEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -148,9 +147,9 @@ public void clientFormattedElementOnMethodIsNull() { handlerContext.put(RestConst.INVOCATION_HANDLER_REQUESTCLIENT, restClientRequest); when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getHandlerContext()).thenReturn(handlerContext); - when(restClientRequest.getRequest()).thenReturn(clientRequest); + when(restClientRequest.getHttpClientRequest()).thenReturn(clientRequest); when(clientRequest.path()).thenReturn(null); ITEM.appendClientFormattedItem(finishEvent, strBuilder); - Assert.assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathWithQueryItemTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathWithQueryItemTest.java index a2f01e896c8..f0bebc1f3d7 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathWithQueryItemTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UrlPathWithQueryItemTest.java @@ -17,15 +17,15 @@ package org.apache.servicecomb.common.accessLog.core.element.impl; -import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.when; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.core.http.HttpServerRequest; @@ -47,7 +47,7 @@ public class UrlPathWithQueryItemTest { private HttpServerRequest serverRequest; - @Before + @BeforeEach public void initStrBuilder() { accessLogEvent = new ServerAccessLogEvent(); routingContext = Mockito.mock(RoutingContext.class); @@ -65,7 +65,7 @@ public void serverFormattedElement() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.uri()).thenReturn(uri); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals(uri, strBuilder.toString()); + Assertions.assertEquals(uri, strBuilder.toString()); } @Test @@ -74,21 +74,21 @@ public void clientFormattedElement() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getLocalContext(RestConst.REST_CLIENT_REQUEST_PATH)).thenReturn(uri); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals(uri, strBuilder.toString()); + Assertions.assertEquals(uri, strBuilder.toString()); } @Test public void serverFormattedElementOnRequestIsNull() { when(routingContext.request()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test public void clientFormattedElementOnRequestIsNull() { when(finishEvent.getInvocation()).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -96,7 +96,7 @@ public void serverFormattedElementOnUriIsNull() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.uri()).thenReturn(null); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -104,7 +104,7 @@ public void clientFormattedElementOnUriIsNull() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getLocalContext(RestConst.REST_CLIENT_REQUEST_PATH)).thenReturn(null); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -112,7 +112,7 @@ public void serverFormattedElementOnUriIsEmpty() { when(routingContext.request()).thenReturn(serverRequest); when(serverRequest.uri()).thenReturn(""); ELEMENT.appendServerFormattedItem(accessLogEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } @Test @@ -120,6 +120,6 @@ public void clientFormattedElementOnUriIsEmpty() { when(finishEvent.getInvocation()).thenReturn(invocation); when(invocation.getLocalContext(RestConst.REST_CLIENT_REQUEST_PATH)).thenReturn(""); ELEMENT.appendClientFormattedItem(finishEvent, strBuilder); - assertEquals("-", strBuilder.toString()); + Assertions.assertEquals("-", strBuilder.toString()); } } diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UserDefinedAccessLogItem.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UserDefinedAccessLogItem.java index 295f13405e2..0cee6247efe 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UserDefinedAccessLogItem.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/element/impl/UserDefinedAccessLogItem.java @@ -28,7 +28,7 @@ * For access log extension test */ public class UserDefinedAccessLogItem implements AccessLogItem { - private String config; + private final String config; public UserDefinedAccessLogItem(String config) { this.config = config; diff --git a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/parser/impl/VertxRestAccessLogPatternParserTest.java b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/parser/impl/VertxRestAccessLogPatternParserTest.java index e7db2732be7..d870fc2b225 100644 --- a/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/parser/impl/VertxRestAccessLogPatternParserTest.java +++ b/common/common-access-log/src/test/java/org/apache/servicecomb/common/accessLog/core/parser/impl/VertxRestAccessLogPatternParserTest.java @@ -17,9 +17,6 @@ package org.apache.servicecomb.common.accessLog.core.parser.impl; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - import java.util.ArrayList; import java.util.Comparator; import java.util.List; @@ -50,15 +47,12 @@ import org.apache.servicecomb.common.accessLog.core.parser.CompositeVertxRestAccessLogItemMeta; import org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta; import org.apache.servicecomb.core.event.ServerAccessLogEvent; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import io.vertx.ext.web.RoutingContext; -import mockit.Deencapsulation; -import mockit.Mock; -import mockit.MockUp; public class VertxRestAccessLogPatternParserTest { private static final String ROW_PATTERN = "[cs-method] %m %s%T%D%h%v%p%B%b%r%U%q" @@ -71,14 +65,14 @@ public class VertxRestAccessLogPatternParserTest { + "%{ctx}SCB-ctx" + "%SCB-transport"; - private static VertxRestAccessLogPatternParser logPatternParser = new VertxRestAccessLogPatternParser(); + private static final VertxRestAccessLogPatternParser logPatternParser = new VertxRestAccessLogPatternParser(); private ServerAccessLogEvent accessLogEvent; private RoutingContext routingContext; - @Before + @BeforeEach public void initStrBuilder() { routingContext = Mockito.mock(RoutingContext.class); accessLogEvent = new ServerAccessLogEvent(); @@ -88,169 +82,169 @@ public void initStrBuilder() { @Test public void testParsePatternFullTest() { List> result = logPatternParser.parsePattern(ROW_PATTERN); - assertEquals(29, result.size()); + Assertions.assertEquals(29, result.size()); StringBuilder builder = new StringBuilder(); result.get(0).appendServerFormattedItem(accessLogEvent, builder); - assertEquals("[", builder.toString()); - assertEquals(HttpMethodAccessItem.class, result.get(1).getClass()); + Assertions.assertEquals("[", builder.toString()); + Assertions.assertEquals(HttpMethodAccessItem.class, result.get(1).getClass()); builder = new StringBuilder(); result.get(2).appendServerFormattedItem(accessLogEvent, builder); - assertEquals("] ", builder.toString()); - assertEquals(HttpMethodAccessItem.class, result.get(3).getClass()); + Assertions.assertEquals("] ", builder.toString()); + Assertions.assertEquals(HttpMethodAccessItem.class, result.get(3).getClass()); builder = new StringBuilder(); result.get(4).appendServerFormattedItem(accessLogEvent, builder); - assertEquals(" ", builder.toString()); - assertEquals(HttpStatusAccessItem.class, result.get(5).getClass()); - assertEquals(DurationSecondAccessItem.class, result.get(6).getClass()); - assertEquals(DurationMillisecondAccessItem.class, result.get(7).getClass()); - assertEquals(RemoteHostAccessItem.class, result.get(8).getClass()); - assertEquals(LocalHostAccessItem.class, result.get(9).getClass()); - assertEquals(LocalPortAccessItem.class, result.get(10).getClass()); - assertEquals(ResponseSizeAccessItem.class, result.get(11).getClass()); - assertEquals("0", ((ResponseSizeAccessItem) result.get(11)).getZeroBytes()); - assertEquals(ResponseSizeAccessItem.class, result.get(12).getClass()); - assertEquals("-", ((ResponseSizeAccessItem) result.get(12)).getZeroBytes()); - assertEquals(FirstLineOfRequestAccessItem.class, result.get(13).getClass()); - assertEquals(UrlPathAccessItem.class, result.get(14).getClass()); - assertEquals(QueryStringAccessItem.class, result.get(15).getClass()); - assertEquals(UrlPathAccessItem.class, result.get(16).getClass()); - assertEquals(QueryStringAccessItem.class, result.get(17).getClass()); - assertEquals(UrlPathWithQueryAccessItem.class, result.get(18).getClass()); - assertEquals(RequestProtocolAccessItem.class, result.get(19).getClass()); - assertEquals(ConfigurableDatetimeAccessItem.class, result.get(20).getClass()); - assertEquals(ConfigurableDatetimeAccessItem.DEFAULT_DATETIME_PATTERN, + Assertions.assertEquals(" ", builder.toString()); + Assertions.assertEquals(HttpStatusAccessItem.class, result.get(5).getClass()); + Assertions.assertEquals(DurationSecondAccessItem.class, result.get(6).getClass()); + Assertions.assertEquals(DurationMillisecondAccessItem.class, result.get(7).getClass()); + Assertions.assertEquals(RemoteHostAccessItem.class, result.get(8).getClass()); + Assertions.assertEquals(LocalHostAccessItem.class, result.get(9).getClass()); + Assertions.assertEquals(LocalPortAccessItem.class, result.get(10).getClass()); + Assertions.assertEquals(ResponseSizeAccessItem.class, result.get(11).getClass()); + Assertions.assertEquals("0", ((ResponseSizeAccessItem) result.get(11)).getZeroBytes()); + Assertions.assertEquals(ResponseSizeAccessItem.class, result.get(12).getClass()); + Assertions.assertEquals("-", ((ResponseSizeAccessItem) result.get(12)).getZeroBytes()); + Assertions.assertEquals(FirstLineOfRequestAccessItem.class, result.get(13).getClass()); + Assertions.assertEquals(UrlPathAccessItem.class, result.get(14).getClass()); + Assertions.assertEquals(QueryStringAccessItem.class, result.get(15).getClass()); + Assertions.assertEquals(UrlPathAccessItem.class, result.get(16).getClass()); + Assertions.assertEquals(QueryStringAccessItem.class, result.get(17).getClass()); + Assertions.assertEquals(UrlPathWithQueryAccessItem.class, result.get(18).getClass()); + Assertions.assertEquals(RequestProtocolAccessItem.class, result.get(19).getClass()); + Assertions.assertEquals(ConfigurableDatetimeAccessItem.class, result.get(20).getClass()); + Assertions.assertEquals(ConfigurableDatetimeAccessItem.DEFAULT_DATETIME_PATTERN, ((ConfigurableDatetimeAccessItem) result.get(20)).getPattern()); - assertEquals(ConfigurableDatetimeAccessItem.DEFAULT_LOCALE, ((ConfigurableDatetimeAccessItem) result.get(20)).getLocale()); - assertEquals(TimeZone.getDefault(), ((ConfigurableDatetimeAccessItem) result.get(20)).getTimezone()); - assertEquals("yyyy MM dd HH:mm:ss zzz", ((ConfigurableDatetimeAccessItem) result.get(21)).getPattern()); - assertEquals(ConfigurableDatetimeAccessItem.DEFAULT_LOCALE, ((ConfigurableDatetimeAccessItem) result.get(21)).getLocale()); - assertEquals(TimeZone.getDefault(), ((ConfigurableDatetimeAccessItem) result.get(21)).getTimezone()); - assertEquals("yyyy MM dd HH:mm:ss", ((ConfigurableDatetimeAccessItem) result.get(22)).getPattern()); - assertEquals(Locale.forLanguageTag("en-US"), ((ConfigurableDatetimeAccessItem) result.get(22)).getLocale()); - assertEquals(TimeZone.getTimeZone("GMT+0"), ((ConfigurableDatetimeAccessItem) result.get(22)).getTimezone()); - assertEquals(RequestHeaderAccessItem.class, result.get(23).getClass()); - assertEquals("incoming-header", ((RequestHeaderAccessItem) result.get(23)).getVarName()); - assertEquals(ResponseHeaderAccessItem.class, result.get(24).getClass()); - assertEquals("outgoing-header", ((ResponseHeaderAccessItem) result.get(24)).getVarName()); - assertEquals(CookieAccessItem.class, result.get(25).getClass()); - assertEquals("cookie", ((CookieAccessItem) result.get(25)).getVarName()); - assertEquals(TraceIdAccessItem.class, result.get(26).getClass()); - assertEquals(InvocationContextAccessItem.class, result.get(27).getClass()); - assertEquals("ctx", ((InvocationContextAccessItem) result.get(27)).getVarName()); - assertEquals(TransportAccessItem.class, result.get(28).getClass()); + Assertions.assertEquals(ConfigurableDatetimeAccessItem.DEFAULT_LOCALE, ((ConfigurableDatetimeAccessItem) result.get(20)).getLocale()); + Assertions.assertEquals(TimeZone.getDefault(), ((ConfigurableDatetimeAccessItem) result.get(20)).getTimezone()); + Assertions.assertEquals("yyyy MM dd HH:mm:ss zzz", ((ConfigurableDatetimeAccessItem) result.get(21)).getPattern()); + Assertions.assertEquals(ConfigurableDatetimeAccessItem.DEFAULT_LOCALE, ((ConfigurableDatetimeAccessItem) result.get(21)).getLocale()); + Assertions.assertEquals(TimeZone.getDefault(), ((ConfigurableDatetimeAccessItem) result.get(21)).getTimezone()); + Assertions.assertEquals("yyyy MM dd HH:mm:ss", ((ConfigurableDatetimeAccessItem) result.get(22)).getPattern()); + Assertions.assertEquals(Locale.forLanguageTag("en-US"), ((ConfigurableDatetimeAccessItem) result.get(22)).getLocale()); + Assertions.assertEquals(TimeZone.getTimeZone("GMT+0"), ((ConfigurableDatetimeAccessItem) result.get(22)).getTimezone()); + Assertions.assertEquals(RequestHeaderAccessItem.class, result.get(23).getClass()); + Assertions.assertEquals("incoming-header", ((RequestHeaderAccessItem) result.get(23)).getVarName()); + Assertions.assertEquals(ResponseHeaderAccessItem.class, result.get(24).getClass()); + Assertions.assertEquals("outgoing-header", ((ResponseHeaderAccessItem) result.get(24)).getVarName()); + Assertions.assertEquals(CookieAccessItem.class, result.get(25).getClass()); + Assertions.assertEquals("cookie", ((CookieAccessItem) result.get(25)).getVarName()); + Assertions.assertEquals(TraceIdAccessItem.class, result.get(26).getClass()); + Assertions.assertEquals(InvocationContextAccessItem.class, result.get(27).getClass()); + Assertions.assertEquals("ctx", ((InvocationContextAccessItem) result.get(27)).getVarName()); + Assertions.assertEquals(TransportAccessItem.class, result.get(28).getClass()); } @Test public void testParsePattern() { String pattern = " %m cs-uri-stem %{response-header}o "; List> result = logPatternParser.parsePattern(pattern); - assertEquals(7, result.size()); + Assertions.assertEquals(7, result.size()); StringBuilder stringBuilder = new StringBuilder(); result.get(0).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); - assertEquals(HttpMethodAccessItem.class, result.get(1).getClass()); + Assertions.assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(HttpMethodAccessItem.class, result.get(1).getClass()); stringBuilder = new StringBuilder(); result.get(2).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); - assertEquals(UrlPathAccessItem.class, result.get(3).getClass()); + Assertions.assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(UrlPathAccessItem.class, result.get(3).getClass()); stringBuilder = new StringBuilder(); result.get(4).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); - assertEquals(ResponseHeaderAccessItem.class, result.get(5).getClass()); - assertEquals("response-header", ((ResponseHeaderAccessItem) result.get(5)).getVarName()); + Assertions.assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(ResponseHeaderAccessItem.class, result.get(5).getClass()); + Assertions.assertEquals("response-header", ((ResponseHeaderAccessItem) result.get(5)).getVarName()); stringBuilder = new StringBuilder(); result.get(6).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(" ", stringBuilder.toString()); } @Test public void testParsePatternWithNoBlank() { String pattern = "%mcs-uri-stem%{response-header}o"; List> result = logPatternParser.parsePattern(pattern); - assertEquals(3, result.size()); + Assertions.assertEquals(3, result.size()); - assertEquals(HttpMethodAccessItem.class, result.get(0).getClass()); - assertEquals(UrlPathAccessItem.class, result.get(1).getClass()); - assertEquals(ResponseHeaderAccessItem.class, result.get(2).getClass()); - assertEquals("response-header", ((ResponseHeaderAccessItem) result.get(2)).getVarName()); + Assertions.assertEquals(HttpMethodAccessItem.class, result.get(0).getClass()); + Assertions.assertEquals(UrlPathAccessItem.class, result.get(1).getClass()); + Assertions.assertEquals(ResponseHeaderAccessItem.class, result.get(2).getClass()); + Assertions.assertEquals("response-header", ((ResponseHeaderAccessItem) result.get(2)).getVarName()); } @Test public void testParsePatternComplex() { String pattern = "%m cs-uri-stem %{response-header}o abc cs-uri-query %s%{request} header}i plain cs-uri"; List> result = logPatternParser.parsePattern(pattern); - assertEquals(12, result.size()); + Assertions.assertEquals(12, result.size()); - assertEquals(HttpMethodAccessItem.class, result.get(0).getClass()); + Assertions.assertEquals(HttpMethodAccessItem.class, result.get(0).getClass()); StringBuilder stringBuilder = new StringBuilder(); result.get(1).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); - assertEquals(UrlPathAccessItem.class, result.get(2).getClass()); + Assertions.assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(UrlPathAccessItem.class, result.get(2).getClass()); stringBuilder = new StringBuilder(); result.get(3).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); - assertEquals(ResponseHeaderAccessItem.class, result.get(4).getClass()); - assertEquals("response-header", ((ResponseHeaderAccessItem) result.get(4)).getVarName()); + Assertions.assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(ResponseHeaderAccessItem.class, result.get(4).getClass()); + Assertions.assertEquals("response-header", ((ResponseHeaderAccessItem) result.get(4)).getVarName()); stringBuilder = new StringBuilder(); result.get(5).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" abc ", stringBuilder.toString()); - assertEquals(QueryStringAccessItem.class, result.get(6).getClass()); + Assertions.assertEquals(" abc ", stringBuilder.toString()); + Assertions.assertEquals(QueryStringAccessItem.class, result.get(6).getClass()); stringBuilder = new StringBuilder(); result.get(7).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" ", stringBuilder.toString()); - assertEquals(HttpStatusAccessItem.class, result.get(8).getClass()); - assertEquals(RequestHeaderAccessItem.class, result.get(9).getClass()); - assertEquals("request} header", ((RequestHeaderAccessItem) result.get(9)).getVarName()); + Assertions.assertEquals(" ", stringBuilder.toString()); + Assertions.assertEquals(HttpStatusAccessItem.class, result.get(8).getClass()); + Assertions.assertEquals(RequestHeaderAccessItem.class, result.get(9).getClass()); + Assertions.assertEquals("request} header", ((RequestHeaderAccessItem) result.get(9)).getVarName()); stringBuilder = new StringBuilder(); result.get(10).appendServerFormattedItem(accessLogEvent, stringBuilder); - assertEquals(" plain ", stringBuilder.toString()); - assertEquals(UrlPathWithQueryAccessItem.class, result.get(11).getClass()); + Assertions.assertEquals(" plain ", stringBuilder.toString()); + Assertions.assertEquals(UrlPathWithQueryAccessItem.class, result.get(11).getClass()); } - Comparator comparator = VertxRestAccessLogPatternParser.accessLogItemMetaComparator; + final Comparator comparator = VertxRestAccessLogPatternParser.accessLogItemMetaComparator; /** * one factor test */ @Test public void testCompareMetaSimple() { - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta(null, null, null, 0), new VertxRestAccessLogItemMeta(null, null, null, 1) ) < 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta(null, "}abc", null, 0), new VertxRestAccessLogItemMeta(null, null, null, 0) ) < 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta(null, "}abc", null, 0), new VertxRestAccessLogItemMeta(null, "}de", null, 0) ) < 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta(null, "}abc", null, 0), new VertxRestAccessLogItemMeta(null, "}ab", null, 0) ) < 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta("%abc", null, null, 0), new VertxRestAccessLogItemMeta("%de", null, null, 0) ) < 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta("%abc", null, null, 0), new VertxRestAccessLogItemMeta("%ab", null, null, 0) ) < 0 ); - Assert.assertEquals(0, comparator.compare( + Assertions.assertEquals(0, comparator.compare( new VertxRestAccessLogItemMeta("%abc", null, null, 0), new VertxRestAccessLogItemMeta("%abc", null, null, 0) )); @@ -261,25 +255,25 @@ public void testCompareMetaSimple() { */ @Test public void testCompareMetaComplex() { - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta("%bcd", "}ab", null, 0), new VertxRestAccessLogItemMeta("%abc", "}abc", null, 0) ) > 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta("%abc", null, null, 0), new VertxRestAccessLogItemMeta("%bcd", "}ab", null, 0) ) > 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta("%bcd", "}abc", null, 0), new VertxRestAccessLogItemMeta("%abc", "}abc", null, 0) ) > 0 ); - Assert.assertTrue( + Assertions.assertTrue( comparator.compare( new VertxRestAccessLogItemMeta("%abc", "}abc", null, 1), new VertxRestAccessLogItemMeta("%ab", "}ab", null, 0) @@ -289,17 +283,17 @@ public void testCompareMetaComplex() { @Test public void testComparePlaceholderString() { - Assert.assertTrue( + Assertions.assertTrue( VertxRestAccessLogPatternParser.comparePlaceholderString("abc", "bbc") < 0 ); - Assert.assertTrue( + Assertions.assertTrue( VertxRestAccessLogPatternParser.comparePlaceholderString("abc", "ab") < 0 ); - Assert.assertEquals(0, VertxRestAccessLogPatternParser.comparePlaceholderString("abc", "abc")); - Assert.assertTrue( + Assertions.assertEquals(0, VertxRestAccessLogPatternParser.comparePlaceholderString("abc", "abc")); + Assertions.assertTrue( VertxRestAccessLogPatternParser.comparePlaceholderString("bbc", "abc") > 0 ); - Assert.assertTrue( + Assertions.assertTrue( VertxRestAccessLogPatternParser.comparePlaceholderString("ab", "abc") > 0 ); } @@ -316,47 +310,53 @@ public void testExtendedVertxRestAccessLogItemCreator() { metaList0.add(new VertxRestAccessLogItemMeta("%0", "}abc", null, 1)); metaList0.add(new VertxRestAccessLogItemMeta("%m", null, null)); - new MockUp() { - @Mock - List loadVertxRestLogItemMeta() { - List metaList = new ArrayList<>(1); - CompositeVertxRestAccessLogItemMeta compositeMeta0 = new CompositeVertxRestAccessLogItemMeta() { - @Override - public List getAccessLogItemMetas() { - return metaList0; - } - }; - CompositeVertxRestAccessLogItemMeta compositeMeta1 = new CompositeVertxRestAccessLogItemMeta() { - @Override - public List getAccessLogItemMetas() { - return metaList1; - } - }; - metaList.add(compositeMeta0); - metaList.add(compositeMeta1); - metaList.add(new VertxRestAccessLogItemMeta("%{", null, null)); - return metaList; + CompositeVertxRestAccessLogItemMeta compositeMeta0 = new CompositeVertxRestAccessLogItemMeta() { + @Override + public List getAccessLogItemMetas() { + return metaList0; + } + }; + CompositeVertxRestAccessLogItemMeta compositeMeta1 = new CompositeVertxRestAccessLogItemMeta() { + @Override + public List getAccessLogItemMetas() { + return metaList1; } }; - VertxRestAccessLogPatternParser parser = new VertxRestAccessLogPatternParser(); + List metaList = new ArrayList<>(1); + metaList.add(compositeMeta0); + metaList.add(compositeMeta1); + metaList.add(new VertxRestAccessLogItemMeta("%{", null, null)); + + VertxRestAccessLogPatternParser parser = Mockito.mock(VertxRestAccessLogPatternParser.class); + Mockito.when(parser.getMetaList()).thenAnswer(invocation -> { + List resultMetaList = new ArrayList<>(); + for (VertxRestAccessLogItemMeta meta : metaList) { + if (CompositeVertxRestAccessLogItemMeta.class.isAssignableFrom(meta.getClass())) { + resultMetaList.addAll(((CompositeVertxRestAccessLogItemMeta) meta).getAccessLogItemMetas()); + } else { + resultMetaList.add(meta); + } + } + VertxRestAccessLogPatternParser.sortAccessLogItemMeta(resultMetaList); + return resultMetaList; + }); - List accessLogItemMetaList = - Deencapsulation.getField(parser, "metaList"); + List accessLogItemMetaList = parser.getMetaList(); - assertEquals(7, accessLogItemMetaList.size()); - assertEquals("%_", accessLogItemMetaList.get(0).getPrefix()); - assertEquals("%a", accessLogItemMetaList.get(1).getPrefix()); - assertEquals("}abc", accessLogItemMetaList.get(1).getSuffix()); - assertEquals("%{", accessLogItemMetaList.get(2).getPrefix()); - assertEquals("}abc", accessLogItemMetaList.get(2).getSuffix()); - assertEquals("%{", accessLogItemMetaList.get(3).getPrefix()); - assertEquals("}a", accessLogItemMetaList.get(3).getSuffix()); - assertEquals("%m", accessLogItemMetaList.get(4).getPrefix()); - assertNull(accessLogItemMetaList.get(4).getSuffix()); - assertEquals("%{", accessLogItemMetaList.get(5).getPrefix()); - assertNull(accessLogItemMetaList.get(5).getSuffix()); - assertEquals("%0", accessLogItemMetaList.get(6).getPrefix()); - assertEquals("}abc", accessLogItemMetaList.get(6).getSuffix()); + Assertions.assertEquals(7, accessLogItemMetaList.size()); + Assertions.assertEquals("%_", accessLogItemMetaList.get(0).getPrefix()); + Assertions.assertEquals("%a", accessLogItemMetaList.get(1).getPrefix()); + Assertions.assertEquals("}abc", accessLogItemMetaList.get(1).getSuffix()); + Assertions.assertEquals("%{", accessLogItemMetaList.get(2).getPrefix()); + Assertions.assertEquals("}abc", accessLogItemMetaList.get(2).getSuffix()); + Assertions.assertEquals("%{", accessLogItemMetaList.get(3).getPrefix()); + Assertions.assertEquals("}a", accessLogItemMetaList.get(3).getSuffix()); + Assertions.assertEquals("%m", accessLogItemMetaList.get(4).getPrefix()); + Assertions.assertNull(accessLogItemMetaList.get(4).getSuffix()); + Assertions.assertEquals("%{", accessLogItemMetaList.get(5).getPrefix()); + Assertions.assertNull(accessLogItemMetaList.get(5).getSuffix()); + Assertions.assertEquals("%0", accessLogItemMetaList.get(6).getPrefix()); + Assertions.assertEquals("}abc", accessLogItemMetaList.get(6).getSuffix()); } } diff --git a/common/common-access-log/src/test/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta b/common/common-access-log/src/test/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta index 501ac43ee58..74f9ee4cb24 100644 --- a/common/common-access-log/src/test/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta +++ b/common/common-access-log/src/test/resources/META-INF/services/org.apache.servicecomb.common.accessLog.core.parser.VertxRestAccessLogItemMeta @@ -16,4 +16,4 @@ # org.apache.servicecomb.common.accessLog.core.parser.impl.TestCompositeExtendedAccessLogItemMeta -org.apache.servicecomb.common.accessLog.core.parser.impl.TestSingleExtendedAccessLogItemMeta \ No newline at end of file +org.apache.servicecomb.common.accessLog.core.parser.impl.TestSingleExtendedAccessLogItemMeta diff --git a/common/common-protobuf/pom.xml b/common/common-protobuf/pom.xml index 97e78f380be..5b7ac5fcf7c 100644 --- a/common/common-protobuf/pom.xml +++ b/common/common-protobuf/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb common - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT common-protobuf Java Chassis::Common::Protobuf @@ -31,24 +31,26 @@ org.apache.servicecomb java-chassis-core - - org.apache.servicecomb - swagger-invocation-core - org.apache.servicecomb foundation-protobuf + + + com.google.protobuf + protobuf-java + test + - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test @@ -61,4 +63,29 @@ foundation-test-scaffolding + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${protobuf-maven-plugin.version} + + com.google.protobuf:protoc:${protoc3-maven-plugin.version}:exe:${os.detected.classifier} + true + grpc-java + io.grpc:protoc-gen-grpc-java:${protoc-gen-grpc-java-plugin.version}:exe:${os.detected.classifier} + + + + + generate-test-sources + + test-compile + + + + + + diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java index 2f0579fb760..6c12da844de 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/OperationProtobuf.java @@ -21,9 +21,6 @@ import java.util.Map; import java.util.Map.Entry; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.Status.Family; - import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.foundation.protobuf.ProtoMapper; @@ -33,9 +30,10 @@ import com.fasterxml.jackson.databind.JavaType; import io.protostuff.compiler.model.Message; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status.Family; -@SuppressWarnings("rawtypes") -public class OperationProtobuf { +public final class OperationProtobuf { private RequestRootSerializer requestRootSerializer; private RequestRootDeserializer requestRootDeserializer; @@ -101,10 +99,10 @@ private void initConsumerRequestCodec(Invocation invocation, Message requestMess requestRootSerializer = new RequestRootSerializer( mapper.createRootSerializer(requestMessage, Object.class), true, false); } else { - if (invocation.getOperationMeta().getSwaggerOperation().getParameters().isEmpty()) { + if (invocation.getOperationMeta().parameterCount() == 0) { requestRootSerializer = new RequestRootSerializer(mapper.createRootSerializer(requestMessage, Object.class), false, false); - } else if (invocation.getOperationMeta().getSwaggerOperation().getParameters().size() == 1) { + } else if (invocation.getOperationMeta().parameterCount() == 1) { requestRootSerializer = new RequestRootSerializer(mapper.createRootSerializer(requestMessage, Object.class), false, true); } else { @@ -118,7 +116,7 @@ private void initRequestCodec(ScopedProtobufSchemaManager scopedProtobufSchemaMa ProtoMapper mapper = scopedProtobufSchemaManager.getOrCreateProtoMapper(invocation.getSchemaMeta()); Message requestMessage = mapper.getRequestMessage(invocation.getOperationMeta().getOperationId()); - if (!invocation.isConsumer()) { + if (invocation.isProducer()) { initProducerRequestCodec(invocation, requestMessage, mapper); } else { initConsumerRequestCodec(invocation, requestMessage, mapper); @@ -168,7 +166,7 @@ private void initResponseCodec(ScopedProtobufSchemaManager scopedProtobufSchemaM Message responseMessage = mapper.getResponseMessage(invocation.getOperationMeta().getOperationId()); JavaType responseType = invocation.findResponseType(Status.OK.getStatusCode()); - if (!invocation.isConsumer()) { + if (invocation.isProducer()) { initProviderResponseCode(responseMessage, mapper, responseType); } else { initConsumerResponseCode(responseMessage, mapper, responseType); diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java index f0b0fd267c9..09ccb9d70cd 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ProtobufManager.java @@ -19,8 +19,9 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager; import org.apache.servicecomb.core.Invocation; @@ -68,8 +69,7 @@ public boolean equals(Object o) { if (!uniqueOperationId.equals(that.uniqueOperationId)) { return false; } - return responseType != null ? responseType.equals(that.responseType) - : that.responseType == null; + return Objects.equals(responseType, that.responseType); } @Override diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java index 00f2ba95c05..ef4e75befdb 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootDeserializer.java @@ -24,11 +24,11 @@ import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper; public class RequestRootDeserializer { - private boolean wrapArgument; + private final boolean wrapArgument; - private String parameterName; + private final String parameterName; - private RootDeserializer rootDeserializer; + private final RootDeserializer rootDeserializer; public RequestRootDeserializer(RootDeserializer rootDeserializer, boolean wrapArgument, String parameterName) { this.rootDeserializer = rootDeserializer; diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootSerializer.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootSerializer.java index ab344454d4e..ac5763d9b57 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootSerializer.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/RequestRootSerializer.java @@ -24,16 +24,16 @@ import io.vertx.core.json.JsonObject; public class RequestRootSerializer { - private RootSerializer rootSerializer; + private final RootSerializer rootSerializer; - private boolean noTypesInfo; + private final boolean noTypesInfo; - private boolean isWrap; + private final boolean isWrap; - public RequestRootSerializer(RootSerializer serializer, boolean isWrapp, boolean noTypesInfo) { + public RequestRootSerializer(RootSerializer serializer, boolean isWrap, boolean noTypesInfo) { this.rootSerializer = serializer; this.noTypesInfo = noTypesInfo; - this.isWrap = isWrapp; + this.isWrap = isWrap; } @SuppressWarnings("unchecked") diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java index 36139cdf40f..e64e45d8c62 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootDeserializer.java @@ -26,9 +26,9 @@ import com.fasterxml.jackson.databind.JavaType; public class ResponseRootDeserializer { - private RootDeserializer rootDeserializer; + private final RootDeserializer rootDeserializer; - private boolean empty; + private final boolean empty; public ResponseRootDeserializer(RootDeserializer rootDeserializer, boolean empty) { this.rootDeserializer = rootDeserializer; diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootSerializer.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootSerializer.java index d7034ca93de..8af18a4a016 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootSerializer.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/definition/ResponseRootSerializer.java @@ -23,16 +23,16 @@ import org.apache.servicecomb.foundation.protobuf.RootSerializer; public class ResponseRootSerializer { - private RootSerializer rootSerializer; + private final RootSerializer rootSerializer; - private boolean noTypesInfo; + private final boolean noTypesInfo; - private boolean isWrap; + private final boolean isWrap; - public ResponseRootSerializer(RootSerializer serializer, boolean isWrapp, boolean noTypesInfo) { + public ResponseRootSerializer(RootSerializer serializer, boolean isWrap, boolean noTypesInfo) { this.rootSerializer = serializer; this.noTypesInfo = noTypesInfo; - this.isWrap = isWrapp; + this.isWrap = isWrap; } public byte[] serialize(Object value) throws IOException { diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/BodyParameterAdapter.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/BodyParameterAdapter.java deleted file mode 100644 index 9dee93cc370..00000000000 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/BodyParameterAdapter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.codec.protobuf.internal.converter; - -import java.util.Collections; -import java.util.List; - -import io.swagger.models.ArrayModel; -import io.swagger.models.Model; -import io.swagger.models.ModelImpl; -import io.swagger.models.RefModel; -import io.swagger.models.parameters.BodyParameter; -import io.swagger.models.properties.ObjectProperty; -import io.swagger.models.properties.Property; - -public class BodyParameterAdapter implements SwaggerTypeAdapter { - private final Model model; - - public BodyParameterAdapter(BodyParameter parameter) { - this.model = parameter.getSchema(); - } - - @Override - public String getRefType() { - if (model instanceof RefModel) { - return ((RefModel) model).getSimpleRef(); - } - - return null; - } - - @Override - public Property getArrayItem() { - if (model instanceof ArrayModel) { - return ((ArrayModel) model).getItems(); - } - - return null; - } - - @Override - public Property getMapItem() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getAdditionalProperties(); - } - - return null; - } - - @Override - public List getEnum() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getEnum(); - } - - return Collections.emptyList(); - } - - @Override - public String getType() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getType(); - } - - return null; - } - - @Override - public String getFormat() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getFormat(); - } - - return null; - } - - @Override - public boolean isJavaLangObject() { - if (model instanceof ModelImpl) { - ModelImpl modelImpl = (ModelImpl) model; - return (ObjectProperty.TYPE.equals(modelImpl.getType()) - && modelImpl.getProperties() == null - && modelImpl.getName() == null); - } - - return false; - } -} diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ModelAdapter.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ModelAdapter.java deleted file mode 100644 index 78dab6bc453..00000000000 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ModelAdapter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.codec.protobuf.internal.converter; - -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import io.swagger.models.ArrayModel; -import io.swagger.models.Model; -import io.swagger.models.ModelImpl; -import io.swagger.models.RefModel; -import io.swagger.models.properties.ObjectProperty; -import io.swagger.models.properties.Property; - -public class ModelAdapter implements SwaggerTypeAdapter { - private final Model model; - - public ModelAdapter(Model model) { - this.model = model; - } - - @Override - public String getRefType() { - if (model instanceof RefModel) { - return ((RefModel) model).getSimpleRef(); - } - - return null; - } - - @Override - public Property getArrayItem() { - if (model instanceof ArrayModel) { - return ((ArrayModel) model).getItems(); - } - - return null; - } - - @Override - public Property getMapItem() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getAdditionalProperties(); - } - - return null; - } - - @Override - public List getEnum() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getEnum(); - } - - return Collections.emptyList(); - } - - @Override - public String getType() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getType(); - } - - return null; - } - - @Override - public String getFormat() { - if (model instanceof ModelImpl) { - return ((ModelImpl) model).getFormat(); - } - - return null; - } - - @Override - public boolean isJavaLangObject() { - if (model instanceof ModelImpl) { - ModelImpl modelImpl = (ModelImpl) model; - return Objects.equals(ObjectProperty.TYPE, modelImpl.getType()) - && modelImpl.getProperties() == null - && modelImpl.getName() == null; - } - - return false; - } -} diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/PropertyAdapter.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/PropertyAdapter.java deleted file mode 100644 index 4fc8ef15256..00000000000 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/PropertyAdapter.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.codec.protobuf.internal.converter; - -import java.util.Collections; -import java.util.List; - -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.MapProperty; -import io.swagger.models.properties.ObjectProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.RefProperty; -import io.swagger.models.properties.StringProperty; - -public class PropertyAdapter implements SwaggerTypeAdapter { - private final Property property; - - public PropertyAdapter(Property property) { - this.property = property; - } - - @Override - public String getRefType() { - if (property instanceof RefProperty) { - return ((RefProperty) property).getSimpleRef(); - } - - return null; - } - - @Override - public Property getArrayItem() { - if (property instanceof ArrayProperty) { - return ((ArrayProperty) property).getItems(); - } - - return null; - } - - @Override - public Property getMapItem() { - if (property instanceof MapProperty) { - return ((MapProperty) property).getAdditionalProperties(); - } - - return null; - } - - @Override - public List getEnum() { - if (property instanceof StringProperty) { - return ((StringProperty) property).getEnum(); - } - - return Collections.emptyList(); - } - - @Override - public String getType() { - return property.getType(); - } - - @Override - public String getFormat() { - return property.getFormat(); - } - - @Override - public boolean isJavaLangObject() { - return property instanceof ObjectProperty; - } -} diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ProtoMethod.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ProtoMethod.java index e8d8a093c13..885dae823c9 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ProtoMethod.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/ProtoMethod.java @@ -18,19 +18,20 @@ import java.util.HashMap; import java.util.Map; - -import javax.ws.rs.core.Response.Status; +import java.util.Map.Entry; import org.apache.servicecomb.swagger.invocation.context.HttpStatus; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.ws.rs.core.Response.Status; + public class ProtoMethod { private String argTypeName; @JsonProperty // key is status - private Map responses = new HashMap<>(); + private final Map responses = new HashMap<>(); private ProtoResponse defaultResponse; @@ -62,6 +63,14 @@ public ProtoResponse findResponse(int statusCode) { return response; } + if (statusCode == Status.OK.getStatusCode()) { + for (Entry code : responses.entrySet()) { + if (HttpStatus.isSuccess(code.getKey())) { + return responses.get(code.getKey()); + } + } + } + if (HttpStatus.isSuccess(statusCode)) { return responses.get(Status.OK.getStatusCode()); } diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SchemaSwaggerTypeAdapter.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SchemaSwaggerTypeAdapter.java new file mode 100644 index 00000000000..68608e3db87 --- /dev/null +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SchemaSwaggerTypeAdapter.java @@ -0,0 +1,65 @@ +/* + * 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.codec.protobuf.internal.converter; + +import java.util.List; + +import io.swagger.v3.oas.models.media.Schema; + +public class SchemaSwaggerTypeAdapter implements SwaggerTypeAdapter { + private final Schema schema; + + public SchemaSwaggerTypeAdapter(Schema schema) { + this.schema = schema; + } + + @Override + public String getRefType() { + return schema.get$ref(); + } + + @Override + public Schema getArrayItem() { + return schema.getItems(); + } + + @Override + public Schema getMapItem() { + return (Schema) schema.getAdditionalProperties(); + } + + @Override + @SuppressWarnings("unchecked") + public List getEnum() { + return (List) schema.getEnum(); + } + + @Override + public String getType() { + return schema.getType(); + } + + @Override + public String getFormat() { + return schema.getFormat(); + } + + @Override + public boolean isJavaLangObject() { + return "object".equals(getType()); + } +} diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SerializableParameterAdapter.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SerializableParameterAdapter.java deleted file mode 100644 index 66ba8bda3ca..00000000000 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SerializableParameterAdapter.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.codec.protobuf.internal.converter; - -import java.util.List; - -import io.swagger.models.parameters.SerializableParameter; -import io.swagger.models.properties.Property; - -public class SerializableParameterAdapter implements SwaggerTypeAdapter { - private final SerializableParameter parameter; - - public SerializableParameterAdapter(SerializableParameter parameter) { - this.parameter = parameter; - } - - @Override - public String getRefType() { - return null; - } - - @Override - public Property getArrayItem() { - if ("array".equals(parameter.getType())) { - return parameter.getItems(); - } - - return null; - } - - @Override - public Property getMapItem() { - return null; - } - - @Override - public List getEnum() { - return parameter.getEnum(); - } - - @Override - public String getType() { - return parameter.getType(); - } - - @Override - public String getFormat() { - return parameter.getFormat(); - } - - @Override - public boolean isJavaLangObject() { - return false; - } -} diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerToProtoGenerator.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerToProtoGenerator.java index 841bab20c01..482808ab816 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerToProtoGenerator.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerToProtoGenerator.java @@ -28,12 +28,10 @@ import java.util.Map.Entry; import java.util.Set; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; - import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst; import org.apache.servicecomb.foundation.protobuf.internal.parser.ProtoParser; +import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,22 +39,25 @@ import io.protostuff.compiler.model.Message; import io.protostuff.compiler.model.Proto; -import io.swagger.models.Model; -import io.swagger.models.ModelImpl; -import io.swagger.models.Operation; -import io.swagger.models.Path; -import io.swagger.models.Response; -import io.swagger.models.Swagger; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.PathItem; +import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.responses.ApiResponse; import io.vertx.core.json.Json; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response.Status; +@SuppressWarnings({"rawtypes", "unchecked"}) public class SwaggerToProtoGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerToProtoGenerator.class); private final String protoPackage; - private final Swagger swagger; + private final OpenAPI swagger; private final StringBuilder msgStringBuilder = new StringBuilder(); @@ -70,7 +71,7 @@ public class SwaggerToProtoGenerator { // not java package // better to be: app_${app}.mid_{microservice}.sid_{schemaId} - public SwaggerToProtoGenerator(String protoPackage, Swagger swagger) { + public SwaggerToProtoGenerator(String protoPackage, OpenAPI swagger) { this.protoPackage = escapePackageName(protoPackage); this.swagger = swagger; } @@ -78,22 +79,19 @@ public SwaggerToProtoGenerator(String protoPackage, Swagger swagger) { public Proto convert() { convertDefinitions(); convertOperations(); - for (; ; ) { + do { List oldPending = pending; pending = new ArrayList<>(); for (Runnable runnable : oldPending) { runnable.run(); } - if (pending.isEmpty()) { - break; - } - } + } while (!pending.isEmpty()); return createProto(); } public static String escapePackageName(String name) { - return name.replaceAll("[\\-\\:]", "_"); + return name.replaceAll("[\\-:]", "_"); } public static String escapeMessageName(String name) { @@ -101,34 +99,31 @@ public static String escapeMessageName(String name) { } public static boolean isValidEnum(String name) { - if (name.contains(".") || name.contains("-")) { - return false; - } - return true; + return !name.contains(".") && !name.contains("-"); } private void convertDefinitions() { - if (swagger.getDefinitions() == null) { + if (swagger.getComponents() == null || swagger.getComponents().getSchemas() == null) { return; } - for (Entry entry : swagger.getDefinitions().entrySet()) { - convertDefinition(entry.getKey(), (ModelImpl) entry.getValue()); + for (Entry entry : swagger.getComponents().getSchemas().entrySet()) { + convertDefinition(entry.getKey(), entry.getValue()); } } @SuppressWarnings("unchecked") - private void convertDefinition(String modelName, ModelImpl model) { - Map properties = model.getProperties(); + private void convertDefinition(String modelName, Schema model) { + Map properties = model.getProperties(); if (properties == null) { // it's a empty message properties = Collections.emptyMap(); } - createMessage(modelName, (Map) (Object) properties); + createMessage(modelName, properties); } - private void createMessage(String protoName, Map properties, String... annotations) { + private void createMessage(String protoName, Map properties, String... annotations) { if (!messages.add(protoName)) { // already created return; @@ -140,8 +135,8 @@ private void createMessage(String protoName, Map properties, Str } appendLine(msgStringBuilder, "message %s {", protoName); int tag = 1; - for (Entry entry : properties.entrySet()) { - Object property = entry.getValue(); + for (Entry entry : properties.entrySet()) { + Schema property = entry.getValue(); String propertyType = convertSwaggerType(property); appendLine(msgStringBuilder, " %s %s = %d;", propertyType, entry.getKey(), tag); @@ -177,10 +172,10 @@ private String convertSwaggerType(Object swaggerType) { type = adapter.getRefType(); if (type != null) { - return type; + return type.substring(Components.COMPONENTS_SCHEMAS_REF.length()); } - Property itemProperty = adapter.getArrayItem(); + Schema itemProperty = adapter.getArrayItem(); if (itemProperty != null) { return "repeated " + convertArrayOrMapItem(itemProperty); } @@ -200,7 +195,7 @@ private String convertSwaggerType(Object swaggerType) { Json.encode(swaggerType))); } - private String convertArrayOrMapItem(Property itemProperty) { + private String convertArrayOrMapItem(Schema itemProperty) { SwaggerTypeAdapter itemAdapter = SwaggerTypeAdapter.create(itemProperty); // List>, need to wrap if (itemAdapter.getArrayItem() != null) { @@ -219,7 +214,7 @@ private String convertArrayOrMapItem(Property itemProperty) { return convertSwaggerType(itemProperty); } - private String generateWrapPropertyName(String prefix, Property property) { + private String generateWrapPropertyName(String prefix, Schema property) { SwaggerTypeAdapter adapter = SwaggerTypeAdapter.create(property); // List>, need to wrap if (adapter.getArrayItem() != null) { @@ -235,14 +230,14 @@ private String generateWrapPropertyName(String prefix, Property property) { return prefix + StringUtils.capitalize(escapeMessageName(convertSwaggerType(adapter))); } - private void wrapPropertyToMessage(String protoName, Object property) { + private void wrapPropertyToMessage(String protoName, Schema property) { createMessage(protoName, Collections.singletonMap("value", property), ProtoConst.ANNOTATION_WRAP_PROPERTY); } private String tryFindEnumType(List enums) { if (enums != null && !enums.isEmpty()) { String strEnums = enums.toString(); - String enumName = "Enum_" + Hashing.sha256().hashString(strEnums, StandardCharsets.UTF_8).toString(); + String enumName = "Enum_" + Hashing.sha256().hashString(strEnums, StandardCharsets.UTF_8); pending.add(() -> createEnum(enumName, enums)); return enumName; } @@ -269,46 +264,32 @@ private void createEnum(String enumName, List enums) { private String findBaseType(String swaggerType, String swaggerFmt) { String key = swaggerType + ":" + swaggerFmt; - switch (key) { - case "boolean:null": - return "bool"; - // there is no int8/int16 in protobuf - case "integer:null": - return "int64"; - case "integer:int8": - case "integer:int16": - case "integer:int32": - return "int32"; - case "integer:int64": - return "int64"; - case "number:null": - return "double"; - case "number:float": - return "float"; - case "number:double": - return "double"; - case "string:null": - return "string"; - case "string:byte": - return "bytes"; - case "string:date": // LocalDate - case "string:date-time": // Date - return "int64"; - case "file:null": - throw new IllegalStateException("not support swagger type: " + swaggerType); - } - return null; + return switch (key) { + case "boolean:null" -> "bool"; + case "integer:int32" -> "sint32"; + case "integer:int64" -> "sint64"; + case "integer:null" -> "string"; // BigInteger like values + case "number:double" -> "double"; + case "number:float" -> "float"; + case "number:null" -> "string"; // BigDecimal like values + case "string:null" -> "string"; + case "string:byte" -> "bytes"; + case "string:date" -> "int64"; + case "string:date-time" -> "int64"; + case "string:binary" -> throw new IllegalArgumentException("proto buffer not support file upload/download"); + default -> null; + }; } private void convertOperations() { - Map paths = swagger.getPaths(); + Paths paths = swagger.getPaths(); if (paths == null || paths.isEmpty()) { return; } appendLine(serviceBuilder, "service MainService {"); - for (Path path : paths.values()) { - for (Operation operation : path.getOperationMap().values()) { + for (PathItem path : paths.values()) { + for (Operation operation : path.readOperations()) { if (isUpload(operation)) { LOGGER.warn("Not support operation for highway {}.{}, {}", this.protoPackage, operation.getOperationId(), "file upload not supported"); @@ -332,20 +313,15 @@ private void convertOperations() { } private boolean isUpload(Operation operation) { - if (operation.getConsumes() != null && operation.getConsumes().contains(MediaType.MULTIPART_FORM_DATA)) { - return true; - } - return false; + return operation.getRequestBody() != null && operation.getRequestBody().getContent() != null + && operation.getRequestBody().getContent().get(MediaType.MULTIPART_FORM_DATA) != null; } private boolean isDownload(Operation operation) { - if (operation.getResponses().get("200").getResponseSchema() instanceof ModelImpl) { - ModelImpl model = (ModelImpl) operation.getResponses().get("200").getResponseSchema(); - if ("file".equals(model.getType())) { - return true; - } - } - return false; + return operation.getResponses().get(SwaggerConst.SUCCESS_KEY) != null && + operation.getResponses().get(SwaggerConst.SUCCESS_KEY).getContent() != null && + operation.getResponses().get(SwaggerConst.SUCCESS_KEY).getContent().get(MediaType.MULTIPART_FORM_DATA) + != null; } private void convertOperation(Operation operation) { @@ -360,15 +336,15 @@ private void convertOperation(Operation operation) { } private void fillRequestType(Operation operation, ProtoMethod protoMethod) { - List parameters = operation.getParameters(); - if (parameters.isEmpty()) { + int parametersCount = parametersCount(operation); + if (parametersCount == 0) { addImports(ProtoConst.EMPTY_PROTO); protoMethod.setArgTypeName(ProtoConst.EMPTY.getCanonicalName()); return; } - if (parameters.size() == 1) { - String type = convertSwaggerType(parameters.get(0)); + if (parametersCount == 1) { + String type = convertSwaggerType(oneSchema(operation)); if (messages.contains(type)) { protoMethod.setArgTypeName(type); return; @@ -376,14 +352,67 @@ private void fillRequestType(Operation operation, ProtoMethod protoMethod) { } String wrapName = StringUtils.capitalize(operation.getOperationId()) + "RequestWrap"; - createWrapArgs(wrapName, parameters); + createWrapArgs(wrapName, wrapSchema(operation)); protoMethod.setArgTypeName(wrapName); } + private Map wrapSchema(Operation operation) { + Map properties = new LinkedHashMap<>(); + if (operation.getParameters() != null) { + for (Parameter parameter : operation.getParameters()) { + properties.put(parameter.getName(), parameter.getSchema()); + } + } + if (operation.getRequestBody() != null + && operation.getRequestBody().getContent().size() != 0) { + if (operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE) != null) { + operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE).getSchema().getProperties() + .forEach((k, v) -> properties.put((String) k, (Schema) v)); + } else { + properties.put((String) operation.getRequestBody().getExtensions().get(SwaggerConst.EXT_BODY_NAME), + operation.getRequestBody().getContent().get( + operation.getRequestBody().getContent().keySet().iterator().next()).getSchema()); + } + } + return properties; + } + + private Schema oneSchema(Operation operation) { + if (operation.getParameters() != null && operation.getParameters().size() == 1) { + return operation.getParameters().get(0).getSchema(); + } + if (operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE) != null) { + return (Schema) operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE).getSchema() + .getProperties() + .values().iterator().next(); + } + return operation.getRequestBody().getContent().get( + operation.getRequestBody().getContent().keySet().iterator().next()).getSchema(); + } + + private int parametersCount(Operation operation) { + int parameters = operation.getParameters() == null ? 0 : operation.getParameters().size(); + if (operation.getRequestBody() != null) { + if (operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE) != null) { + parameters = parameters + operation.getRequestBody() + .getContent().get(SwaggerConst.FORM_MEDIA_TYPE).getSchema().getProperties().size(); + } else if (operation.getRequestBody().getContent().size() != 0) { + parameters = parameters + 1; + } + } + return parameters; + } + private void fillResponseType(Operation operation, ProtoMethod protoMethod) { - for (Entry entry : operation.getResponses().entrySet()) { - String type = convertSwaggerType(entry.getValue().getResponseSchema()); + for (Entry entry : operation.getResponses().entrySet()) { + Schema schema = null; + if (entry.getValue().getContent() != null && + entry.getValue().getContent().size() != 0) { + schema = entry.getValue().getContent().get( + entry.getValue().getContent().keySet().iterator().next()).getSchema(); + } + String type = convertSwaggerType(schema); boolean wrapped = !messages.contains(type); ProtoResponse protoResponse = new ProtoResponse(); @@ -391,7 +420,7 @@ private void fillResponseType(Operation operation, ProtoMethod protoMethod) { if (wrapped) { String wrapName = StringUtils.capitalize(operation.getOperationId()) + "ResponseWrap" + entry.getKey(); - wrapPropertyToMessage(wrapName, entry.getValue().getResponseSchema()); + wrapPropertyToMessage(wrapName, schema); protoResponse.setTypeName(wrapName); } @@ -399,11 +428,7 @@ private void fillResponseType(Operation operation, ProtoMethod protoMethod) { } } - private void createWrapArgs(String wrapName, List parameters) { - Map properties = new LinkedHashMap<>(); - for (Parameter parameter : parameters) { - properties.put(parameter.getName(), parameter); - } + private void createWrapArgs(String wrapName, Map properties) { createMessage(wrapName, properties, ProtoConst.ANNOTATION_WRAP_ARGUMENTS); } diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerTypeAdapter.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerTypeAdapter.java index 2fd0580ec9c..80a20fd2822 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerTypeAdapter.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/internal/converter/SwaggerTypeAdapter.java @@ -18,10 +18,7 @@ import java.util.List; -import io.swagger.models.Model; -import io.swagger.models.parameters.BodyParameter; -import io.swagger.models.parameters.SerializableParameter; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.media.Schema; public interface SwaggerTypeAdapter { static SwaggerTypeAdapter create(Object swaggerType) { @@ -29,20 +26,8 @@ static SwaggerTypeAdapter create(Object swaggerType) { return (SwaggerTypeAdapter) swaggerType; } - if (swaggerType instanceof Model) { - return new ModelAdapter((Model) swaggerType); - } - - if (swaggerType instanceof Property) { - return new PropertyAdapter((Property) swaggerType); - } - - if (swaggerType instanceof SerializableParameter) { - return new SerializableParameterAdapter((SerializableParameter) swaggerType); - } - - if (swaggerType instanceof BodyParameter) { - return new BodyParameterAdapter((BodyParameter) swaggerType); + if (swaggerType instanceof Schema) { + return new SchemaSwaggerTypeAdapter((Schema) swaggerType); } throw new IllegalStateException("not support swagger type: " + swaggerType.getClass().getName()); @@ -50,9 +35,9 @@ static SwaggerTypeAdapter create(Object swaggerType) { String getRefType(); - Property getArrayItem(); + Schema getArrayItem(); - Property getMapItem(); + Schema getMapItem(); List getEnum(); diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/schema/SchemaToProtoGenerator.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/schema/SchemaToProtoGenerator.java new file mode 100644 index 00000000000..0220cd96b30 --- /dev/null +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/schema/SchemaToProtoGenerator.java @@ -0,0 +1,416 @@ +/* + * 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.codec.protobuf.schema; + + +import static org.apache.servicecomb.foundation.common.utils.StringBuilderUtils.appendLine; + +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst; +import org.apache.servicecomb.foundation.protobuf.internal.parser.ProtoParser; +import org.apache.servicecomb.swagger.SwaggerUtils; + +import com.google.common.hash.Hashing; + +import io.protostuff.compiler.model.Proto; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public class SchemaToProtoGenerator { + record IdentifierRunnable(Schema identifier, Runnable target) + implements Runnable { + + @Override + public void run() { + this.target.run(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + IdentifierRunnable that = (IdentifierRunnable) o; + return SwaggerUtils.schemaEquals(identifier, that.identifier); + } + + @Override + public int hashCode() { + return SwaggerUtils.schemaHashCode(identifier); + } + } + + private final String protoPackage; + + private final OpenAPI openAPI; + + private final Schema rootSchema; + + private final String rootName; + + private final Set messages = new HashSet<>(); + + private final StringBuilder msgStringBuilder = new StringBuilder(); + + private List pending = new ArrayList<>(); + + public SchemaToProtoGenerator(String protoPackage, OpenAPI openAPI, Schema rootSchema, String rootName) { + this.protoPackage = protoPackage; + this.openAPI = openAPI; + this.rootSchema = rootSchema; + this.rootName = rootName; + } + + public Proto convert() { + createMessage(this.rootSchema); + + int iteration = 0; + do { + List oldPending = pending; + pending = new ArrayList<>(); + for (Runnable runnable : oldPending) { + runnable.run(); + } + if (pending.size() >= oldPending.size()) { + iteration++; + } + } while (!pending.isEmpty() && iteration < 1000); + + if (iteration == 1000) { + throw new IllegalArgumentException( + String.format("Failed to create schema %s. May be cyclic object.", this.rootName)); + } + + Map wrap = new HashMap<>(1); + wrap.put("value", this.rootSchema); + createMessage(rootName, wrap, ProtoConst.ANNOTATION_WRAP_PROPERTY); + + return createProto(); + } + + protected Proto createProto() { + StringBuilder sb = new StringBuilder(); + appendLine(sb, "syntax = \"proto3\";"); + if (StringUtils.isNotEmpty(protoPackage)) { + sb.append("package ").append(protoPackage).append(";\n"); + } + sb.append(msgStringBuilder); + ProtoParser protoParser = new ProtoParser(); + return protoParser.parseFromContent(sb.toString()); + } + + private String findSchemaType(Schema schema) { + @SuppressWarnings("unchecked") + String type = tryFindEnumType((List) schema.getEnum()); + if (type != null) { + return type; + } + + type = findBaseType(schema.getType(), schema.getFormat()); + if (type != null) { + return type; + } + + Schema itemProperty = schema.getItems(); + if (itemProperty != null) { + String containerType = findArrayOrMapItemType(itemProperty); + if (containerType != null) { + return "repeated " + containerType; + } + return null; + } + + itemProperty = (Schema) schema.getAdditionalProperties(); + if (itemProperty != null) { + String containerType = findArrayOrMapItemType(itemProperty); + if (containerType != null) { + return String.format("map", containerType); + } + return null; + } + + type = schema.get$ref(); + if (type != null) { + String typeName = type.substring(Components.COMPONENTS_SCHEMAS_REF.length()); + Schema refSchema = openAPI.getComponents().getSchemas().get(typeName); + if (refSchema == null) { + throw new IllegalArgumentException("not found ref in components " + type); + } + if (StringUtils.isEmpty(refSchema.getName())) { + refSchema.setName(typeName); + } + return findSchemaType(refSchema); + } + + return findObjectType(schema); + } + + private String findObjectType(Schema schema) { + String name = schema.getName(); + if (messages.contains(name)) { + return name; + } + return null; + } + + private void createEnum(String enumName, List enums) { + if (!messages.add(enumName)) { + // already created + return; + } + + appendLine(msgStringBuilder, "enum %s {", enumName); + for (int idx = 0; idx < enums.size(); idx++) { + if (isValidEnum(enums.get(idx))) { + appendLine(msgStringBuilder, " %s =%d;", enums.get(idx), idx); + } else { + throw new IllegalStateException( + String.format("enum class [%s] name [%s] not supported by protobuffer.", enumName, enums.get(idx))); + } + } + appendLine(msgStringBuilder, "}"); + } + + public static boolean isValidEnum(String name) { + return !name.contains(".") && !name.contains("-"); + } + + private String tryFindEnumType(List enums) { + if (enums != null && !enums.isEmpty()) { + String strEnums = enums.toString(); + String enumName = "Enum_" + Hashing.sha256().hashString(strEnums, StandardCharsets.UTF_8); + pending.add(() -> createEnum(enumName, enums)); + return enumName; + } + return null; + } + + private String findBaseType(String swaggerType, String swaggerFmt) { + String key = swaggerType + ":" + swaggerFmt; + return switch (key) { + case "boolean:null" -> "bool"; + case "integer:int32" -> "sint32"; + case "integer:int64" -> "sint64"; + case "integer:null" -> "string"; // BigInteger like values + case "number:double" -> "double"; + case "number:float" -> "float"; + case "number:null" -> "string"; // BigDecimal like values + case "string:null" -> "string"; + case "string:byte" -> "bytes"; + case "string:date" -> "int64"; + case "string:date-time" -> "int64"; + case "string:binary" -> throw new IllegalArgumentException("proto buffer not support file upload/download"); + default -> null; + }; + } + + private String findArrayOrMapItemType(Schema itemProperty) { + // List>, need to wrap + if (itemProperty.getItems() != null) { + return findWrapPropertyType(List.class.getSimpleName(), itemProperty.getItems()); + } + + // List>, need to wrap + if (itemProperty.getAdditionalProperties() != null) { + return findWrapPropertyType(Map.class.getSimpleName(), (Schema) itemProperty.getAdditionalProperties()); + } + + return findSchemaType(itemProperty); + } + + + private String findWrapPropertyType(String prefix, Schema property) { + // List>, need to wrap + if (property.getItems() != null) { + return findWrapPropertyType(prefix + List.class.getSimpleName(), property.getItems()); + } + + // List>, need to wrap + if (property.getAdditionalProperties() != null) { + return findWrapPropertyType(prefix + Map.class.getSimpleName(), + (Schema) property.getAdditionalProperties()); + } + + String type = findSchemaType(property); + if (type == null) { + return null; + } + + // message name cannot have . (package separator) + return prefix + StringUtils.capitalize(escapeMessageName(type)); + } + + public static String escapeMessageName(String name) { + return name.replaceAll("\\.", "_"); + } + + + private void wrapPropertyToMessage(String protoName, Schema property) { + createMessage(protoName, Collections.singletonMap("value", property), ProtoConst.ANNOTATION_WRAP_PROPERTY); + } + + private void createMessage(String protoName, Map properties, String... annotations) { + for (String annotation : annotations) { + msgStringBuilder.append("//"); + appendLine(msgStringBuilder, annotation); + } + appendLine(msgStringBuilder, "message %s {", protoName); + int tag = 1; + for (Entry entry : properties.entrySet()) { + Schema property = entry.getValue(); + String propertyType = findSchemaType(property); + + appendLine(msgStringBuilder, " %s %s = %d;", propertyType, entry.getKey(), tag); + tag++; + } + appendLine(msgStringBuilder, "}"); + } + + public void createMessage(Schema schema) { + String ref = schema.get$ref(); + if (ref != null) { + String typeName = ref.substring(Components.COMPONENTS_SCHEMAS_REF.length()); + Schema refSchema = openAPI.getComponents().getSchemas().get(typeName); + if (refSchema == null) { + throw new IllegalArgumentException("not found ref in components " + ref); + } + if (StringUtils.isEmpty(refSchema.getName())) { + refSchema.setName(typeName); + } + createMessage(refSchema); + return; + } + + boolean wait = false; + + //array or map + if (isArrayOrMap(schema)) { + Schema mapOrArrayItem = arrayOrMapItem(schema); + if (findSchemaType(mapOrArrayItem) == null) { + createMessageTask(mapOrArrayItem); + wait = true; + } else { + if (createMapOrArrayMessageTask(mapOrArrayItem, true, schema)) { + wait = true; + } + } + } + + //object + if (schema.getProperties() != null) { + for (Entry entry : schema.getProperties().entrySet()) { + if (findSchemaType(entry.getValue()) == null) { + createMessageTask(entry.getValue()); + wait = true; + } else if (isArrayOrMap(entry.getValue())) { + if (createMapOrArrayMessageTask(arrayOrMapItem(entry.getValue()), false, null)) { + wait = true; + } + } + } + } + + if (wait) { + IdentifierRunnable runnable = new IdentifierRunnable(schema, () -> createMessage(schema)); + if (!pending.contains(runnable)) { + pending.add(runnable); + } + return; + } + + if (findSchemaType(schema) != null) { + return; + } + + messages.add(schema.getName()); + + appendLine(msgStringBuilder, "message %s {", schema.getName()); + List> sortedProperties = new ArrayList<>(schema.getProperties().entrySet()); + sortedProperties.sort(Comparator.comparing(Map.Entry::getKey)); + int tag = 1; + for (Entry entry : sortedProperties) { + Schema property = entry.getValue(); + String propertyType = findSchemaType(property); + + appendLine(msgStringBuilder, " %s %s = %d;", propertyType, entry.getKey(), tag); + tag++; + } + appendLine(msgStringBuilder, "}"); + } + + private boolean isArrayOrMap(Schema value) { + return value.getItems() != null || value.getAdditionalProperties() != null; + } + + private Schema arrayOrMapItem(Schema schema) { + return schema.getItems() == null ? + (Schema) schema.getAdditionalProperties() : schema.getItems(); + } + + private void createMessageTask(Schema schema) { + IdentifierRunnable runnable = new IdentifierRunnable(schema, () -> createMessage(schema)); + if (!pending.contains(runnable)) { + pending.add(runnable); + } + } + + private boolean createMapOrArrayMessageTask(Schema schema, boolean nested, Schema owner) { + if (schema.getAdditionalProperties() != null) { + String protoName = findWrapPropertyType(Map.class.getSimpleName(), + (Schema) schema.getAdditionalProperties()); + if (messages.add(protoName)) { + pending.add(() -> wrapPropertyToMessage(protoName, schema)); + createMessageTask((Schema) schema.getAdditionalProperties()); + return true; + } + } + if (schema.getItems() != null) { + String protoName = findWrapPropertyType(List.class.getSimpleName(), schema.getItems()); + if (messages.add(protoName)) { + pending.add(() -> wrapPropertyToMessage(protoName, schema)); + createMessageTask(schema.getItems()); + return true; + } + } + if (nested) { + String protoName = owner.getAdditionalProperties() != null ? + findWrapPropertyType(Map.class.getSimpleName(), schema) : + findWrapPropertyType(List.class.getSimpleName(), schema); + if (messages.add(protoName)) { + pending.add(() -> wrapPropertyToMessage(protoName, owner)); + return true; + } + } + return false; + } +} diff --git a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/utils/ScopedProtobufSchemaManager.java b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/utils/ScopedProtobufSchemaManager.java index 51e1c0b3c44..3c7e5adbb64 100644 --- a/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/utils/ScopedProtobufSchemaManager.java +++ b/common/common-protobuf/src/main/java/org/apache/servicecomb/codec/protobuf/utils/ScopedProtobufSchemaManager.java @@ -19,14 +19,18 @@ import java.util.Map; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.codec.protobuf.internal.converter.SwaggerToProtoGenerator; +import org.apache.servicecomb.codec.protobuf.schema.SchemaToProtoGenerator; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.protobuf.ProtoMapper; import org.apache.servicecomb.foundation.protobuf.ProtoMapperFactory; +import org.apache.servicecomb.swagger.SwaggerUtils; import io.protostuff.compiler.model.Proto; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; /** * Manage swagger -> protoBuffer mappings. @@ -35,8 +39,48 @@ * for each MicroserviceMeta. */ public class ScopedProtobufSchemaManager { + static class SchemaKey { + String schemaId; + + String rootMessage; + + Schema schema; + + int hashCode = -1; + + SchemaKey(String schemaId, String rootMessage, Schema schema) { + this.schemaId = schemaId; + this.rootMessage = rootMessage; + this.schema = schema; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SchemaKey other = (SchemaKey) o; + return StringUtils.equals(schemaId, other.schemaId) && StringUtils.equals(rootMessage, other.rootMessage) + && SwaggerUtils.schemaEquals(schema, other.schema); + } + + @Override + public int hashCode() { + if (hashCode != -1) { + return hashCode; + } + hashCode = schemaId.hashCode() ^ rootMessage.hashCode() ^ SwaggerUtils.schemaHashCode(schema); + return hashCode; + } + } + // Because this class belongs to each SchemaMeta, the key is the schema id. - private Map mapperCache = new ConcurrentHashMapEx<>(); + private final Map mapperCache = new ConcurrentHashMapEx<>(); + + private final Map schemaMapperCache = new ConcurrentHashMapEx<>(); public ScopedProtobufSchemaManager() { @@ -47,7 +91,7 @@ public ScopedProtobufSchemaManager() { */ public ProtoMapper getOrCreateProtoMapper(SchemaMeta schemaMeta) { return mapperCache.computeIfAbsent(schemaMeta.getSchemaId(), key -> { - Swagger swagger = schemaMeta.getSwagger(); + OpenAPI swagger = schemaMeta.getSwagger(); SwaggerToProtoGenerator generator = new SwaggerToProtoGenerator(schemaMeta.getMicroserviceQualifiedName(), swagger); Proto proto = generator.convert(); @@ -55,4 +99,19 @@ public ProtoMapper getOrCreateProtoMapper(SchemaMeta schemaMeta) { return protoMapperFactory.create(proto); }); } + + /** + * get the ProtoMapper from Schema + */ + public ProtoMapper getOrCreateProtoMapper(OpenAPI openAPI, String schemaId, String rootMessageName, + Schema schema) { + SchemaKey schemaKey = new SchemaKey(schemaId, rootMessageName, schema); + return schemaMapperCache.computeIfAbsent(schemaKey, key -> { + SchemaToProtoGenerator generator = new SchemaToProtoGenerator("scb.schema", openAPI, + key.schema, rootMessageName); + Proto proto = generator.convert(); + ProtoMapperFactory protoMapperFactory = new ProtoMapperFactory(); + return protoMapperFactory.create(proto); + }); + } } diff --git a/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtobuf.java b/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtobuf.java deleted file mode 100644 index b7a6ff3f264..00000000000 --- a/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtobuf.java +++ /dev/null @@ -1,2899 +0,0 @@ -/* - * 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. - */ - -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: ModelProtobuf.proto - -package io.protostuff.runtime.model; - -import com.google.protobuf.CodedOutputStream; - -@SuppressWarnings({"cast"}) -public final class ModelProtobuf { - private ModelProtobuf() { - } - - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); - } - - public interface UserOrBuilder extends - // @@protoc_insertion_point(interface_extends:io.protostuff.runtime.model.User) - com.google.protobuf.MessageOrBuilder { - - /** - * string name = 1; - */ - java.lang.String getName(); - - /** - * string name = 1; - */ - com.google.protobuf.ByteString getNameBytes(); - } - - /** - * Protobuf type {@code io.protostuff.runtime.model.User} - */ - public static final class User extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:io.protostuff.runtime.model.User) - UserOrBuilder { - // Use User.newBuilder() to construct. - private User(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - - private User() { - name_ = ""; - } - - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); - } - - @SuppressWarnings("unused") - private User( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - int mutable_bitField0_ = 0; - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - - name_ = s; - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - makeExtensionsImmutable(); - } - } - - public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_User_descriptor; - } - - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_User_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.protostuff.runtime.model.ModelProtobuf.User.class, - io.protostuff.runtime.model.ModelProtobuf.User.Builder.class); - } - - public static final int NAME_FIELD_NUMBER = 1; - - private volatile java.lang.Object name_; - - /** - * string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - - /** - * string name = 1; - */ - public com.google.protobuf.ByteString getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - private byte memoizedIsInitialized = -1; - - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) { - return true; - } - if (isInitialized == 0) { - return false; - } - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!getNameBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); - } - } - - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) { - return size; - } - - size = 0; - if (!getNameBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); - } - memoizedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.protostuff.runtime.model.ModelProtobuf.User)) { - return super.equals(obj); - } - io.protostuff.runtime.model.ModelProtobuf.User other = - (io.protostuff.runtime.model.ModelProtobuf.User) obj; - - boolean result = true; - result = result && getName() - .equals(other.getName()); - return result; - } - - @SuppressWarnings("unchecked") - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseDelimitedFrom( - java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - com.google.protobuf.CodedInputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public Builder newBuilderForType() { - return newBuilder(); - } - - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - - public static Builder newBuilder(io.protostuff.runtime.model.ModelProtobuf.User prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - - public Builder toBuilder() { - return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - - /** - * Protobuf type {@code io.protostuff.runtime.model.User} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:io.protostuff.runtime.model.User) - io.protostuff.runtime.model.ModelProtobuf.UserOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_User_descriptor; - } - - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_User_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.protostuff.runtime.model.ModelProtobuf.User.class, - io.protostuff.runtime.model.ModelProtobuf.User.Builder.class); - } - - // Construct using io.protostuff.runtime.model.ModelProtobuf.User.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { - } - } - - public Builder clear() { - super.clear(); - name_ = ""; - - return this; - } - - public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_User_descriptor; - } - - public io.protostuff.runtime.model.ModelProtobuf.User getDefaultInstanceForType() { - return io.protostuff.runtime.model.ModelProtobuf.User.getDefaultInstance(); - } - - public io.protostuff.runtime.model.ModelProtobuf.User build() { - io.protostuff.runtime.model.ModelProtobuf.User result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - public io.protostuff.runtime.model.ModelProtobuf.User buildPartial() { - io.protostuff.runtime.model.ModelProtobuf.User result = - new io.protostuff.runtime.model.ModelProtobuf.User(this); - result.name_ = name_; - onBuilt(); - return result; - } - - public Builder clone() { - return (Builder) super.clone(); - } - - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); - } - - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.protostuff.runtime.model.ModelProtobuf.User) { - return mergeFrom((io.protostuff.runtime.model.ModelProtobuf.User) other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.protostuff.runtime.model.ModelProtobuf.User other) { - if (other == io.protostuff.runtime.model.ModelProtobuf.User.getDefaultInstance()) { - return this; - } - if (!other.getName().isEmpty()) { - name_ = other.name_; - onChanged(); - } - onChanged(); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - io.protostuff.runtime.model.ModelProtobuf.User parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (io.protostuff.runtime.model.ModelProtobuf.User) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - - private java.lang.Object name_ = ""; - - /** - * string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - - /** - * string name = 1; - */ - public com.google.protobuf.ByteString getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - /** - * string name = 1; - */ - public Builder setName( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - name_ = value; - onChanged(); - return this; - } - - /** - * string name = 1; - */ - public Builder clearName() { - - name_ = getDefaultInstance().getName(); - onChanged(); - return this; - } - - /** - * string name = 1; - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - name_ = value; - onChanged(); - return this; - } - - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - // @@protoc_insertion_point(builder_scope:io.protostuff.runtime.model.User) - } - - // @@protoc_insertion_point(class_scope:io.protostuff.runtime.model.User) - private static final io.protostuff.runtime.model.ModelProtobuf.User DEFAULT_INSTANCE; - - static { - DEFAULT_INSTANCE = new io.protostuff.runtime.model.ModelProtobuf.User(); - } - - public static io.protostuff.runtime.model.ModelProtobuf.User getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public User parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new User(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - public io.protostuff.runtime.model.ModelProtobuf.User getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - } - - public interface RequestHeaderOrBuilder extends - // @@protoc_insertion_point(interface_extends:io.protostuff.runtime.model.RequestHeader) - com.google.protobuf.MessageOrBuilder { - - /** - * string destMicroservice = 1; - */ - java.lang.String getDestMicroservice(); - - /** - * string destMicroservice = 1; - */ - com.google.protobuf.ByteString getDestMicroserviceBytes(); - - /** - * int32 msgType = 2; - */ - int getMsgType(); - - /** - * int32 flags = 3; - */ - int getFlags(); - - /** - * string schemaId = 5; - */ - java.lang.String getSchemaId(); - - /** - * string schemaId = 5; - */ - com.google.protobuf.ByteString getSchemaIdBytes(); - - /** - * string operationName = 6; - */ - java.lang.String getOperationName(); - - /** - * string operationName = 6; - */ - com.google.protobuf.ByteString getOperationNameBytes(); - - /** - * map<string, string> cseContext = 7; - */ - int getCseContextCount(); - - /** - * map<string, string> cseContext = 7; - */ - boolean containsCseContext( - java.lang.String key); - - /** - * Use {@link #getCseContextMap()} instead. - */ - @java.lang.Deprecated - java.util.Map getCseContext(); - - /** - * map<string, string> cseContext = 7; - */ - java.util.Map getCseContextMap(); - - /** - * map<string, string> cseContext = 7; - */ - - java.lang.String getCseContextOrDefault( - java.lang.String key, - java.lang.String defaultValue); - - /** - * map<string, string> cseContext = 7; - */ - - java.lang.String getCseContextOrThrow( - java.lang.String key); - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - int getUserMapCount(); - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - boolean containsUserMap( - java.lang.String key); - - /** - * Use {@link #getUserMapMap()} instead. - */ - @java.lang.Deprecated - java.util.Map getUserMap(); - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - java.util.Map getUserMapMap(); - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - io.protostuff.runtime.model.ModelProtobuf.User getUserMapOrDefault( - java.lang.String key, - io.protostuff.runtime.model.ModelProtobuf.User defaultValue); - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - io.protostuff.runtime.model.ModelProtobuf.User getUserMapOrThrow( - java.lang.String key); - - /** - * repeated string list = 9; - */ - java.util.List getListList(); - - /** - * repeated string list = 9; - */ - int getListCount(); - - /** - * repeated string list = 9; - */ - java.lang.String getList(int index); - - /** - * repeated string list = 9; - */ - com.google.protobuf.ByteString getListBytes(int index); - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - java.util.List getUserListList(); - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - io.protostuff.runtime.model.ModelProtobuf.User getUserList(int index); - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - int getUserListCount(); - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - java.util.List getUserListOrBuilderList(); - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - io.protostuff.runtime.model.ModelProtobuf.UserOrBuilder getUserListOrBuilder( - int index); - } - - /** - * Protobuf type {@code io.protostuff.runtime.model.RequestHeader} - */ - public static final class RequestHeader extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:io.protostuff.runtime.model.RequestHeader) - RequestHeaderOrBuilder { - // Use RequestHeader.newBuilder() to construct. - private RequestHeader(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - - private RequestHeader() { - destMicroservice_ = ""; - msgType_ = 0; - flags_ = 0; - schemaId_ = ""; - operationName_ = ""; - list_ = com.google.protobuf.LazyStringArrayList.EMPTY; - userList_ = java.util.Collections.emptyList(); - } - - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet getUnknownFields() { - return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); - } - - private RequestHeader( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - int mutable_bitField0_ = 0; - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - default: { - if (!input.skipField(tag)) { - done = true; - } - break; - } - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - - destMicroservice_ = s; - break; - } - case 16: { - - msgType_ = input.readInt32(); - break; - } - case 24: { - - flags_ = input.readInt32(); - break; - } - case 42: { - java.lang.String s = input.readStringRequireUtf8(); - - schemaId_ = s; - break; - } - case 50: { - java.lang.String s = input.readStringRequireUtf8(); - - operationName_ = s; - break; - } - case 58: { - if (!((mutable_bitField0_ & 0x00000020) == 0x00000020)) { - cseContext_ = com.google.protobuf.MapField.newMapField( - CseContextDefaultEntryHolder.defaultEntry); - mutable_bitField0_ |= 0x00000020; - } - com.google.protobuf.MapEntry cseContext__ = - input.readMessage( - CseContextDefaultEntryHolder.defaultEntry.getParserForType(), - extensionRegistry); - cseContext_.getMutableMap().put( - cseContext__.getKey(), - cseContext__.getValue()); - break; - } - case 66: { - if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) { - userMap_ = com.google.protobuf.MapField.newMapField( - UserMapDefaultEntryHolder.defaultEntry); - mutable_bitField0_ |= 0x00000040; - } - com.google.protobuf.MapEntry userMap__ = - input.readMessage( - UserMapDefaultEntryHolder.defaultEntry.getParserForType(), - extensionRegistry); - userMap_.getMutableMap().put( - userMap__.getKey(), - userMap__.getValue()); - break; - } - case 74: { - java.lang.String s = input.readStringRequireUtf8(); - if (!((mutable_bitField0_ & 0x00000080) == 0x00000080)) { - list_ = new com.google.protobuf.LazyStringArrayList(); - mutable_bitField0_ |= 0x00000080; - } - list_.add(s); - break; - } - case 82: { - if (!((mutable_bitField0_ & 0x00000100) == 0x00000100)) { - userList_ = new java.util.ArrayList<>(); - mutable_bitField0_ |= 0x00000100; - } - userList_.add( - input.readMessage(io.protostuff.runtime.model.ModelProtobuf.User.parser(), - extensionRegistry)); - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - if (((mutable_bitField0_ & 0x00000080) == 0x00000080)) { - list_ = list_.getUnmodifiableView(); - } - if (((mutable_bitField0_ & 0x00000100) == 0x00000100)) { - userList_ = java.util.Collections.unmodifiableList(userList_); - } - makeExtensionsImmutable(); - } - } - - public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 7: - return internalGetCseContext(); - case 8: - return internalGetUserMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.protostuff.runtime.model.ModelProtobuf.RequestHeader.class, - io.protostuff.runtime.model.ModelProtobuf.RequestHeader.Builder.class); - } - - @SuppressWarnings("unused") - private int bitField0_; - - public static final int DESTMICROSERVICE_FIELD_NUMBER = 1; - - private volatile java.lang.Object destMicroservice_; - - /** - * string destMicroservice = 1; - */ - public java.lang.String getDestMicroservice() { - java.lang.Object ref = destMicroservice_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - destMicroservice_ = s; - return s; - } - } - - /** - * string destMicroservice = 1; - */ - public com.google.protobuf.ByteString getDestMicroserviceBytes() { - java.lang.Object ref = destMicroservice_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - destMicroservice_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int MSGTYPE_FIELD_NUMBER = 2; - - private int msgType_; - - /** - * int32 msgType = 2; - */ - public int getMsgType() { - return msgType_; - } - - public static final int FLAGS_FIELD_NUMBER = 3; - - private int flags_; - - /** - * int32 flags = 3; - */ - public int getFlags() { - return flags_; - } - - public static final int SCHEMAID_FIELD_NUMBER = 5; - - private volatile java.lang.Object schemaId_; - - /** - * string schemaId = 5; - */ - public java.lang.String getSchemaId() { - java.lang.Object ref = schemaId_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - schemaId_ = s; - return s; - } - } - - /** - * string schemaId = 5; - */ - public com.google.protobuf.ByteString getSchemaIdBytes() { - java.lang.Object ref = schemaId_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - schemaId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int OPERATIONNAME_FIELD_NUMBER = 6; - - private volatile java.lang.Object operationName_; - - /** - * string operationName = 6; - */ - public java.lang.String getOperationName() { - java.lang.Object ref = operationName_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - operationName_ = s; - return s; - } - } - - /** - * string operationName = 6; - */ - public com.google.protobuf.ByteString getOperationNameBytes() { - java.lang.Object ref = operationName_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - operationName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int CSECONTEXT_FIELD_NUMBER = 7; - - private static final class CseContextDefaultEntryHolder { - static final com.google.protobuf.MapEntry defaultEntry = - com.google.protobuf.MapEntry.newDefaultInstance( - io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_CseContextEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - - private com.google.protobuf.MapField cseContext_; - - private com.google.protobuf.MapField internalGetCseContext() { - if (cseContext_ == null) { - return com.google.protobuf.MapField.emptyMapField( - CseContextDefaultEntryHolder.defaultEntry); - } - return cseContext_; - } - - public int getCseContextCount() { - return internalGetCseContext().getMap().size(); - } - - /** - * map<string, string> cseContext = 7; - */ - - public boolean containsCseContext( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - return internalGetCseContext().getMap().containsKey(key); - } - - /** - * Use {@link #getCseContextMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getCseContext() { - return getCseContextMap(); - } - - /** - * map<string, string> cseContext = 7; - */ - - public java.util.Map getCseContextMap() { - return internalGetCseContext().getMap(); - } - - /** - * map<string, string> cseContext = 7; - */ - - public java.lang.String getCseContextOrDefault( - java.lang.String key, - java.lang.String defaultValue) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetCseContext().getMap(); - return map.getOrDefault(key, defaultValue); - } - - /** - * map<string, string> cseContext = 7; - */ - - public java.lang.String getCseContextOrThrow( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetCseContext().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int USERMAP_FIELD_NUMBER = 8; - - private static final class UserMapDefaultEntryHolder { - static final com.google.protobuf.MapEntry defaultEntry = - com.google.protobuf.MapEntry.newDefaultInstance( - io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_UserMapEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.MESSAGE, - io.protostuff.runtime.model.ModelProtobuf.User.getDefaultInstance()); - } - - private com.google.protobuf.MapField userMap_; - - private com.google.protobuf.MapField internalGetUserMap() { - if (userMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - UserMapDefaultEntryHolder.defaultEntry); - } - return userMap_; - } - - public int getUserMapCount() { - return internalGetUserMap().getMap().size(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public boolean containsUserMap( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - return internalGetUserMap().getMap().containsKey(key); - } - - /** - * Use {@link #getUserMapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getUserMap() { - return getUserMapMap(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public java.util.Map getUserMapMap() { - return internalGetUserMap().getMap(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public io.protostuff.runtime.model.ModelProtobuf.User getUserMapOrDefault( - java.lang.String key, - io.protostuff.runtime.model.ModelProtobuf.User defaultValue) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetUserMap().getMap(); - return map.getOrDefault(key, defaultValue); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public io.protostuff.runtime.model.ModelProtobuf.User getUserMapOrThrow( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetUserMap().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int LIST_FIELD_NUMBER = 9; - - private com.google.protobuf.LazyStringList list_; - - /** - * repeated string list = 9; - */ - public com.google.protobuf.ProtocolStringList getListList() { - return list_; - } - - /** - * repeated string list = 9; - */ - public int getListCount() { - return list_.size(); - } - - /** - * repeated string list = 9; - */ - public java.lang.String getList(int index) { - return list_.get(index); - } - - /** - * repeated string list = 9; - */ - public com.google.protobuf.ByteString getListBytes(int index) { - return list_.getByteString(index); - } - - public static final int USERLIST_FIELD_NUMBER = 10; - - private java.util.List userList_; - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public java.util.List getUserListList() { - return userList_; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public java.util.List getUserListOrBuilderList() { - return userList_; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public int getUserListCount() { - return userList_.size(); - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.User getUserList(int index) { - return userList_.get(index); - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.UserOrBuilder getUserListOrBuilder( - int index) { - return userList_.get(index); - } - - private byte memoizedIsInitialized = -1; - - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) { - return true; - } - if (isInitialized == 0) { - return false; - } - - memoizedIsInitialized = 1; - return true; - } - - public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { - if (!getDestMicroserviceBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 1, destMicroservice_); - } - if (msgType_ != 0) { - output.writeInt32(2, msgType_); - } - if (flags_ != 0) { - output.writeInt32(3, flags_); - } - if (!getSchemaIdBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 5, schemaId_); - } - if (!getOperationNameBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 6, operationName_); - } - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetCseContext(), - CseContextDefaultEntryHolder.defaultEntry, - 7); - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetUserMap(), - UserMapDefaultEntryHolder.defaultEntry, - 8); - for (int i = 0; i < list_.size(); i++) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 9, list_.getRaw(i)); - } - for (User anUserList_ : userList_) { - output.writeMessage(10, anUserList_); - } - } - - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) { - return size; - } - - size = 0; - if (!getDestMicroserviceBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, destMicroservice_); - } - if (msgType_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(2, msgType_); - } - if (flags_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(3, flags_); - } - if (!getSchemaIdBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(5, schemaId_); - } - if (!getOperationNameBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(6, operationName_); - } - for (java.util.Map.Entry entry : internalGetCseContext().getMap() - .entrySet()) { - com.google.protobuf.MapEntry cseContext__ = - CseContextDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(7, cseContext__); - } - for (java.util.Map.Entry entry : internalGetUserMap() - .getMap() - .entrySet()) { - com.google.protobuf.MapEntry userMap__ = - UserMapDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(8, userMap__); - } - { - int dataSize = 0; - for (int i = 0; i < list_.size(); i++) { - dataSize += computeStringSizeNoTag(list_.getRaw(i)); - } - size += dataSize; - size += 1 * getListList().size(); - } - size += userList_.stream().mapToInt(anUserList_ -> CodedOutputStream - .computeMessageSize(10, anUserList_)).sum(); - memoizedSize = size; - return size; - } - - private static final long serialVersionUID = 0L; - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof io.protostuff.runtime.model.ModelProtobuf.RequestHeader)) { - return super.equals(obj); - } - io.protostuff.runtime.model.ModelProtobuf.RequestHeader other = - (io.protostuff.runtime.model.ModelProtobuf.RequestHeader) obj; - - boolean result = true; - result = result && getDestMicroservice() - .equals(other.getDestMicroservice()); - result = result && (getMsgType() == other.getMsgType()); - result = result && (getFlags() == other.getFlags()); - result = result && getSchemaId() - .equals(other.getSchemaId()); - result = result && getOperationName() - .equals(other.getOperationName()); - result = result && internalGetCseContext().equals( - other.internalGetCseContext()); - result = result && internalGetUserMap().equals( - other.internalGetUserMap()); - result = result && getListList() - .equals(other.getListList()); - result = result && getUserListList() - .equals(other.getUserListList()); - return result; - } - - @SuppressWarnings("unchecked") - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + DESTMICROSERVICE_FIELD_NUMBER; - hash = (53 * hash) + getDestMicroservice().hashCode(); - hash = (37 * hash) + MSGTYPE_FIELD_NUMBER; - hash = (53 * hash) + getMsgType(); - hash = (37 * hash) + FLAGS_FIELD_NUMBER; - hash = (53 * hash) + getFlags(); - hash = (37 * hash) + SCHEMAID_FIELD_NUMBER; - hash = (53 * hash) + getSchemaId().hashCode(); - hash = (37 * hash) + OPERATIONNAME_FIELD_NUMBER; - hash = (53 * hash) + getOperationName().hashCode(); - if (!internalGetCseContext().getMap().isEmpty()) { - hash = (37 * hash) + CSECONTEXT_FIELD_NUMBER; - hash = (53 * hash) + internalGetCseContext().hashCode(); - } - if (!internalGetUserMap().getMap().isEmpty()) { - hash = (37 * hash) + USERMAP_FIELD_NUMBER; - hash = (53 * hash) + internalGetUserMap().hashCode(); - } - if (getListCount() > 0) { - hash = (37 * hash) + LIST_FIELD_NUMBER; - hash = (53 * hash) + getListList().hashCode(); - } - if (getUserListCount() > 0) { - hash = (37 * hash) + USERLIST_FIELD_NUMBER; - hash = (53 * hash) + getUserListList().hashCode(); - } - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - java.nio.ByteBuffer data) throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - com.google.protobuf.ByteString data) throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - byte[] data) throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseDelimitedFrom( - java.io.InputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - com.google.protobuf.CodedInputStream input) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - public Builder newBuilderForType() { - return newBuilder(); - } - - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - - public static Builder newBuilder(io.protostuff.runtime.model.ModelProtobuf.RequestHeader prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - - public Builder toBuilder() { - return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - - /** - * Protobuf type {@code io.protostuff.runtime.model.RequestHeader} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:io.protostuff.runtime.model.RequestHeader) - io.protostuff.runtime.model.ModelProtobuf.RequestHeaderOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 7: - return internalGetCseContext(); - case 8: - return internalGetUserMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMutableMapField( - int number) { - switch (number) { - case 7: - return internalGetMutableCseContext(); - case 8: - return internalGetMutableUserMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internalGetFieldAccessorTable() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_fieldAccessorTable - .ensureFieldAccessorsInitialized( - io.protostuff.runtime.model.ModelProtobuf.RequestHeader.class, - io.protostuff.runtime.model.ModelProtobuf.RequestHeader.Builder.class); - } - - // Construct using io.protostuff.runtime.model.ModelProtobuf.RequestHeader.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders) { - getUserListFieldBuilder(); - } - } - - public Builder clear() { - super.clear(); - destMicroservice_ = ""; - - msgType_ = 0; - - flags_ = 0; - - schemaId_ = ""; - - operationName_ = ""; - - internalGetMutableCseContext().clear(); - internalGetMutableUserMap().clear(); - list_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bitField0_ = (bitField0_ & ~0x00000080); - if (userListBuilder_ == null) { - userList_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000100); - } else { - userListBuilder_.clear(); - } - return this; - } - - public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { - return io.protostuff.runtime.model.ModelProtobuf.internal_static_io_protostuff_runtime_model_RequestHeader_descriptor; - } - - public io.protostuff.runtime.model.ModelProtobuf.RequestHeader getDefaultInstanceForType() { - return io.protostuff.runtime.model.ModelProtobuf.RequestHeader.getDefaultInstance(); - } - - public io.protostuff.runtime.model.ModelProtobuf.RequestHeader build() { - io.protostuff.runtime.model.ModelProtobuf.RequestHeader result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @SuppressWarnings("unused") - public io.protostuff.runtime.model.ModelProtobuf.RequestHeader buildPartial() { - io.protostuff.runtime.model.ModelProtobuf.RequestHeader result = - new io.protostuff.runtime.model.ModelProtobuf.RequestHeader(this); - int from_bitField0_ = bitField0_; - int to_bitField0_ = 0; - result.destMicroservice_ = destMicroservice_; - result.msgType_ = msgType_; - result.flags_ = flags_; - result.schemaId_ = schemaId_; - result.operationName_ = operationName_; - result.cseContext_ = internalGetCseContext(); - result.cseContext_.makeImmutable(); - result.userMap_ = internalGetUserMap(); - result.userMap_.makeImmutable(); - if (((bitField0_ & 0x00000080) == 0x00000080)) { - list_ = list_.getUnmodifiableView(); - bitField0_ = (bitField0_ & ~0x00000080); - } - result.list_ = list_; - if (userListBuilder_ == null) { - if (((bitField0_ & 0x00000100) == 0x00000100)) { - userList_ = java.util.Collections.unmodifiableList(userList_); - bitField0_ = (bitField0_ & ~0x00000100); - } - result.userList_ = userList_; - } else { - result.userList_ = userListBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - public Builder clone() { - return (Builder) super.clone(); - } - - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.setField(field, value); - } - - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - Object value) { - return (Builder) super.addRepeatedField(field, value); - } - - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof io.protostuff.runtime.model.ModelProtobuf.RequestHeader) { - return mergeFrom((io.protostuff.runtime.model.ModelProtobuf.RequestHeader) other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(io.protostuff.runtime.model.ModelProtobuf.RequestHeader other) { - if (other == io.protostuff.runtime.model.ModelProtobuf.RequestHeader.getDefaultInstance()) { - return this; - } - if (!other.getDestMicroservice().isEmpty()) { - destMicroservice_ = other.destMicroservice_; - onChanged(); - } - if (other.getMsgType() != 0) { - setMsgType(other.getMsgType()); - } - if (other.getFlags() != 0) { - setFlags(other.getFlags()); - } - if (!other.getSchemaId().isEmpty()) { - schemaId_ = other.schemaId_; - onChanged(); - } - if (!other.getOperationName().isEmpty()) { - operationName_ = other.operationName_; - onChanged(); - } - internalGetMutableCseContext().mergeFrom( - other.internalGetCseContext()); - internalGetMutableUserMap().mergeFrom( - other.internalGetUserMap()); - if (!other.list_.isEmpty()) { - if (list_.isEmpty()) { - list_ = other.list_; - bitField0_ = (bitField0_ & ~0x00000080); - } else { - ensureListIsMutable(); - list_.addAll(other.list_); - } - onChanged(); - } - if (userListBuilder_ == null) { - if (!other.userList_.isEmpty()) { - if (userList_.isEmpty()) { - userList_ = other.userList_; - bitField0_ = (bitField0_ & ~0x00000100); - } else { - ensureUserListIsMutable(); - userList_.addAll(other.userList_); - } - onChanged(); - } - } else { - if (!other.userList_.isEmpty()) { - if (userListBuilder_.isEmpty()) { - userListBuilder_.dispose(); - userListBuilder_ = null; - userList_ = other.userList_; - bitField0_ = (bitField0_ & ~0x00000100); - userListBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders - ? getUserListFieldBuilder() - : null; - } else { - userListBuilder_.addAllMessages(other.userList_); - } - } - } - onChanged(); - return this; - } - - public final boolean isInitialized() { - return true; - } - - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) throws java.io.IOException { - io.protostuff.runtime.model.ModelProtobuf.RequestHeader parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = - (io.protostuff.runtime.model.ModelProtobuf.RequestHeader) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - - private int bitField0_; - - private java.lang.Object destMicroservice_ = ""; - - /** - * string destMicroservice = 1; - */ - public java.lang.String getDestMicroservice() { - java.lang.Object ref = destMicroservice_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - destMicroservice_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - - /** - * string destMicroservice = 1; - */ - public com.google.protobuf.ByteString getDestMicroserviceBytes() { - java.lang.Object ref = destMicroservice_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - destMicroservice_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - /** - * string destMicroservice = 1; - */ - public Builder setDestMicroservice( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - destMicroservice_ = value; - onChanged(); - return this; - } - - /** - * string destMicroservice = 1; - */ - public Builder clearDestMicroservice() { - - destMicroservice_ = getDefaultInstance().getDestMicroservice(); - onChanged(); - return this; - } - - /** - * string destMicroservice = 1; - */ - public Builder setDestMicroserviceBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - destMicroservice_ = value; - onChanged(); - return this; - } - - private int msgType_; - - /** - * int32 msgType = 2; - */ - public int getMsgType() { - return msgType_; - } - - /** - * int32 msgType = 2; - */ - public Builder setMsgType(int value) { - - msgType_ = value; - onChanged(); - return this; - } - - /** - * int32 msgType = 2; - */ - public Builder clearMsgType() { - - msgType_ = 0; - onChanged(); - return this; - } - - private int flags_; - - /** - * int32 flags = 3; - */ - public int getFlags() { - return flags_; - } - - /** - * int32 flags = 3; - */ - public Builder setFlags(int value) { - - flags_ = value; - onChanged(); - return this; - } - - /** - * int32 flags = 3; - */ - public Builder clearFlags() { - - flags_ = 0; - onChanged(); - return this; - } - - private java.lang.Object schemaId_ = ""; - - /** - * string schemaId = 5; - */ - public java.lang.String getSchemaId() { - java.lang.Object ref = schemaId_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - schemaId_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - - /** - * string schemaId = 5; - */ - public com.google.protobuf.ByteString getSchemaIdBytes() { - java.lang.Object ref = schemaId_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - schemaId_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - /** - * string schemaId = 5; - */ - public Builder setSchemaId( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - schemaId_ = value; - onChanged(); - return this; - } - - /** - * string schemaId = 5; - */ - public Builder clearSchemaId() { - - schemaId_ = getDefaultInstance().getSchemaId(); - onChanged(); - return this; - } - - /** - * string schemaId = 5; - */ - public Builder setSchemaIdBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - schemaId_ = value; - onChanged(); - return this; - } - - private java.lang.Object operationName_ = ""; - - /** - * string operationName = 6; - */ - public java.lang.String getOperationName() { - java.lang.Object ref = operationName_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - operationName_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - - /** - * string operationName = 6; - */ - public com.google.protobuf.ByteString getOperationNameBytes() { - java.lang.Object ref = operationName_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - operationName_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - /** - * string operationName = 6; - */ - public Builder setOperationName( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - operationName_ = value; - onChanged(); - return this; - } - - /** - * string operationName = 6; - */ - public Builder clearOperationName() { - - operationName_ = getDefaultInstance().getOperationName(); - onChanged(); - return this; - } - - /** - * string operationName = 6; - */ - public Builder setOperationNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - operationName_ = value; - onChanged(); - return this; - } - - private com.google.protobuf.MapField cseContext_; - - private com.google.protobuf.MapField internalGetCseContext() { - if (cseContext_ == null) { - return com.google.protobuf.MapField.emptyMapField( - CseContextDefaultEntryHolder.defaultEntry); - } - return cseContext_; - } - - private com.google.protobuf.MapField internalGetMutableCseContext() { - onChanged(); - if (cseContext_ == null) { - cseContext_ = com.google.protobuf.MapField.newMapField( - CseContextDefaultEntryHolder.defaultEntry); - } - if (!cseContext_.isMutable()) { - cseContext_ = cseContext_.copy(); - } - return cseContext_; - } - - public int getCseContextCount() { - return internalGetCseContext().getMap().size(); - } - - /** - * map<string, string> cseContext = 7; - */ - - public boolean containsCseContext( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - return internalGetCseContext().getMap().containsKey(key); - } - - /** - * Use {@link #getCseContextMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getCseContext() { - return getCseContextMap(); - } - - /** - * map<string, string> cseContext = 7; - */ - - public java.util.Map getCseContextMap() { - return internalGetCseContext().getMap(); - } - - /** - * map<string, string> cseContext = 7; - */ - - public java.lang.String getCseContextOrDefault( - java.lang.String key, - java.lang.String defaultValue) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetCseContext().getMap(); - return map.getOrDefault(key, defaultValue); - } - - /** - * map<string, string> cseContext = 7; - */ - - public java.lang.String getCseContextOrThrow( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetCseContext().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearCseContext() { - internalGetMutableCseContext().getMutableMap() - .clear(); - return this; - } - - /** - * map<string, string> cseContext = 7; - */ - - public Builder removeCseContext( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - internalGetMutableCseContext().getMutableMap() - .remove(key); - return this; - } - - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map getMutableCseContext() { - return internalGetMutableCseContext().getMutableMap(); - } - - /** - * map<string, string> cseContext = 7; - */ - public Builder putCseContext( - java.lang.String key, - java.lang.String value) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - if (value == null) { - throw new java.lang.NullPointerException(); - } - internalGetMutableCseContext().getMutableMap() - .put(key, value); - return this; - } - - /** - * map<string, string> cseContext = 7; - */ - - public Builder putAllCseContext( - java.util.Map values) { - internalGetMutableCseContext().getMutableMap() - .putAll(values); - return this; - } - - private com.google.protobuf.MapField userMap_; - - private com.google.protobuf.MapField internalGetUserMap() { - if (userMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - UserMapDefaultEntryHolder.defaultEntry); - } - return userMap_; - } - - private com.google.protobuf.MapField internalGetMutableUserMap() { - onChanged(); - if (userMap_ == null) { - userMap_ = com.google.protobuf.MapField.newMapField( - UserMapDefaultEntryHolder.defaultEntry); - } - if (!userMap_.isMutable()) { - userMap_ = userMap_.copy(); - } - return userMap_; - } - - public int getUserMapCount() { - return internalGetUserMap().getMap().size(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public boolean containsUserMap( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - return internalGetUserMap().getMap().containsKey(key); - } - - /** - * Use {@link #getUserMapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getUserMap() { - return getUserMapMap(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public java.util.Map getUserMapMap() { - return internalGetUserMap().getMap(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public io.protostuff.runtime.model.ModelProtobuf.User getUserMapOrDefault( - java.lang.String key, - io.protostuff.runtime.model.ModelProtobuf.User defaultValue) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetUserMap().getMap(); - return map.getOrDefault(key, defaultValue); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public io.protostuff.runtime.model.ModelProtobuf.User getUserMapOrThrow( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - java.util.Map map = - internalGetUserMap().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearUserMap() { - internalGetMutableUserMap().getMutableMap() - .clear(); - return this; - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public Builder removeUserMap( - java.lang.String key) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - internalGetMutableUserMap().getMutableMap() - .remove(key); - return this; - } - - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map getMutableUserMap() { - return internalGetMutableUserMap().getMutableMap(); - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - public Builder putUserMap( - java.lang.String key, - io.protostuff.runtime.model.ModelProtobuf.User value) { - if (key == null) { - throw new java.lang.NullPointerException(); - } - if (value == null) { - throw new java.lang.NullPointerException(); - } - internalGetMutableUserMap().getMutableMap() - .put(key, value); - return this; - } - - /** - * map<string, .io.protostuff.runtime.model.User> userMap = 8; - */ - - public Builder putAllUserMap( - java.util.Map values) { - internalGetMutableUserMap().getMutableMap() - .putAll(values); - return this; - } - - private com.google.protobuf.LazyStringList list_ = com.google.protobuf.LazyStringArrayList.EMPTY; - - private void ensureListIsMutable() { - if (!((bitField0_ & 0x00000080) == 0x00000080)) { - list_ = new com.google.protobuf.LazyStringArrayList(list_); - bitField0_ |= 0x00000080; - } - } - - /** - * repeated string list = 9; - */ - public com.google.protobuf.ProtocolStringList getListList() { - return list_.getUnmodifiableView(); - } - - /** - * repeated string list = 9; - */ - public int getListCount() { - return list_.size(); - } - - /** - * repeated string list = 9; - */ - public java.lang.String getList(int index) { - return list_.get(index); - } - - /** - * repeated string list = 9; - */ - public com.google.protobuf.ByteString getListBytes(int index) { - return list_.getByteString(index); - } - - /** - * repeated string list = 9; - */ - public Builder setList( - int index, java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - ensureListIsMutable(); - list_.set(index, value); - onChanged(); - return this; - } - - /** - * repeated string list = 9; - */ - public Builder addList( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - ensureListIsMutable(); - list_.add(value); - onChanged(); - return this; - } - - /** - * repeated string list = 9; - */ - public Builder addAllList( - java.lang.Iterable values) { - ensureListIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, - list_); - onChanged(); - return this; - } - - /** - * repeated string list = 9; - */ - public Builder clearList() { - list_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bitField0_ = (bitField0_ & ~0x00000080); - onChanged(); - return this; - } - - /** - * repeated string list = 9; - */ - public Builder addListBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - ensureListIsMutable(); - list_.add(value); - onChanged(); - return this; - } - - private java.util.List userList_ = - java.util.Collections.emptyList(); - - private void ensureUserListIsMutable() { - if (!((bitField0_ & 0x00000100) == 0x00000100)) { - userList_ = new java.util.ArrayList<>(userList_); - bitField0_ |= 0x00000100; - } - } - - private com.google.protobuf.RepeatedFieldBuilderV3 userListBuilder_; - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public java.util.List getUserListList() { - if (userListBuilder_ == null) { - return java.util.Collections.unmodifiableList(userList_); - } else { - return userListBuilder_.getMessageList(); - } - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public int getUserListCount() { - if (userListBuilder_ == null) { - return userList_.size(); - } else { - return userListBuilder_.getCount(); - } - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.User getUserList(int index) { - if (userListBuilder_ == null) { - return userList_.get(index); - } else { - return userListBuilder_.getMessage(index); - } - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder setUserList( - int index, io.protostuff.runtime.model.ModelProtobuf.User value) { - if (userListBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureUserListIsMutable(); - userList_.set(index, value); - onChanged(); - } else { - userListBuilder_.setMessage(index, value); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder setUserList( - int index, io.protostuff.runtime.model.ModelProtobuf.User.Builder builderForValue) { - if (userListBuilder_ == null) { - ensureUserListIsMutable(); - userList_.set(index, builderForValue.build()); - onChanged(); - } else { - userListBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder addUserList(io.protostuff.runtime.model.ModelProtobuf.User value) { - if (userListBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureUserListIsMutable(); - userList_.add(value); - onChanged(); - } else { - userListBuilder_.addMessage(value); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder addUserList( - int index, io.protostuff.runtime.model.ModelProtobuf.User value) { - if (userListBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureUserListIsMutable(); - userList_.add(index, value); - onChanged(); - } else { - userListBuilder_.addMessage(index, value); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder addUserList( - io.protostuff.runtime.model.ModelProtobuf.User.Builder builderForValue) { - if (userListBuilder_ == null) { - ensureUserListIsMutable(); - userList_.add(builderForValue.build()); - onChanged(); - } else { - userListBuilder_.addMessage(builderForValue.build()); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder addUserList( - int index, io.protostuff.runtime.model.ModelProtobuf.User.Builder builderForValue) { - if (userListBuilder_ == null) { - ensureUserListIsMutable(); - userList_.add(index, builderForValue.build()); - onChanged(); - } else { - userListBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder addAllUserList( - java.lang.Iterable values) { - if (userListBuilder_ == null) { - ensureUserListIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, - userList_); - onChanged(); - } else { - userListBuilder_.addAllMessages(values); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder clearUserList() { - if (userListBuilder_ == null) { - userList_ = java.util.Collections.emptyList(); - bitField0_ = (bitField0_ & ~0x00000100); - onChanged(); - } else { - userListBuilder_.clear(); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public Builder removeUserList(int index) { - if (userListBuilder_ == null) { - ensureUserListIsMutable(); - userList_.remove(index); - onChanged(); - } else { - userListBuilder_.remove(index); - } - return this; - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.User.Builder getUserListBuilder( - int index) { - return getUserListFieldBuilder().getBuilder(index); - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.UserOrBuilder getUserListOrBuilder( - int index) { - if (userListBuilder_ == null) { - return userList_.get(index); - } else { - return userListBuilder_.getMessageOrBuilder(index); - } - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public java.util.List getUserListOrBuilderList() { - if (userListBuilder_ != null) { - return userListBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(userList_); - } - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.User.Builder addUserListBuilder() { - return getUserListFieldBuilder().addBuilder( - io.protostuff.runtime.model.ModelProtobuf.User.getDefaultInstance()); - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public io.protostuff.runtime.model.ModelProtobuf.User.Builder addUserListBuilder( - int index) { - return getUserListFieldBuilder().addBuilder( - index, - io.protostuff.runtime.model.ModelProtobuf.User.getDefaultInstance()); - } - - /** - * repeated .io.protostuff.runtime.model.User userList = 10; - */ - public java.util.List getUserListBuilderList() { - return getUserListFieldBuilder().getBuilderList(); - } - - private com.google.protobuf.RepeatedFieldBuilderV3 getUserListFieldBuilder() { - if (userListBuilder_ == null) { - userListBuilder_ = - new com.google.protobuf.RepeatedFieldBuilderV3<>( - userList_, - ((bitField0_ & 0x00000100) == 0x00000100), - getParentForChildren(), - isClean()); - userList_ = null; - } - return userListBuilder_; - } - - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return this; - } - - // @@protoc_insertion_point(builder_scope:io.protostuff.runtime.model.RequestHeader) - } - - // @@protoc_insertion_point(class_scope:io.protostuff.runtime.model.RequestHeader) - private static final io.protostuff.runtime.model.ModelProtobuf.RequestHeader DEFAULT_INSTANCE; - - static { - DEFAULT_INSTANCE = new io.protostuff.runtime.model.ModelProtobuf.RequestHeader(); - } - - public static io.protostuff.runtime.model.ModelProtobuf.RequestHeader getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser PARSER = - new com.google.protobuf.AbstractParser() { - public RequestHeader parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new RequestHeader(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - public io.protostuff.runtime.model.ModelProtobuf.RequestHeader getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - } - - private static final com.google.protobuf.Descriptors.Descriptor internal_static_io_protostuff_runtime_model_User_descriptor; - - private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_io_protostuff_runtime_model_User_fieldAccessorTable; - - private static final com.google.protobuf.Descriptors.Descriptor internal_static_io_protostuff_runtime_model_RequestHeader_descriptor; - - private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_io_protostuff_runtime_model_RequestHeader_fieldAccessorTable; - - private static final com.google.protobuf.Descriptors.Descriptor internal_static_io_protostuff_runtime_model_RequestHeader_CseContextEntry_descriptor; - - @SuppressWarnings("unused") - private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_io_protostuff_runtime_model_RequestHeader_CseContextEntry_fieldAccessorTable; - - private static final com.google.protobuf.Descriptors.Descriptor internal_static_io_protostuff_runtime_model_RequestHeader_UserMapEntry_descriptor; - - @SuppressWarnings("unused") - private static final com.google.protobuf.GeneratedMessageV3.FieldAccessorTable internal_static_io_protostuff_runtime_model_RequestHeader_UserMapEntry_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { - return descriptor; - } - - private static com.google.protobuf.Descriptors.FileDescriptor descriptor; - - static { - java.lang.String[] descriptorData = { - "\n\023ModelProtobuf.proto\022\033io.protostuff.run" + - "time.model\"\024\n\004User\022\014\n\004name\030\001 \001(\t\"\325\003\n\rReq" + - "uestHeader\022\030\n\020destMicroservice\030\001 \001(\t\022\017\n\007" + - "msgType\030\002 \001(\005\022\r\n\005flags\030\003 \001(\005\022\020\n\010schemaId" + - "\030\005 \001(\t\022\025\n\roperationName\030\006 \001(\t\022N\n\ncseCont" + - "ext\030\007 \003(\0132:.io.protostuff.runtime.model." + - "RequestHeader.CseContextEntry\022H\n\007userMap" + - "\030\010 \003(\01327.io.protostuff.runtime.model.Req" + - "uestHeader.UserMapEntry\022\014\n\004list\030\t \003(\t\0223\n" + - "\010userList\030\n \003(\0132!.io.protostuff.runtime.", - "model.User\0321\n\017CseContextEntry\022\013\n\003key\030\001 \001" + - "(\t\022\r\n\005value\030\002 \001(\t:\0028\001\032Q\n\014UserMapEntry\022\013\n" + - "\003key\030\001 \001(\t\0220\n\005value\030\002 \001(\0132!.io.protostuf" + - "f.runtime.model.User:\0028\001b\006proto3" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - }, - assigner); - internal_static_io_protostuff_runtime_model_User_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_io_protostuff_runtime_model_User_fieldAccessorTable = - new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_io_protostuff_runtime_model_User_descriptor, - new java.lang.String[] {"Name",}); - internal_static_io_protostuff_runtime_model_RequestHeader_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_io_protostuff_runtime_model_RequestHeader_fieldAccessorTable = - new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_io_protostuff_runtime_model_RequestHeader_descriptor, - new java.lang.String[] {"DestMicroservice", "MsgType", "Flags", "SchemaId", "OperationName", - "CseContext", "UserMap", "List", "UserList",}); - internal_static_io_protostuff_runtime_model_RequestHeader_CseContextEntry_descriptor = - internal_static_io_protostuff_runtime_model_RequestHeader_descriptor.getNestedTypes().get(0); - internal_static_io_protostuff_runtime_model_RequestHeader_CseContextEntry_fieldAccessorTable = - new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_io_protostuff_runtime_model_RequestHeader_CseContextEntry_descriptor, - new java.lang.String[] {"Key", "Value",}); - internal_static_io_protostuff_runtime_model_RequestHeader_UserMapEntry_descriptor = - internal_static_io_protostuff_runtime_model_RequestHeader_descriptor.getNestedTypes().get(1); - internal_static_io_protostuff_runtime_model_RequestHeader_UserMapEntry_fieldAccessorTable = - new com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_io_protostuff_runtime_model_RequestHeader_UserMapEntry_descriptor, - new java.lang.String[] {"Key", "Value",}); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtostuff.java b/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtostuff.java index ec4efd65480..c9f41070fa0 100644 --- a/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtostuff.java +++ b/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtostuff.java @@ -24,7 +24,6 @@ public class ModelProtostuff { - //CHECKSTYLE:OFF: magicnumber @Tag(1) private String destMicroservice; diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/definition/TestResponseRootDeserializer.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/definition/TestResponseRootDeserializer.java index 5b7c9aa7121..bf8a98f5c67 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/definition/TestResponseRootDeserializer.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/definition/TestResponseRootDeserializer.java @@ -22,12 +22,12 @@ import java.util.Map; import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.type.SimpleType; import com.fasterxml.jackson.databind.type.TypeFactory; +import org.junit.jupiter.api.Test; class Model { @@ -37,35 +37,26 @@ class Model { public class TestResponseRootDeserializer { @Test public void testNeedConvert() { - Assert.assertEquals(SimpleType.constructUnsafe(Object.class), ProtoConst.OBJECT_TYPE); - Assert.assertEquals(false, - ResponseRootDeserializer.needConvert(1, TypeFactory.defaultInstance().constructType(int.class))); - Assert.assertEquals(false, - ResponseRootDeserializer.needConvert(1, TypeFactory.defaultInstance().constructType(Integer.class))); - Assert.assertEquals(false, - ResponseRootDeserializer - .needConvert(Integer.valueOf(1), TypeFactory.defaultInstance().constructType(int.class))); - Assert.assertEquals(false, - ResponseRootDeserializer - .needConvert(Integer.valueOf(1), TypeFactory.defaultInstance().constructType(Integer.class))); - Assert.assertEquals(true, - ResponseRootDeserializer + Assertions.assertEquals(SimpleType.constructUnsafe(Object.class), ProtoConst.OBJECT_TYPE); + Assertions.assertFalse(ResponseRootDeserializer.needConvert(1, TypeFactory.defaultInstance().constructType(int.class))); + Assertions.assertFalse(ResponseRootDeserializer.needConvert(1, TypeFactory.defaultInstance().constructType(Integer.class))); + Assertions.assertFalse(ResponseRootDeserializer + .needConvert(1, TypeFactory.defaultInstance().constructType(int.class))); + Assertions.assertFalse(ResponseRootDeserializer + .needConvert(1, TypeFactory.defaultInstance().constructType(Integer.class))); + Assertions.assertTrue(ResponseRootDeserializer .needConvert(new HashMap<>(), TypeFactory.defaultInstance().constructType(Model.class))); - Assert.assertEquals(false, - ResponseRootDeserializer + Assertions.assertFalse(ResponseRootDeserializer .needConvert(new Model(), TypeFactory.defaultInstance().constructType(Model.class))); - Assert.assertEquals(false, - ResponseRootDeserializer + Assertions.assertFalse(ResponseRootDeserializer .needConvert(new Model(), TypeFactory.defaultInstance().constructType(Object.class))); List modelList = new ArrayList<>(); - List modemaplList = new ArrayList<>(); - Assert.assertEquals(true, - ResponseRootDeserializer - .needConvert(modemaplList, TypeFactory.defaultInstance().constructType(new TypeReference>() { + List modelMapList = new ArrayList<>(); + Assertions.assertTrue(ResponseRootDeserializer + .needConvert(modelMapList, TypeFactory.defaultInstance().constructType(new TypeReference>() { }))); // This case should be false, however it is not exists in real applications, for simpler, take it true. - Assert.assertEquals(true, - ResponseRootDeserializer + Assertions.assertTrue(ResponseRootDeserializer .needConvert(modelList, TypeFactory.defaultInstance().constructType(new TypeReference>() { }))); } diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestProtoToStringGenerator.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestProtoToStringGenerator.java index 9618313ab1b..d3ed28720b8 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestProtoToStringGenerator.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestProtoToStringGenerator.java @@ -17,13 +17,13 @@ package org.apache.servicecomb.codec.protobuf.internal.converter; import org.apache.servicecomb.foundation.protobuf.internal.parser.ProtoParser; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import io.protostuff.compiler.model.Proto; +import org.junit.jupiter.api.Test; public class TestProtoToStringGenerator { - static String content = "syntax = \"proto3\";\n" + static final String content = "syntax = \"proto3\";\n" + "import \"google/protobuf/any.proto\";\n" + "package org.apache.servicecomb.foundation.protobuf.internal.model;\n" + "\n" @@ -78,6 +78,6 @@ public void protoToString() { Proto proto = protoParser.parseFromContent(content); String newContent = new ProtoToStringGenerator(proto).protoToString(); - Assert.assertEquals(content, newContent); + Assertions.assertEquals(content, newContent); } } diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java index 822d4d8610f..141b7cf4b2c 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodec.java @@ -35,11 +35,13 @@ import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchema; import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchemaPojo; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.InvocationRuntimeType; import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.MicroserviceVersionsMeta; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.foundation.protobuf.internal.ProtoConst; +import org.apache.servicecomb.core.executor.ExecutorManager; import org.apache.servicecomb.foundation.test.scaffolding.model.Color; import org.apache.servicecomb.foundation.test.scaffolding.model.Empty; import org.apache.servicecomb.foundation.test.scaffolding.model.People; @@ -51,62 +53,55 @@ import org.apache.servicecomb.swagger.generator.pojo.PojoSwaggerGenerator; import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator; import org.apache.servicecomb.swagger.invocation.InvocationType; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.Swagger; -import mockit.Expectations; -import mockit.Injectable; - /** * SchemaMetaCodec test cases. This test cases covers POJO invoker and producer. */ @SuppressWarnings({"rawtypes", "unchecked"}) public class TestSchemaMetaCodec { - @Injectable - private MicroserviceMeta providerMicroserviceMeta; - - @Injectable - private MicroserviceMeta consumerMicroserviceMeta; private SchemaMeta providerSchemaMeta; private SchemaMeta consumerSchemaMeta; - @Before + @BeforeEach public void setUp() { ProtobufManager.clear(); } private void mockSchemaMeta(String schemaId, AbstractSwaggerGenerator swaggerGenerator, Object producerInstance) throws Exception { - new Expectations() { - { - providerMicroserviceMeta.getMicroserviceName(); - result = "test"; - providerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID); - result = null; - consumerMicroserviceMeta.getMicroserviceName(); - result = "test"; - consumerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID); - result = null; - } - }; - Swagger swagger = swaggerGenerator.generate(); + MicroserviceVersionsMeta microserviceVersionsMeta = Mockito.mock(MicroserviceVersionsMeta.class); + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getExecutorManager()).thenReturn(executorManager); + + MicroserviceMeta providerMicroserviceMeta = Mockito.mock(MicroserviceMeta.class); + Mockito.when(providerMicroserviceMeta.getScbEngine()).thenReturn(scbEngine); + Mockito.when(providerMicroserviceMeta.getMicroserviceVersionsMeta()).thenReturn(microserviceVersionsMeta); + Mockito.when(providerMicroserviceMeta.getMicroserviceName()).thenReturn("test"); + Mockito.when(providerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID)).thenReturn(null); + + MicroserviceMeta consumerMicroserviceMeta = Mockito.mock(MicroserviceMeta.class); + Mockito.when(consumerMicroserviceMeta.getScbEngine()).thenReturn(scbEngine); + Mockito.when(consumerMicroserviceMeta.getMicroserviceVersionsMeta()).thenReturn(microserviceVersionsMeta); + Mockito.when(consumerMicroserviceMeta.getMicroserviceName()).thenReturn("test"); + Mockito.when(consumerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID)).thenReturn(null); SwaggerEnvironment swaggerEnvironment = new SwaggerEnvironment(); - - providerSchemaMeta = new SchemaMeta(providerMicroserviceMeta, schemaId, swagger); - SwaggerProducer swaggerProducer = swaggerEnvironment.createProducer(producerInstance, swagger); + SwaggerProducer swaggerProducer = swaggerEnvironment.createProducer(producerInstance); + providerSchemaMeta = new SchemaMeta(providerMicroserviceMeta, schemaId, swaggerProducer.getSwagger()); for (SwaggerProducerOperation producerOperation : swaggerProducer.getAllOperations()) { OperationMeta operationMeta = providerSchemaMeta.ensureFindOperation(producerOperation.getOperationId()); operationMeta.setSwaggerProducerOperation(producerOperation); } - consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, schemaId, swagger); + consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, schemaId, swaggerProducer.getSwagger()); } @Test @@ -123,18 +118,18 @@ public void testProtoSchemaOperationUserPOJO() throws Exception { private Invocation mockInvocation(String operation, InvocationType invocationType) { OperationMeta operationMeta; - boolean isConsumer; + boolean isProvider; Invocation invocation = Mockito.mock(Invocation.class); InvocationRuntimeType invocationRuntimeType; if (InvocationType.CONSUMER == invocationType) { operationMeta = consumerSchemaMeta.getOperations().get(operation); - isConsumer = true; + isProvider = false; Mockito.when(invocation.getSchemaMeta()).thenReturn(consumerSchemaMeta); invocationRuntimeType = operationMeta.buildBaseConsumerRuntimeType(); } else { operationMeta = providerSchemaMeta.getOperations().get(operation); - isConsumer = false; + isProvider = true; Mockito.when(invocation.getSchemaMeta()).thenReturn(providerSchemaMeta); invocationRuntimeType = operationMeta.buildBaseProviderRuntimeType(); } @@ -148,13 +143,13 @@ private Invocation mockInvocation(String operation, InvocationType invocationTyp Mockito.when(invocation.getInvocationType()).thenReturn(invocationType); Mockito.when(invocation.getMicroserviceMeta()).thenReturn(microserviceMeta); - Mockito.when(invocation.isConsumer()).thenReturn(isConsumer); + Mockito.when(invocation.isProducer()).thenReturn(isProvider); return invocation; } private void testProtoSchemaOperationUserImpl() throws IOException { Invocation consumerInvocation = mockInvocation("user", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("user", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("user", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -178,8 +173,8 @@ private void testProtoSchemaOperationUserImpl() throws IOException { RequestRootDeserializer requestDeserializer = providerOperationProtobuf.getRequestRootDeserializer(); Map decodedUserArgs = requestDeserializer.deserialize(values); - Assert.assertEquals(user.name, ((User) decodedUserArgs.get("user")).name); - Assert.assertEquals(user.friends.get(0).name, ((User) decodedUserArgs.get("user")).friends.get(0).name); + Assertions.assertEquals(user.name, ((User) decodedUserArgs.get("user")).name); + Assertions.assertEquals(user.friends.get(0).name, ((User) decodedUserArgs.get("user")).friends.get(0).name); // write request map (pojo) args = new HashMap<>(); @@ -194,8 +189,8 @@ private void testProtoSchemaOperationUserImpl() throws IOException { values = requestSerializer.serialize(args); decodedUserArgs = requestDeserializer.deserialize(values); - Assert.assertEquals(user.name, ((User) decodedUserArgs.get("user")).name); - Assert.assertEquals(user.friends.get(0).name, ((User) decodedUserArgs.get("user")).friends.get(0).name); + Assertions.assertEquals(user.name, ((User) decodedUserArgs.get("user")).name); + Assertions.assertEquals(user.friends.get(0).name, ((User) decodedUserArgs.get("user")).friends.get(0).name); // response message ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200); @@ -203,16 +198,16 @@ private void testProtoSchemaOperationUserImpl() throws IOException { ResponseRootDeserializer responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200); User decodedUser = (User) responseDeserializer .deserialize(values, TypeFactory.defaultInstance().constructType(User.class)); - Assert.assertEquals(user.name, decodedUser.name); - Assert.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name); + Assertions.assertEquals(user.name, decodedUser.name); + Assertions.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name); user.friends = new ArrayList<>(); values = responseSerializer.serialize(user); decodedUser = (User) responseDeserializer .deserialize(values, TypeFactory.defaultInstance().constructType(User.class)); - Assert.assertEquals(user.name, decodedUser.name); + Assertions.assertEquals(user.name, decodedUser.name); // proto buffer encode and decode empty list to be null - Assert.assertEquals(null, decodedUser.friends); + Assertions.assertNull(decodedUser.friends); } @Test @@ -229,7 +224,7 @@ public void testProtoSchemaOperationmapUserPOJO() throws Exception { private void testProtoSchemaOperationmapUserImpl(boolean isPojo) throws IOException { Invocation consumerInvocation = mockInvocation("mapUser", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("mapUser", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("mapUser", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -253,7 +248,7 @@ private void testProtoSchemaOperationmapUserImpl(boolean isPojo) throws IOExcept args.put("users", userMap); if (isPojo) { Map swaggerArgs = new HashMap<>(1); - swaggerArgs.put("users", args); + swaggerArgs.put("listListUserBody", args); values = requestSerializer.serialize(swaggerArgs); } else { values = requestSerializer.serialize(args); @@ -261,31 +256,33 @@ private void testProtoSchemaOperationmapUserImpl(boolean isPojo) throws IOExcept RequestRootDeserializer requestDeserializer = providerOperationProtobuf.getRequestRootDeserializer(); Map decodedUserArgs = requestDeserializer.deserialize(values); if (isPojo) { - decodedUserArgs = (Map) decodedUserArgs.get("users"); - Assert.assertEquals(user.name, + decodedUserArgs = (Map) decodedUserArgs.get("mapUserBody"); + Assertions.assertEquals(user.name, ((Map>) decodedUserArgs.get("users")).get("test").get("name")); - Assert.assertEquals(user.friends.get(0).name, + Assertions.assertEquals(user.friends.get(0).name, ((List>) ((Map>) decodedUserArgs.get("users")).get("test") .get("friends")).get(0).get("name")); } else { - Assert.assertEquals(user.name, ((Map) decodedUserArgs.get("users")).get("test").name); - Assert.assertEquals(user.friends.get(0).name, + Assertions.assertEquals(user.name, ((Map) decodedUserArgs.get("users")).get("test").name); + Assertions.assertEquals(user.friends.get(0).name, ((Map) decodedUserArgs.get("users")).get("test").friends.get(0).name); } // response message ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200); values = responseSerializer.serialize(userMap); ResponseRootDeserializer responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200); - Map decodedUser = (Map) responseDeserializer.deserialize(values, ProtoConst.MAP_TYPE); - Assert.assertEquals(user.name, decodedUser.get("test").name); - Assert.assertEquals(user.friends.get(0).name, decodedUser.get("test").friends.get(0).name); + Map decodedUser = (Map) responseDeserializer.deserialize(values, + TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, User.class)); + Assertions.assertEquals(user.name, decodedUser.get("test").name); + Assertions.assertEquals(user.friends.get(0).name, decodedUser.get("test").friends.get(0).name); user.friends = new ArrayList<>(); values = responseSerializer.serialize(userMap); - decodedUser = (Map) responseDeserializer.deserialize(values, ProtoConst.MAP_TYPE); - Assert.assertEquals(user.name, decodedUser.get("test").name); + decodedUser = (Map) responseDeserializer.deserialize(values, + TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, User.class)); + Assertions.assertEquals(user.name, decodedUser.get("test").name); // proto buffer encode and decode empty list to be null - Assert.assertEquals(null, decodedUser.get("test").friends); + Assertions.assertNull(decodedUser.get("test").friends); } @Test @@ -302,7 +299,7 @@ public void testProtoSchemaOperationBasePOJO() throws Exception { private void testProtoSchemaOperationBaseImpl(boolean isPojo) throws IOException { Invocation consumerInvocation = mockInvocation("base", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("base", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("base", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -346,31 +343,31 @@ private void testProtoSchemaOperationBaseImpl(boolean isPojo) throws IOException Map decodedSwaggerArgs = requestDeserializer.deserialize(values); Map decodedArgs; if (isPojo) { - Assert.assertEquals(1, decodedSwaggerArgs.size()); + Assertions.assertEquals(1, decodedSwaggerArgs.size()); decodedArgs = (Map) decodedSwaggerArgs.get("baseBody"); } else { decodedArgs = decodedSwaggerArgs; } - Assert.assertEquals(boolValue, decodedArgs.get("boolValue")); - Assert.assertEquals(iValue, decodedArgs.get("iValue")); - Assert.assertEquals(lValue, decodedArgs.get("lValue")); - Assert.assertEquals(fValue, decodedArgs.get("fValue")); - Assert.assertEquals(dValue, decodedArgs.get("dValue")); + Assertions.assertEquals(boolValue, decodedArgs.get("boolValue")); + Assertions.assertEquals(iValue, decodedArgs.get("iValue")); + Assertions.assertEquals(lValue, decodedArgs.get("lValue")); + Assertions.assertEquals(fValue, decodedArgs.get("fValue")); + Assertions.assertEquals(dValue, decodedArgs.get("dValue")); if (isPojo) { - Assert.assertEquals(2, ((List) decodedArgs.get("iArray")).size()); - Assert.assertEquals(60, (((List) decodedArgs.get("iArray")).get(0).intValue())); - Assert.assertEquals(70, (((List) decodedArgs.get("iArray")).get(1).intValue())); - Assert.assertEquals(color.ordinal(), decodedArgs.get("color")); - Assert.assertEquals(date.getTime(), decodedArgs.get("date")); - Assert.assertEquals(localDate.getLong(ChronoField.EPOCH_DAY), decodedArgs.get("localDate")); - Assert.assertEquals(true, ((Map) decodedArgs.get("empty")).isEmpty()); + Assertions.assertEquals(2, ((List) decodedArgs.get("iArray")).size()); + Assertions.assertEquals(60, (((List) decodedArgs.get("iArray")).get(0).intValue())); + Assertions.assertEquals(70, (((List) decodedArgs.get("iArray")).get(1).intValue())); + Assertions.assertEquals(color.ordinal(), decodedArgs.get("color")); + Assertions.assertEquals(date.getTime(), decodedArgs.get("date")); + Assertions.assertEquals(localDate.getLong(ChronoField.EPOCH_DAY), decodedArgs.get("localDate")); + Assertions.assertTrue(((Map) decodedArgs.get("empty")).isEmpty()); } else { - Assert.assertArrayEquals(iArray, (int[]) decodedArgs.get("iArray")); - Assert.assertEquals(color, decodedArgs.get("color")); - Assert.assertEquals(date, decodedArgs.get("date")); - Assert.assertTrue(decodedArgs.get("localDate") instanceof LocalDate); - Assert.assertEquals(localDate, decodedArgs.get("localDate")); - Assert.assertTrue(decodedArgs.get("empty") instanceof Empty); + Assertions.assertArrayEquals(iArray, (int[]) decodedArgs.get("iArray")); + Assertions.assertEquals(color, decodedArgs.get("color")); + Assertions.assertEquals(date, decodedArgs.get("date")); + Assertions.assertTrue(decodedArgs.get("localDate") instanceof LocalDate); + Assertions.assertEquals(localDate, decodedArgs.get("localDate")); + Assertions.assertTrue(decodedArgs.get("empty") instanceof Empty); } // default value testing @@ -387,16 +384,16 @@ private void testProtoSchemaOperationBaseImpl(boolean isPojo) throws IOException args.put("empty", null); values = requestSerializer.serialize(args); decodedArgs = requestDeserializer.deserialize(values); - Assert.assertEquals(null, decodedArgs.get("boolValue")); - Assert.assertEquals(null, decodedArgs.get("iValue")); - Assert.assertEquals(null, decodedArgs.get("lValue")); - Assert.assertEquals(null, decodedArgs.get("fValue")); - Assert.assertEquals(null, decodedArgs.get("dValue")); - Assert.assertEquals(null, decodedArgs.get("iArray")); - Assert.assertEquals(null, decodedArgs.get("color")); - Assert.assertEquals(null, decodedArgs.get("localDate")); - Assert.assertEquals(null, decodedArgs.get("date")); - Assert.assertEquals(null, decodedArgs.get("empty")); + Assertions.assertNull(decodedArgs.get("boolValue")); + Assertions.assertNull(decodedArgs.get("iValue")); + Assertions.assertNull(decodedArgs.get("lValue")); + Assertions.assertNull(decodedArgs.get("fValue")); + Assertions.assertNull(decodedArgs.get("dValue")); + Assertions.assertNull(decodedArgs.get("iArray")); + Assertions.assertNull(decodedArgs.get("color")); + Assertions.assertNull(decodedArgs.get("localDate")); + Assertions.assertNull(decodedArgs.get("date")); + Assertions.assertNull(decodedArgs.get("empty")); // response message ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200); @@ -404,7 +401,7 @@ private void testProtoSchemaOperationBaseImpl(boolean isPojo) throws IOException ResponseRootDeserializer responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200); Object decodedValue = responseDeserializer .deserialize(values, TypeFactory.defaultInstance().constructType(int.class)); - Assert.assertEquals(30, (int) decodedValue); + Assertions.assertEquals(30, (int) decodedValue); } @Test @@ -421,7 +418,7 @@ public void testProtoSchemaOperationlistListUserPOJO() throws Exception { private void testProtoSchemaOperationlistListUserImpl(boolean isPojo) throws IOException { Invocation consumerInvocation = mockInvocation("listListUser", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("listListUser", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("listListUser", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -447,7 +444,7 @@ private void testProtoSchemaOperationlistListUserImpl(boolean isPojo) throws IOE if (isPojo) { Map swaggerArgs = new HashMap<>(); - swaggerArgs.put("value", args); + swaggerArgs.put("listListUserBody", args); values = requestSerializer.serialize(swaggerArgs); } else { values = requestSerializer.serialize(args); @@ -456,27 +453,27 @@ private void testProtoSchemaOperationlistListUserImpl(boolean isPojo) throws IOE Map decodedSwaggerArgs = requestDeserializer.deserialize(values); Map decodedArgs; if (isPojo) { - Assert.assertEquals(1, decodedSwaggerArgs.size()); - decodedArgs = (Map) decodedSwaggerArgs.get("value"); + Assertions.assertEquals(1, decodedSwaggerArgs.size()); + decodedArgs = (Map) decodedSwaggerArgs.get("listListUserBody"); } else { decodedArgs = decodedSwaggerArgs; } List> listOfUsersRaw = (List>) decodedArgs.get("value"); - Assert.assertEquals(1, listOfUsersRaw.size()); + Assertions.assertEquals(1, listOfUsersRaw.size()); List mapUsersRaw = (List) listOfUsersRaw.get(0); - Assert.assertEquals(1, mapUsersRaw.size()); + Assertions.assertEquals(1, mapUsersRaw.size()); if (isPojo) { Map userMap = (Map) mapUsersRaw.get(0); - Assert.assertEquals("user", userMap.get("name")); + Assertions.assertEquals("user", userMap.get("name")); // proto buffer encode and decode empty list to be null friends = (List) userMap.get("friends"); Map friendMap = (Map) friends.get(0); - Assert.assertEquals("friend", friendMap.get("name")); + Assertions.assertEquals("friend", friendMap.get("name")); } else { user = (User) mapUsersRaw.get(0); - Assert.assertEquals("user", user.name); + Assertions.assertEquals("user", user.name); // proto buffer encode and decode empty list to be null - Assert.assertEquals("friend", user.friends.get(0).name); + Assertions.assertEquals("friend", user.friends.get(0).name); } } @@ -494,7 +491,7 @@ public void testProtoSchemaOperationObjPOJO() throws Exception { private void testProtoSchemaOperationObjImpl(boolean isPojo) throws IOException { Invocation consumerInvocation = mockInvocation("obj", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("obj", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("obj", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -511,7 +508,7 @@ private void testProtoSchemaOperationObjImpl(boolean isPojo) throws IOException RequestRootDeserializer requestDeserializer = providerOperationProtobuf.getRequestRootDeserializer(); Map decodedArgs = requestDeserializer.deserialize(values); int result = (int) decodedArgs.get("value"); - Assert.assertEquals(2, result); + Assertions.assertEquals(2, result); User user = new User(); user.name = "user"; @@ -524,11 +521,11 @@ private void testProtoSchemaOperationObjImpl(boolean isPojo) throws IOException values = requestSerializer.serialize(args); decodedArgs = requestDeserializer.deserialize(values); Map userMap = (Map) decodedArgs.get("value"); - Assert.assertEquals("user", userMap.get("name")); + Assertions.assertEquals("user", userMap.get("name")); // proto buffer encode and decode empty list to be null friends = (List) userMap.get("friends"); Map friendMap = (Map) friends.get(0); - Assert.assertEquals("friend", friendMap.get("name")); + Assertions.assertEquals("friend", friendMap.get("name")); args.clear(); People people = new People(); @@ -542,8 +539,8 @@ private void testProtoSchemaOperationObjImpl(boolean isPojo) throws IOException values = requestSerializer.serialize(args); decodedArgs = requestDeserializer.deserialize(values); people = (People) decodedArgs.get("value"); - Assert.assertEquals("user", people.name); + Assertions.assertEquals("user", people.name); // proto buffer encode and decode empty list to be null - Assert.assertEquals("friend", people.friends.get(0).name); + Assertions.assertEquals("friend", people.friends.get(0).name); } } diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java index c638e8c85b9..2a861d202be 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSchemaMetaCodecRestTemplate.java @@ -32,10 +32,13 @@ import org.apache.servicecomb.codec.protobuf.definition.ResponseRootSerializer; import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchema; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.InvocationRuntimeType; import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.MicroserviceVersionsMeta; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.core.executor.ExecutorManager; import org.apache.servicecomb.foundation.test.scaffolding.model.Color; import org.apache.servicecomb.foundation.test.scaffolding.model.Empty; import org.apache.servicecomb.foundation.test.scaffolding.model.User; @@ -44,75 +47,70 @@ import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator; import org.apache.servicecomb.swagger.invocation.InvocationType; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.Swagger; -import mockit.Expectations; -import mockit.Injectable; - /** * SchemaMetaCodec test cases. This test cases covers RestTemplate invoker and producer. */ public class TestSchemaMetaCodecRestTemplate { - @Injectable - private MicroserviceMeta providerMicroserviceMeta; - - @Injectable - private MicroserviceMeta consumerMicroserviceMeta; private SchemaMeta providerSchemaMeta; private SchemaMeta consumerSchemaMeta; - @Before + @BeforeEach public void setUp() { ProtobufManager.clear(); + MicroserviceVersionsMeta microserviceVersionsMeta = Mockito.mock(MicroserviceVersionsMeta.class); + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getExecutorManager()).thenReturn(executorManager); + + MicroserviceMeta providerMicroserviceMeta = Mockito.mock(MicroserviceMeta.class); + Mockito.when(providerMicroserviceMeta.getScbEngine()).thenReturn(scbEngine); + Mockito.when(providerMicroserviceMeta.getMicroserviceVersionsMeta()).thenReturn(microserviceVersionsMeta); + Mockito.when(providerMicroserviceMeta.getMicroserviceName()).thenReturn("test"); + Mockito.when(providerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID)).thenReturn(null); + + MicroserviceMeta consumerMicroserviceMeta = Mockito.mock(MicroserviceMeta.class); + Mockito.when(consumerMicroserviceMeta.getScbEngine()).thenReturn(scbEngine); + Mockito.when(consumerMicroserviceMeta.getMicroserviceVersionsMeta()).thenReturn(microserviceVersionsMeta); + Mockito.when(consumerMicroserviceMeta.getMicroserviceName()).thenReturn("test"); + Mockito.when(consumerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID)).thenReturn(null); - new Expectations() { - { - providerMicroserviceMeta.getMicroserviceName(); - result = "test"; - providerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID); - result = null; - consumerMicroserviceMeta.getMicroserviceName(); - result = "test"; - consumerMicroserviceMeta.getExtData(ProtobufManager.EXT_ID); - result = null; - } - }; SpringmvcSwaggerGenerator swaggerGenerator = new SpringmvcSwaggerGenerator(ProtoSchema.class); - Swagger swagger = swaggerGenerator.generate(); SwaggerEnvironment swaggerEnvironment = new SwaggerEnvironment(); - providerSchemaMeta = new SchemaMeta(providerMicroserviceMeta, "ProtoSchema", swagger); - SwaggerProducer swaggerProducer = swaggerEnvironment.createProducer(new ProtoSchema(), swagger); + SwaggerProducer swaggerProducer = swaggerEnvironment.createProducer(new ProtoSchema()); + providerSchemaMeta = new SchemaMeta(providerMicroserviceMeta, "ProtoSchema", swaggerProducer.getSwagger()); + for (SwaggerProducerOperation producerOperation : swaggerProducer.getAllOperations()) { OperationMeta operationMeta = providerSchemaMeta.ensureFindOperation(producerOperation.getOperationId()); operationMeta.setSwaggerProducerOperation(producerOperation); } - consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, "ProtoSchema", swagger); + consumerSchemaMeta = new SchemaMeta(consumerMicroserviceMeta, "ProtoSchema", swaggerProducer.getSwagger()); } private Invocation mockInvocation(String operation, InvocationType invocationType) { OperationMeta operationMeta; - boolean isConsumer; + boolean isProvider; Invocation invocation = Mockito.mock(Invocation.class); InvocationRuntimeType invocationRuntimeType; if (InvocationType.CONSUMER == invocationType) { operationMeta = consumerSchemaMeta.getOperations().get(operation); - isConsumer = true; + isProvider = false; Mockito.when(invocation.getSchemaMeta()).thenReturn(consumerSchemaMeta); invocationRuntimeType = operationMeta.buildBaseConsumerRuntimeType(); } else { operationMeta = providerSchemaMeta.getOperations().get(operation); - isConsumer = false; + isProvider = true; Mockito.when(invocation.getSchemaMeta()).thenReturn(providerSchemaMeta); invocationRuntimeType = operationMeta.buildBaseProviderRuntimeType(); } @@ -126,14 +124,14 @@ private Invocation mockInvocation(String operation, InvocationType invocationTyp Mockito.when(invocation.getInvocationType()).thenReturn(invocationType); Mockito.when(invocation.getMicroserviceMeta()).thenReturn(microserviceMeta); - Mockito.when(invocation.isConsumer()).thenReturn(isConsumer); + Mockito.when(invocation.isProducer()).thenReturn(isProvider); return invocation; } @Test public void testProtoSchemaOperationUser() throws Exception { Invocation consumerInvocation = mockInvocation("user", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("user", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("user", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -157,8 +155,8 @@ public void testProtoSchemaOperationUser() throws Exception { RequestRootDeserializer requestDeserializer = providerOperationProtobuf.getRequestRootDeserializer(); Map decodedUserArgs = requestDeserializer.deserialize(values); - Assert.assertEquals(user.name, ((User) decodedUserArgs.get("user")).name); - Assert.assertEquals(user.friends.get(0).name, ((User) decodedUserArgs.get("user")).friends.get(0).name); + Assertions.assertEquals(user.name, ((User) decodedUserArgs.get("user")).name); + Assertions.assertEquals(user.friends.get(0).name, ((User) decodedUserArgs.get("user")).friends.get(0).name); // response message ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200); @@ -166,23 +164,23 @@ public void testProtoSchemaOperationUser() throws Exception { ResponseRootDeserializer responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200); User decodedUser = (User) responseDeserializer .deserialize(values, TypeFactory.defaultInstance().constructType(User.class)); - Assert.assertEquals(user.name, decodedUser.name); - Assert.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name); + Assertions.assertEquals(user.name, decodedUser.name); + Assertions.assertEquals(user.friends.get(0).name, decodedUser.friends.get(0).name); user.friends = new ArrayList<>(); values = responseSerializer.serialize(user); decodedUser = (User) responseDeserializer .deserialize(values, TypeFactory.defaultInstance().constructType(User.class)); - Assert.assertEquals(user.name, decodedUser.name); + Assertions.assertEquals(user.name, decodedUser.name); // proto buffer encode and decode empty list to be null - Assert.assertEquals(null, decodedUser.friends); + Assertions.assertNull(decodedUser.friends); } @Test @SuppressWarnings({"rawtypes", "unchecked"}) public void testProtoSchemaOperationBase() throws Exception { Invocation consumerInvocation = mockInvocation("base", InvocationType.CONSUMER); - Invocation providerInvocation = mockInvocation("base", InvocationType.PRODUCER); + Invocation providerInvocation = mockInvocation("base", InvocationType.PROVIDER); OperationProtobuf providerOperationProtobuf = ProtobufManager .getOrCreateOperation(providerInvocation); @@ -218,17 +216,17 @@ public void testProtoSchemaOperationBase() throws Exception { values = requestSerializer.serialize(args); RequestRootDeserializer requestDeserializer = providerOperationProtobuf.getRequestRootDeserializer(); Map decodedArgs = requestDeserializer.deserialize(values); - Assert.assertEquals(boolValue, decodedArgs.get("boolValue")); - Assert.assertEquals(iValue, decodedArgs.get("iValue")); - Assert.assertEquals(lValue, decodedArgs.get("lValue")); - Assert.assertEquals(fValue, decodedArgs.get("fValue")); - Assert.assertEquals(dValue, decodedArgs.get("dValue")); - Assert.assertArrayEquals(iArray, (int[]) decodedArgs.get("iArray")); - Assert.assertEquals(color, decodedArgs.get("color")); - Assert.assertEquals(date, decodedArgs.get("date")); - Assert.assertTrue(decodedArgs.get("localDate") instanceof LocalDate); - Assert.assertEquals(localDate, decodedArgs.get("localDate")); - Assert.assertTrue(decodedArgs.get("empty") instanceof Empty); + Assertions.assertEquals(boolValue, decodedArgs.get("boolValue")); + Assertions.assertEquals(iValue, decodedArgs.get("iValue")); + Assertions.assertEquals(lValue, decodedArgs.get("lValue")); + Assertions.assertEquals(fValue, decodedArgs.get("fValue")); + Assertions.assertEquals(dValue, decodedArgs.get("dValue")); + Assertions.assertArrayEquals(iArray, (int[]) decodedArgs.get("iArray")); + Assertions.assertEquals(color, decodedArgs.get("color")); + Assertions.assertEquals(date, decodedArgs.get("date")); + Assertions.assertTrue(decodedArgs.get("localDate") instanceof LocalDate); + Assertions.assertEquals(localDate, decodedArgs.get("localDate")); + Assertions.assertTrue(decodedArgs.get("empty") instanceof Empty); // default value testing args.put("boolValue", false); @@ -244,16 +242,16 @@ public void testProtoSchemaOperationBase() throws Exception { args.put("empty", null); values = requestSerializer.serialize(args); decodedArgs = requestDeserializer.deserialize(values); - Assert.assertEquals(null, decodedArgs.get("boolValue")); - Assert.assertEquals(null, decodedArgs.get("iValue")); - Assert.assertEquals(null, decodedArgs.get("lValue")); - Assert.assertEquals(null, decodedArgs.get("fValue")); - Assert.assertEquals(null, decodedArgs.get("dValue")); - Assert.assertEquals(null, decodedArgs.get("iArray")); - Assert.assertEquals(null, decodedArgs.get("color")); - Assert.assertEquals(null, decodedArgs.get("localDate")); - Assert.assertEquals(null, decodedArgs.get("date")); - Assert.assertEquals(null, decodedArgs.get("empty")); + Assertions.assertNull(decodedArgs.get("boolValue")); + Assertions.assertNull(decodedArgs.get("iValue")); + Assertions.assertNull(decodedArgs.get("lValue")); + Assertions.assertNull(decodedArgs.get("fValue")); + Assertions.assertNull(decodedArgs.get("dValue")); + Assertions.assertNull(decodedArgs.get("iArray")); + Assertions.assertNull(decodedArgs.get("color")); + Assertions.assertNull(decodedArgs.get("localDate")); + Assertions.assertNull(decodedArgs.get("date")); + Assertions.assertNull(decodedArgs.get("empty")); // response message ResponseRootSerializer responseSerializer = providerOperationProtobuf.findResponseRootSerializer(200); @@ -261,6 +259,6 @@ public void testProtoSchemaOperationBase() throws Exception { ResponseRootDeserializer responseDeserializer = consumerOperationProtobuf.findResponseRootDeserializer(200); Object decodedValue = responseDeserializer .deserialize(values, TypeFactory.defaultInstance().constructType(int.class)); - Assert.assertEquals(30, (int) decodedValue); + Assertions.assertEquals(30, (int) decodedValue); } } diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSwaggerToProtoGenerator.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSwaggerToProtoGenerator.java index 478ca495d55..535404f7bc0 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSwaggerToProtoGenerator.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/TestSwaggerToProtoGenerator.java @@ -18,43 +18,44 @@ import java.io.IOException; import java.net.URL; +import java.nio.charset.StandardCharsets; import org.apache.commons.io.IOUtils; import org.apache.servicecomb.codec.protobuf.internal.converter.model.ProtoSchema; import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import io.protostuff.compiler.model.Proto; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; public class TestSwaggerToProtoGenerator { @Test public void convert() throws IOException { URL url = TestSwaggerToProtoGenerator.class.getClassLoader().getResource("ProtoSchema.proto"); - String protoContent = IOUtils.toString(url, "UTF-8"); + String protoContent = IOUtils.toString(url, StandardCharsets.UTF_8); int idx = protoContent.indexOf("syntax = "); protoContent = protoContent.substring(idx); SpringmvcSwaggerGenerator swaggerGenerator = new SpringmvcSwaggerGenerator(ProtoSchema.class); - Swagger swagger = swaggerGenerator.generate(); + OpenAPI swagger = swaggerGenerator.generate(); SwaggerToProtoGenerator generator = new SwaggerToProtoGenerator("a.b", swagger); Proto proto = generator.convert(); - Assert.assertEquals(protoContent.replaceAll("\r\n", "\n"), + Assertions.assertEquals(protoContent.replaceAll("\r\n", "\n"), new ProtoToStringGenerator(proto).protoToString().replaceAll("\r\n", "\n")); } @Test public void testEscape() { - Assert.assertEquals("hello_my_service", SwaggerToProtoGenerator.escapeMessageName("hello.my.service")); - Assert.assertEquals("hello_my_service", SwaggerToProtoGenerator.escapeMessageName("hello_my_service")); - Assert.assertEquals("hello.my_service", SwaggerToProtoGenerator.escapePackageName("hello.my-service")); - Assert.assertEquals("hello.test.test", SwaggerToProtoGenerator.escapePackageName("hello.test.test")); - Assert.assertEquals("hello_my.test.test", SwaggerToProtoGenerator.escapePackageName("hello:my.test.test")); - Assert.assertEquals(false, SwaggerToProtoGenerator.isValidEnum("hello.test.test")); - Assert.assertEquals(false, SwaggerToProtoGenerator.isValidEnum("hello.my-service")); - Assert.assertEquals(true, SwaggerToProtoGenerator.isValidEnum("My_ENum")); + Assertions.assertEquals("hello_my_service", SwaggerToProtoGenerator.escapeMessageName("hello.my.service")); + Assertions.assertEquals("hello_my_service", SwaggerToProtoGenerator.escapeMessageName("hello_my_service")); + Assertions.assertEquals("hello.my_service", SwaggerToProtoGenerator.escapePackageName("hello.my-service")); + Assertions.assertEquals("hello.test.test", SwaggerToProtoGenerator.escapePackageName("hello.test.test")); + Assertions.assertEquals("hello_my.test.test", SwaggerToProtoGenerator.escapePackageName("hello:my.test.test")); + Assertions.assertFalse(SwaggerToProtoGenerator.isValidEnum("hello.test.test")); + Assertions.assertFalse(SwaggerToProtoGenerator.isValidEnum("hello.my-service")); + Assertions.assertTrue(SwaggerToProtoGenerator.isValidEnum("My_ENum")); } } diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchema.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchema.java index ae4f2dae190..169e742c9b5 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchema.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchema.java @@ -30,12 +30,16 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.ws.rs.core.MediaType; @RequestMapping(path = "/") public class ProtoSchema implements ProtoSchemaIntf { - @ApiResponses(value = {@ApiResponse(code = 444, response = Color.class, message = "xxx")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "444", content = @Content(schema = @Schema(implementation = Color.class)), description = "xxx")}) @GetMapping(path = "/base") public int base(boolean boolValue, int iValue, long lValue, float fValue, double dValue, String sValue, int[] iArray, Color color, @@ -174,4 +178,9 @@ public Map>> mapMapMapString( public FieldNeedWrap fieldNeedWrap(@RequestBody FieldNeedWrap fieldNeedWrap) { return fieldNeedWrap; } + + @PostMapping(path = "/testTextPlain", consumes = MediaType.TEXT_PLAIN, produces = MediaType.TEXT_PLAIN) + public String testTextPlain(@RequestBody String fieldNeedWrap) { + return null; + } } diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchemaPojo.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchemaPojo.java index 8f6a61212d9..af01e2e2325 100644 --- a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchemaPojo.java +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/internal/converter/model/ProtoSchemaPojo.java @@ -26,11 +26,14 @@ import org.apache.servicecomb.foundation.test.scaffolding.model.Empty; import org.apache.servicecomb.foundation.test.scaffolding.model.User; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; public class ProtoSchemaPojo implements ProtoSchemaIntf { - @ApiResponses(value = {@ApiResponse(code = 444, response = Color.class, message = "xxx")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "444", content = @Content(schema = @Schema(implementation = Color.class)), description = "xxx")}) public int base(boolean boolValue, int iValue, long lValue, float fValue, double dValue, String sValue, int[] iArray, Color color, LocalDate localDate, Date date, Empty empty) { diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/TestSchemaCodec.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/TestSchemaCodec.java new file mode 100644 index 00000000000..9eab70ae00a --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/TestSchemaCodec.java @@ -0,0 +1,144 @@ +/* + * 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.codec.protobuf.schema; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.codec.protobuf.schema.model.DeptInfo; +import org.apache.servicecomb.codec.protobuf.schema.model.SchemaService; +import org.apache.servicecomb.codec.protobuf.schema.model.ScoreInfo; +import org.apache.servicecomb.codec.protobuf.schema.model.UserInfo; +import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager; +import org.apache.servicecomb.foundation.protobuf.ProtoMapper; +import org.apache.servicecomb.foundation.protobuf.RootDeserializer; +import org.apache.servicecomb.foundation.protobuf.RootSerializer; +import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper; +import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator; +import org.junit.jupiter.api.Test; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.NumberSchema; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.StringSchema; +import jakarta.ws.rs.core.MediaType; + +public class TestSchemaCodec { + ScopedProtobufSchemaManager manager = new ScopedProtobufSchemaManager(); + + @Test + public void test_string_schema_codec() throws Exception { + OpenAPI openAPI = new OpenAPI(); + StringSchema schema = new StringSchema(); + ProtoMapper protoMapper = manager.getOrCreateProtoMapper(openAPI, "test", "input", schema); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage("input"), + String.class); + Map arguments = new HashMap<>(); + arguments.put("value", "abcdefg"); + byte[] result = serializer.serialize(arguments); + RootDeserializer> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage("input"), String.class); + PropertyWrapper deserializedResult = deserializer.deserialize(result); + assertEquals("abcdefg", deserializedResult.getValue()); + } + + @Test + public void test_number_schema_codec() throws Exception { + OpenAPI openAPI = new OpenAPI(); + NumberSchema schema = new NumberSchema(); + ProtoMapper protoMapper = manager.getOrCreateProtoMapper(openAPI, "test", "input", schema); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage("input"), + BigDecimal.class); + Map arguments = new HashMap<>(); + BigDecimal number = new BigDecimal(10); + arguments.put("value", number); + byte[] result = serializer.serialize(arguments); + RootDeserializer> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage("input"), BigDecimal.class); + PropertyWrapper deserializedResult = deserializer.deserialize(result); + assertEquals(number, deserializedResult.getValue()); + } + + public static class User { + public String name; + } + + @Test + public void test_object_schema_codec() throws Exception { + OpenAPI openAPI = new OpenAPI(); + + ObjectSchema schema = new ObjectSchema(); + schema.setName("User"); + schema.addProperty("name", new StringSchema()); + openAPI.setComponents(new Components()); + openAPI.getComponents().addSchemas("User", schema); + + ObjectSchema ref = new ObjectSchema(); + ref.set$ref(Components.COMPONENTS_SCHEMAS_REF + "User"); + + ProtoMapper protoMapper = manager.getOrCreateProtoMapper(openAPI, "test", "input", ref); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage("input"), + User.class); + Map arguments = new HashMap<>(); + User user = new User(); + user.name = "abcdefg"; + arguments.put("value", user); + byte[] result = serializer.serialize(arguments); + RootDeserializer> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage("input"), User.class); + PropertyWrapper deserializedResult = deserializer.deserialize(result); + assertEquals("abcdefg", deserializedResult.getValue().name); + } + + @Test + public void test_springmvc_model_schema_codec_correct() throws Exception { + SpringmvcSwaggerGenerator generator = new SpringmvcSwaggerGenerator(SchemaService.class); + OpenAPI openAPI = generator.generate(); + + ProtoMapper protoMapper = manager.getOrCreateProtoMapper(openAPI, "schemaService", "input", + openAPI.getPaths().get("/testUserInfo").getPost() + .getRequestBody().getContent().get(MediaType.APPLICATION_JSON) + .getSchema()); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage("input"), + UserInfo.class); + Map arguments = new HashMap<>(); + UserInfo userInfo = new UserInfo(); + DeptInfo deptInfo = new DeptInfo(); + deptInfo.setCode("123"); + ScoreInfo scoreInfo = new ScoreInfo(); + scoreInfo.setType(233); + deptInfo.setScores(List.of(scoreInfo)); + userInfo.setSubDeptInfos(List.of(deptInfo)); + arguments.put("value", userInfo); + byte[] result = serializer.serialize(arguments); + RootDeserializer> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage("input"), UserInfo.class); + PropertyWrapper deserializedResult = deserializer.deserialize(result); + assertEquals(1, deserializedResult.getValue().getSubDeptInfos().size()); + assertEquals("123", deserializedResult.getValue().getSubDeptInfos().get(0).getCode()); + assertEquals(233, deserializedResult.getValue().getSubDeptInfos().get(0).getScores().get(0).getType()); + } +} diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/TestSchemaToProtoGenerator.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/TestSchemaToProtoGenerator.java new file mode 100644 index 00000000000..23ac41135ad --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/TestSchemaToProtoGenerator.java @@ -0,0 +1,306 @@ +/* + * 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.codec.protobuf.schema; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.apache.servicecomb.codec.protobuf.internal.converter.ProtoToStringGenerator; +import org.apache.servicecomb.codec.protobuf.schema.model.SchemaService; +import org.apache.servicecomb.swagger.generator.springmvc.SpringmvcSwaggerGenerator; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; + +import io.protostuff.compiler.model.Proto; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.ObjectSchema; +import io.swagger.v3.oas.models.media.StringSchema; +import jakarta.ws.rs.core.MediaType; + +//CHECKSTYLE:OFF +@SuppressWarnings("unused") +public class TestSchemaToProtoGenerator { + @Test + public void test_string_schema_is_correct() { + OpenAPI openAPI = new OpenAPI(); + StringSchema schema = new StringSchema(); + SchemaToProtoGenerator generator = + new SchemaToProtoGenerator("test.string", openAPI, schema, "input"); + Proto proto = generator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.string; + + //@WrapProperty + message input { + string value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + } + + @Test + public void test_object_schema_is_correct() { + OpenAPI openAPI = new OpenAPI(); + + ObjectSchema schema = new ObjectSchema(); + schema.setName("User"); + schema.addProperty("name", new StringSchema()); + openAPI.setComponents(new Components()); + openAPI.getComponents().addSchemas("User", schema); + + ObjectSchema ref = new ObjectSchema(); + ref.set$ref(Components.COMPONENTS_SCHEMAS_REF + "User"); + + SchemaToProtoGenerator generator = + new SchemaToProtoGenerator("test.object", openAPI, ref, "input"); + Proto proto = generator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.object; + + message User { + string name = 1; + } + + //@WrapProperty + message input { + User value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + } + + static class Model { + public String name; + + public int age; + } + + interface SpringMvcSchema { + @PostMapping("/testInt") + int testInt(@RequestBody int param); + + @PostMapping("/testModel") + Model testModel(@RequestBody Model model); + } + + @Test + public void test_springmvc_int_schema_correct() { + SpringmvcSwaggerGenerator generator = new SpringmvcSwaggerGenerator(SpringMvcSchema.class); + OpenAPI openAPI = generator.generate(); + + SchemaToProtoGenerator protoGenerator = + new SchemaToProtoGenerator("test.int", openAPI, + openAPI.getPaths().get("/testInt").getPost() + .getRequestBody().getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "testIntRequest"); + Proto proto = protoGenerator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.int; + + //@WrapProperty + message testIntRequest { + sint32 value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + + protoGenerator = + new SchemaToProtoGenerator("test.int", openAPI, + openAPI.getPaths().get("/testInt").getPost() + .getResponses().get("200").getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "testIntResponse"); + proto = protoGenerator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.int; + + //@WrapProperty + message testIntResponse { + sint32 value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + } + + + @Test + public void test_springmvc_model_schema_correct() { + SpringmvcSwaggerGenerator generator = new SpringmvcSwaggerGenerator(SpringMvcSchema.class); + OpenAPI openAPI = generator.generate(); + + SchemaToProtoGenerator protoGenerator = + new SchemaToProtoGenerator("test.model", openAPI, + openAPI.getPaths().get("/testModel").getPost() + .getRequestBody().getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "testModelRequest"); + Proto proto = protoGenerator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.model; + + message Model { + sint32 age = 1; + string name = 2; + } + + //@WrapProperty + message testModelRequest { + Model value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + + protoGenerator = + new SchemaToProtoGenerator("test.model", openAPI, + openAPI.getPaths().get("/testModel").getPost() + .getResponses().get("200").getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "testIntResponse"); + proto = protoGenerator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.model; + + message Model { + sint32 age = 1; + string name = 2; + } + + //@WrapProperty + message testIntResponse { + Model value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + } + + @Test + public void testNestedModelCorrect() { + SpringmvcSwaggerGenerator generator = new SpringmvcSwaggerGenerator(SchemaService.class); + OpenAPI openAPI = generator.generate(); + SchemaToProtoGenerator protoGenerator = + new SchemaToProtoGenerator("test.model", openAPI, + openAPI.getPaths().get("/testUserInfo").getPost() + .getRequestBody().getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "request"); + Proto proto = protoGenerator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.model; + + //@WrapProperty + message MapString { + map value = 1; + } + + //@WrapProperty + message ListListString { + repeated ListString value = 1; + } + + //@WrapProperty + message ListString { + repeated string value = 1; + } + + message ScoreInfo { + sint32 type = 1; + } + + message DeptInfo { + string code = 1; + string name = 2; + repeated ScoreInfo scores = 3; + } + + message UserInfo { + repeated MapString extraInfos = 1; + repeated ListListString nestedLists = 2; + repeated DeptInfo subDeptInfos = 3; + } + + //@WrapProperty + message ListScoreInfo { + repeated ScoreInfo value = 1; + } + + //@WrapProperty + message ListDeptInfo { + repeated DeptInfo value = 1; + } + + //@WrapProperty + message request { + UserInfo value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + } + + @Test + public void testListMapTypeCorrect() { + SpringmvcSwaggerGenerator generator = new SpringmvcSwaggerGenerator(SchemaService.class); + OpenAPI openAPI = generator.generate(); + SchemaToProtoGenerator protoGenerator = + new SchemaToProtoGenerator("test.model", openAPI, + openAPI.getPaths().get("/testListType").getPost() + .getRequestBody().getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "request"); + Proto proto = protoGenerator.convert(); + assertEquals(""" + syntax = "proto3"; + package test.model; + + message ScoreInfo { + sint32 type = 1; + } + + message DeptInfo { + string code = 1; + string name = 2; + repeated ScoreInfo scores = 3; + } + + //@WrapProperty + message ListScoreInfo { + repeated ScoreInfo value = 1; + } + + //@WrapProperty + message ListDeptInfo { + repeated DeptInfo value = 1; + } + + //@WrapProperty + message request { + repeated DeptInfo value = 1; + } + """.trim(), new ProtoToStringGenerator(proto).protoToString().trim()); + } + + @Test + public void testCyclicModelWrong() { + SpringmvcSwaggerGenerator generator = new SpringmvcSwaggerGenerator(SchemaService.class); + OpenAPI openAPI = generator.generate(); + SchemaToProtoGenerator protoGenerator = + new SchemaToProtoGenerator("test.model", openAPI, + openAPI.getPaths().get("/testCyclic").getPost() + .getRequestBody().getContent().get(MediaType.APPLICATION_JSON) + .getSchema(), "request"); + IllegalArgumentException throwable = Assertions.catchThrowableOfType(() -> protoGenerator.convert(), + IllegalArgumentException.class); + assertEquals("Failed to create schema request. May be cyclic object.", throwable.getMessage()); + } +} +//CHECKSTYLE:ON diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/CyclicInfo.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/CyclicInfo.java new file mode 100644 index 00000000000..ae8f2fbd5c0 --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/CyclicInfo.java @@ -0,0 +1,38 @@ +/* + * 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.codec.protobuf.schema.model; + +public class CyclicInfo { + private String name; + private CyclicInfo child; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public CyclicInfo getChild() { + return child; + } + + public void setChild(CyclicInfo child) { + this.child = child; + } +} diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/DeptInfo.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/DeptInfo.java new file mode 100644 index 00000000000..713b45e0224 --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/DeptInfo.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.codec.protobuf.schema.model; + +import java.util.List; + +public class DeptInfo { + private String name; + + private String code; + + private List scores; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public List getScores() { + return scores; + } + + public void setScores(List scores) { + this.scores = scores; + } +} diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/SchemaService.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/SchemaService.java new file mode 100644 index 00000000000..99edc87023d --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/SchemaService.java @@ -0,0 +1,38 @@ +/* + * 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.codec.protobuf.schema.model; + +import java.util.List; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/schemaService") +public class SchemaService { + @PostMapping("testUserInfo") + public void testUserInfo(@RequestBody UserInfo request) { + } + + @PostMapping("testListType") + public void testListType(@RequestBody List request) { + } + + @PostMapping("testCyclic") + public void testCyclic(@RequestBody CyclicInfo request) { + } +} diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/ScoreInfo.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/ScoreInfo.java new file mode 100644 index 00000000000..960ce778857 --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/ScoreInfo.java @@ -0,0 +1,29 @@ +/* + * 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.codec.protobuf.schema.model; + +public class ScoreInfo { + private Integer type; + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } +} diff --git a/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/UserInfo.java b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/UserInfo.java new file mode 100644 index 00000000000..37662bb32ed --- /dev/null +++ b/common/common-protobuf/src/test/java/org/apache/servicecomb/codec/protobuf/schema/model/UserInfo.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.codec.protobuf.schema.model; + +import java.util.List; +import java.util.Map; + +public class UserInfo { + private List subDeptInfos; + + private List> extraInfos; + + private List>> nestedLists; + + public List getSubDeptInfos() { + return subDeptInfos; + } + + public void setSubDeptInfos(List subDeptInfos) { + this.subDeptInfos = subDeptInfos; + } + + public List> getExtraInfos() { + return extraInfos; + } + + public void setExtraInfos(List> extraInfos) { + this.extraInfos = extraInfos; + } + + public List>> getNestedLists() { + return nestedLists; + } + + public void setNestedLists(List>> nestedLists) { + this.nestedLists = nestedLists; + } +} diff --git a/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtobuf.proto b/common/common-protobuf/src/test/proto/ModelProtobuf.proto similarity index 90% rename from common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtobuf.proto rename to common/common-protobuf/src/test/proto/ModelProtobuf.proto index 1c2cb5abf23..c1fb2ed34dd 100644 --- a/common/common-protobuf/src/test/java/io/protostuff/runtime/model/ModelProtobuf.proto +++ b/common/common-protobuf/src/test/proto/ModelProtobuf.proto @@ -5,9 +5,9 @@ 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. @@ -16,7 +16,10 @@ */ syntax = "proto3"; -package io.protostuff.runtime.model; +package proto; + +option java_package = "io.protostuff.runtime.model"; +option java_outer_classname = "ModelProtobuf"; message User{ string name = 1; diff --git a/common/common-protobuf/src/test/resources/ProtoSchema.proto b/common/common-protobuf/src/test/resources/ProtoSchema.proto index cb78e18d890..bbb1a476948 100644 --- a/common/common-protobuf/src/test/resources/ProtoSchema.proto +++ b/common/common-protobuf/src/test/resources/ProtoSchema.proto @@ -52,12 +52,12 @@ message Ref2 { //@WrapArguments message BaseRequestWrap { bool boolValue = 1; - int32 iValue = 2; - int64 lValue = 3; + sint32 iValue = 2; + sint64 lValue = 3; float fValue = 4; double dValue = 5; string sValue = 6; - repeated int32 iArray = 7; + repeated sint32 iArray = 7; Enum_2610aa5dc6cd086cf20168892802c9c765a557f4951557340ad9f0982c53e055 color = 8; int64 localDate = 9; int64 date = 10; @@ -65,13 +65,13 @@ message BaseRequestWrap { } //@WrapProperty -message BaseResponseWrap444 { - Enum_2610aa5dc6cd086cf20168892802c9c765a557f4951557340ad9f0982c53e055 value = 1; +message BaseResponseWrap200 { + sint32 value = 1; } //@WrapProperty -message BaseResponseWrap200 { - int32 value = 1; +message BaseResponseWrap444 { + Enum_2610aa5dc6cd086cf20168892802c9c765a557f4951557340ad9f0982c53e055 value = 1; } //@WrapArguments @@ -274,10 +274,20 @@ message MapUserResponseWrap200 { map value = 1; } +//@WrapArguments +message TestTextPlainRequestWrap { + string fieldNeedWrap = 1; +} + +//@WrapProperty +message TestTextPlainResponseWrap200 { + string value = 1; +} + //@WrapArguments message UserWrapInProtobufRequestWrap { - User user = 1; - int32 ivalue = 2; + sint32 ivalue = 1; + User user = 2; } //@WrapProperty @@ -422,6 +432,9 @@ service MainService { //@Rpc{"argTypeName":"Ref1","responses":{"200":{"typeName":"Ref2"}}} rpc ref (Ref1) returns (Ref2); + //@Rpc{"argTypeName":"TestTextPlainRequestWrap","responses":{"200":{"typeName":"TestTextPlainResponseWrap200"}}} + rpc testTextPlain (TestTextPlainRequestWrap) returns (TestTextPlainResponseWrap200); + //@Rpc{"argTypeName":"User","responses":{"200":{"typeName":"User"}}} rpc user (User) returns (User); diff --git a/common/common-protobuf/src/test/resources/log4j.properties b/common/common-protobuf/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/common/common-protobuf/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/common/common-rest/pom.xml b/common/common-rest/pom.xml index 7c13b6c0e0e..f1f2c84b45b 100644 --- a/common/common-rest/pom.xml +++ b/common/common-rest/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb common - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT common-rest @@ -34,6 +34,10 @@ org.apache.servicecomb java-chassis-core + + org.apache.servicecomb + common-protobuf + io.vertx @@ -47,13 +51,13 @@ test - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test @@ -65,5 +69,10 @@ swagger-generator-jaxrs test + + org.mockito + mockito-inline + test + diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java deleted file mode 100644 index 1b638a93ee2..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java +++ /dev/null @@ -1,329 +0,0 @@ -/* - * 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.common.rest; - -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.Status; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.common.rest.filter.HttpServerFilterBeforeSendResponseExecutor; -import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter; -import org.apache.servicecomb.common.rest.locator.OperationLocator; -import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractRestInvocation { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRestInvocation.class); - - public static final String UNKNOWN_OPERATION_ID = "UNKNOWN_OPERATION"; - - protected long start; - - protected RestOperationMeta restOperationMeta; - - protected Invocation invocation; - - protected HttpServletRequestEx requestEx; - - protected HttpServletResponseEx responseEx; - - protected ProduceProcessor produceProcessor; - - protected List httpServerFilters = Collections.emptyList(); - - public AbstractRestInvocation() { - this.start = System.nanoTime(); - } - - public void setHttpServerFilters(List httpServerFilters) { - this.httpServerFilters = httpServerFilters; - } - - protected void findRestOperation(MicroserviceMeta microserviceMeta) { - ServicePathManager servicePathManager = ServicePathManager.getServicePathManager(microserviceMeta); - if (servicePathManager == null) { - LOGGER.error("No schema defined for {}:{}.", microserviceMeta.getAppId(), microserviceMeta.getMicroserviceName()); - throw new InvocationException(Status.NOT_FOUND, Status.NOT_FOUND.getReasonPhrase()); - } - - OperationLocator locator = locateOperation(servicePathManager); - requestEx.setAttribute(RestConst.PATH_PARAMETERS, locator.getPathVarMap()); - this.restOperationMeta = locator.getOperation(); - } - - protected void initProduceProcessor() { - produceProcessor = restOperationMeta.ensureFindProduceProcessor(requestEx); - if (produceProcessor == null) { - LOGGER.error("Accept {} is not supported, operation={}.", requestEx.getHeader(HttpHeaders.ACCEPT), - restOperationMeta.getOperationMeta().getMicroserviceQualifiedName()); - String msg = String.format("Accept %s is not supported", requestEx.getHeader(HttpHeaders.ACCEPT)); - throw new InvocationException(Status.NOT_ACCEPTABLE, msg); - } - } - - protected void setContext() throws Exception { - String strCseContext = requestEx.getHeader(Const.CSE_CONTEXT); - if (StringUtils.isEmpty(strCseContext)) { - return; - } - - @SuppressWarnings("unchecked") - Map cseContext = - JsonUtils.readValue(strCseContext.getBytes(StandardCharsets.UTF_8), Map.class); - invocation.mergeContext(cseContext); - } - - public String getContext(String key) { - if (null == invocation || null == invocation.getContext()) { - return null; - } - - return invocation.getContext(key); - } - - protected void scheduleInvocation() { - try { - createInvocation(); - } catch (Throwable e) { - sendFailResponse(e); - return; - } - - try { - this.setContext(); - } catch (Exception e) { - LOGGER.error("failed to set invocation context", e); - sendFailResponse(e); - return; - } - - invocation.onStart(requestEx, start); - invocation.getInvocationStageTrace().startSchedule(); - OperationMeta operationMeta = restOperationMeta.getOperationMeta(); - - Holder qpsFlowControlReject = checkQpsFlowControl(operationMeta); - if (qpsFlowControlReject.value) { - return; - } - - try { - operationMeta.getExecutor().execute(() -> { - synchronized (this.requestEx) { - try { - if (isInQueueTimeout()) { - throw new InvocationException(Status.INTERNAL_SERVER_ERROR, "Timeout when processing the request."); - } - if (requestEx.getAttribute(RestConst.REST_REQUEST) != requestEx) { - // already timeout - // in this time, request maybe recycled and reused by web container, do not use requestEx - LOGGER.error("Rest request already timeout, abandon execute, method {}, operation {}.", - operationMeta.getHttpMethod(), - operationMeta.getMicroserviceQualifiedName()); - return; - } - - runOnExecutor(); - } catch (InvocationException e) { - LOGGER.error("Invocation failed, cause={}", e.getMessage()); - sendFailResponse(e); - } catch (Throwable e) { - LOGGER.error("Processing rest server request error", e); - sendFailResponse(e); - } - } - }); - } catch (Throwable e) { - LOGGER.error("failed to schedule invocation, message={}, executor={}.", e.getMessage(), e.getClass().getName()); - sendFailResponse(e); - } - } - - private Holder checkQpsFlowControl(OperationMeta operationMeta) { - Holder qpsFlowControlReject = new Holder<>(false); - @SuppressWarnings("deprecation") - Handler providerQpsFlowControlHandler = operationMeta.getProviderQpsFlowControlHandler(); - if (null != providerQpsFlowControlHandler) { - try { - providerQpsFlowControlHandler.handle(invocation, response -> { - qpsFlowControlReject.value = true; - produceProcessor = ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(); - sendResponse(response); - }); - } catch (Throwable e) { - LOGGER.error("failed to execute ProviderQpsFlowControlHandler", e); - qpsFlowControlReject.value = true; - sendFailResponse(e); - } - } - return qpsFlowControlReject; - } - - private boolean isInQueueTimeout() { - return System.nanoTime() - invocation.getInvocationStageTrace().getStart() > - invocation.getOperationMeta().getConfig().getNanoRestRequestWaitInPoolTimeout(); - } - - protected void runOnExecutor() { - invocation.onExecuteStart(); - - invoke(); - } - - protected abstract OperationLocator locateOperation(ServicePathManager servicePathManager); - - // create a invocation without args setted - protected abstract void createInvocation(); - - public void invoke() { - try { - Response response = prepareInvoke(); - if (response != null) { - sendResponseQuietly(response); - return; - } - - doInvoke(); - } catch (InvocationException e) { - LOGGER.error("Invocation failed, cause={}", e.getMessage()); - sendFailResponse(e); - } catch (Throwable e) { - LOGGER.error("Processing rest server request error", e); - sendFailResponse(e); - } - } - - protected Response prepareInvoke() throws Throwable { - this.initProduceProcessor(); - invocation.getHandlerContext().put(RestConst.REST_REQUEST, requestEx); - - invocation.getInvocationStageTrace().startServerFiltersRequest(); - for (HttpServerFilter filter : httpServerFilters) { - if (filter.enabled()) { - Response response = filter.afterReceiveRequest(invocation, requestEx); - if (response != null) { - return response; - } - } - } - - return null; - } - - protected void doInvoke() throws Throwable { - invocation.onStartHandlersRequest(); - invocation.next(resp -> sendResponseQuietly(resp)); - } - - public void sendFailResponse(Throwable throwable) { - if (produceProcessor == null) { - produceProcessor = ProduceProcessorManager.INSTANCE.findDefaultProcessor(); - } - - Response response = Response.createProducerFail(throwable); - sendResponseQuietly(response); - } - - protected void sendResponseQuietly(Response response) { - if (invocation != null) { - invocation.getInvocationStageTrace().finishHandlersResponse(); - } - try { - sendResponse(response); - } catch (Throwable e) { - LOGGER.error("Failed to send rest response, operation:{}, request uri:{}", - getMicroserviceQualifiedName(), requestEx.getRequestURI(), e); - } - } - - @SuppressWarnings("deprecation") - protected void sendResponse(Response response) { - RestServerCodecFilter.copyHeadersToHttpResponse(response.getHeaders(), responseEx); - - responseEx.setStatus(response.getStatusCode(), response.getReasonPhrase()); - responseEx.setAttribute(RestConst.INVOCATION_HANDLER_RESPONSE, response); - responseEx.setAttribute(RestConst.INVOCATION_HANDLER_PROCESSOR, produceProcessor); - - executeHttpServerFilters(response); - } - - protected void executeHttpServerFilters(Response response) { - HttpServerFilterBeforeSendResponseExecutor exec = - new HttpServerFilterBeforeSendResponseExecutor(httpServerFilters, invocation, responseEx); - CompletableFuture future = exec.run(); - future.whenComplete((v, e) -> { - if (invocation != null) { - invocation.getInvocationStageTrace().finishServerFiltersResponse(); - } - - onExecuteHttpServerFiltersFinish(response, e); - }); - } - - protected void onExecuteHttpServerFiltersFinish(Response response, Throwable e) { - if (e != null) { - LOGGER.error("Failed to execute HttpServerFilters, operation:{}, request uri:{}", - getMicroserviceQualifiedName(), requestEx.getRequestURI(), e); - } - - try { - responseEx.flushBuffer(); - } catch (Throwable flushException) { - LOGGER.error("Failed to flush rest response, operation:{}, request uri:{}", - getMicroserviceQualifiedName(), requestEx.getRequestURI(), flushException); - } - - try { - requestEx.getAsyncContext().complete(); - } catch (Throwable completeException) { - LOGGER.error("Failed to complete async rest response, operation:{}, request uri:{}", - getMicroserviceQualifiedName(), requestEx.getRequestURI(), completeException); - } - - // if failed to locate path, then will not create invocation - // TODO: statistics this case - if (invocation != null) { - invocation.onFinish(response); - } - } - - private String getMicroserviceQualifiedName() { - return null == invocation ? UNKNOWN_OPERATION_ID : invocation.getMicroserviceQualifiedName(); - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/CommonRestConfiguration.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/CommonRestConfiguration.java new file mode 100644 index 00000000000..a642265ae0f --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/CommonRestConfiguration.java @@ -0,0 +1,79 @@ +/* + * 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.common.rest; + +import java.util.List; + +import org.apache.servicecomb.common.rest.codec.query.QueryCodec; +import org.apache.servicecomb.common.rest.codec.query.QueryCodecCsv; +import org.apache.servicecomb.common.rest.codec.query.QueryCodecMulti; +import org.apache.servicecomb.common.rest.codec.query.QueryCodecPipes; +import org.apache.servicecomb.common.rest.codec.query.QueryCodecSsv; +import org.apache.servicecomb.common.rest.codec.query.QueryCodecs; +import org.apache.servicecomb.common.rest.codec.query.QueryCodecsUtils; +import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter; +import org.apache.servicecomb.common.rest.filter.inner.WebSocketServerCodecFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CommonRestConfiguration { + @Bean + public QueryCodecCsv scbQueryCodecCsv() { + return new QueryCodecCsv(); + } + + @Bean + public QueryCodecSsv scbQueryCodecSsv() { + return new QueryCodecSsv(); + } + + @Bean + public QueryCodecPipes scbQueryCodecPipes() { + return new QueryCodecPipes(); + } + + @Bean + public QueryCodecMulti scbQueryCodecMulti() { + return new QueryCodecMulti(); + } + + @Bean + public QueryCodecsUtils scbQueryCodecsUtils(QueryCodecs queryCodecs) { + return new QueryCodecsUtils(queryCodecs); + } + + @Bean + public RestServerCodecFilter scbRestServerCodecFilter() { + return new RestServerCodecFilter(); + } + + @Bean + public WebSocketServerCodecFilter scbWebSocketServerCodecFilter() { + return new WebSocketServerCodecFilter(); + } + + @Bean + public QueryCodecs scbQueryCodecs(List orderedCodecs) { + return new QueryCodecs(orderedCodecs); + } + + @Bean + public RestEngineSchemaListener scbRestEngineSchemaListener() { + return new RestEngineSchemaListener(); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/EdgeServerWebSocketInvocationCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/EdgeServerWebSocketInvocationCreator.java new file mode 100644 index 00000000000..ff0b0f38174 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/EdgeServerWebSocketInvocationCreator.java @@ -0,0 +1,83 @@ +/* + * 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.common.rest; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.common.rest.locator.OperationLocator; +import org.apache.servicecomb.common.rest.locator.ServicePathManager; +import org.apache.servicecomb.core.Endpoint; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.invocation.InvocationFactory; +import org.apache.servicecomb.core.provider.consumer.MicroserviceReferenceConfig; +import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; + +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.ServerWebSocket; + +public class EdgeServerWebSocketInvocationCreator extends ProviderServerWebSocketInvocationCreator { + private final String microserviceName; + + protected MicroserviceReferenceConfig microserviceReferenceConfig; + + protected final String path; + + public EdgeServerWebSocketInvocationCreator(String microserviceName, String path, + Endpoint endpoint, ServerWebSocket webSocket) { + super(null, endpoint, webSocket); + this.microserviceName = microserviceName; + this.path = path; + } + + @Override + public CompletableFuture createAsync() { + return createMicroserviceReferenceConfig() + .thenCompose(v -> super.createAsync()); + } + + protected CompletableFuture createMicroserviceReferenceConfig() { + return SCBEngine.getInstance() + .getOrCreateReferenceConfigAsync(microserviceName) + .thenAccept(mrc -> { + this.microserviceReferenceConfig = mrc; + this.microserviceMeta = mrc.getMicroserviceMeta(); + }); + } + + @Override + protected OperationLocator locateOperation(ServicePathManager servicePathManager) { + return servicePathManager.consumerLocateOperation(path, HttpMethod.POST.name()); + } + + @Override + protected Invocation createInstance() { + ReferenceConfig referenceConfig = microserviceReferenceConfig + .createReferenceConfig(restOperationMeta.getOperationMeta()); + + Invocation invocation = InvocationFactory.forConsumer(referenceConfig, + restOperationMeta.getOperationMeta(), + restOperationMeta.getOperationMeta().buildBaseConsumerRuntimeType(), + null); + invocation.setSync(false); + invocation.setEdge(); + invocation.setEndpoint(endpoint); // ensure transport name is correct + + return invocation; + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/HttpTransportContext.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/HttpTransportContext.java index 4cfb259337d..d9b0df27c92 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/HttpTransportContext.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/HttpTransportContext.java @@ -16,23 +16,18 @@ */ package org.apache.servicecomb.common.rest; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.context.TransportContext; public class HttpTransportContext implements TransportContext { - private HttpServletRequestEx requestEx; + private final HttpServletRequestEx requestEx; - private HttpServletResponseEx responseEx; + private final HttpServletResponseEx responseEx; - private ProduceProcessor produceProcessor; - - public HttpTransportContext(HttpServletRequestEx requestEx, HttpServletResponseEx responseEx, - ProduceProcessor produceProcessor) { + public HttpTransportContext(HttpServletRequestEx requestEx, HttpServletResponseEx responseEx) { this.requestEx = requestEx; this.responseEx = responseEx; - this.produceProcessor = produceProcessor; } public HttpServletRequestEx getRequestEx() { @@ -42,8 +37,4 @@ public HttpServletRequestEx getRequestEx() { public HttpServletResponseEx getResponseEx() { return responseEx; } - - public ProduceProcessor getProduceProcessor() { - return produceProcessor; - } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/ProviderServerWebSocketInvocationCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/ProviderServerWebSocketInvocationCreator.java new file mode 100644 index 00000000000..bcd4fc827b3 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/ProviderServerWebSocketInvocationCreator.java @@ -0,0 +1,37 @@ +/* + * 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.common.rest; + +import org.apache.servicecomb.core.Endpoint; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.definition.MicroserviceMeta; + +import io.vertx.core.http.ServerWebSocket; + +public class ProviderServerWebSocketInvocationCreator extends ServerWebSocketInvocationCreator { + public ProviderServerWebSocketInvocationCreator(MicroserviceMeta microserviceMeta, + Endpoint endpoint, ServerWebSocket webSocket) { + super(microserviceMeta, endpoint, webSocket); + } + + @Override + protected void initTransportContext(Invocation invocation) { + WebSocketTransportContext transportContext = new WebSocketTransportContext(websocket); + invocation.setTransportContext(transportContext); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java index 722775fde11..bc598f973f6 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestConst.java @@ -17,6 +17,8 @@ package org.apache.servicecomb.common.rest; +import org.apache.commons.lang3.SystemUtils; + public final class RestConst { private RestConst() { } @@ -41,17 +43,14 @@ private RestConst() { // in HttpServletRequest attribute public static final String BODY_PARAMETER = "servicecomb-body"; - // in HttpServletRequest attribute - public static final String FORM_PARAMETERS = "servicecomb-forms"; - //in invocation response - public static final String INVOCATION_HANDLER_RESPONSE = "servicecomb-invocation-hanlder-response"; + public static final String INVOCATION_HANDLER_RESPONSE = "servicecomb-invocation-handler-response"; //in invocation response - public static final String INVOCATION_HANDLER_PROCESSOR = "servicecomb-invocation-hanlder-processor"; + public static final String INVOCATION_HANDLER_PROCESSOR = "servicecomb-invocation-handler-processor"; //in invocation response - public static final String INVOCATION_HANDLER_REQUESTCLIENT = "servicecomb-invocation-hanlder-requestclient"; + public static final String INVOCATION_HANDLER_REQUESTCLIENT = "servicecomb-invocation-handler-requestclient"; public static final String REST_PRODUCER_INVOCATION = "servicecomb-rest-producer-invocation"; @@ -65,6 +64,8 @@ private RestConst() { public static final String UPLOAD_DIR = "servicecomb.uploads.directory"; + public static final String UPLOAD_DEFAULT_DIR = SystemUtils.JAVA_IO_TMPDIR; + // limit of one upload file, only available for servlet rest transport public static final String UPLOAD_MAX_FILE_SIZE = "servicecomb.uploads.maxFileSize"; @@ -78,4 +79,10 @@ private RestConst() { public static final String PROVIDER_SCAN_REST_CONTROLLER = "servicecomb.provider.rest.scanRestController"; public static final String PRINT_CODEC_ERROR_MESSGAGE = "servicecomb.codec.printErrorMessage"; + + public static final String HEADER_CONTEXT_MAPPER = "servicecomb.context.headerContextMapper"; + + public static final String QUERY_CONTEXT_MAPPER = "servicecomb.context.queryContextMapper"; + + public static final String DECODE_INVOCATION_CONTEXT = "servicecomb.context.decodeInvocationContext"; } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestEngineSchemaListener.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestEngineSchemaListener.java index 51d68a8b07a..178d52f614d 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestEngineSchemaListener.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestEngineSchemaListener.java @@ -19,11 +19,9 @@ import org.apache.servicecomb.common.rest.locator.ServicePathManager; import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.core.definition.CoreMetaUtils; +import org.apache.servicecomb.core.SCBEngine.CreateMicroserviceMetaEvent; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.foundation.common.event.EnableExceptionPropagation; -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; -import org.apache.servicecomb.registry.api.event.CreateMicroserviceVersionEvent; import com.google.common.eventbus.Subscribe; @@ -42,9 +40,8 @@ public void onBeforeRegistry(BootEvent event) { @EnableExceptionPropagation @Subscribe - public void onCreateMicroserviceVersion(CreateMicroserviceVersionEvent event) { - MicroserviceVersion microserviceVersion = event.getMicroserviceVersion(); - MicroserviceMeta microserviceMeta = CoreMetaUtils.getMicroserviceMeta(microserviceVersion); + public void onCreateMicroserviceMetaEvent(CreateMicroserviceMetaEvent event) { + MicroserviceMeta microserviceMeta = event.getMicroserviceMeta(); createServicePathManager(microserviceMeta); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocation.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocation.java deleted file mode 100644 index 965cebf13b2..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocation.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.common.rest; - -import java.util.List; - -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.common.rest.locator.OperationLocator; -import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.core.invocation.InvocationFactory; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class RestProducerInvocation extends AbstractRestInvocation { - - protected Transport transport; - - public void invoke(Transport transport, HttpServletRequestEx requestEx, HttpServletResponseEx responseEx, - List httpServerFilters) { - this.transport = transport; - this.requestEx = requestEx; - this.responseEx = responseEx; - this.httpServerFilters = httpServerFilters; - requestEx.setAttribute(RestConst.REST_REQUEST, requestEx); - - try { - findRestOperation(); - } catch (InvocationException e) { - sendFailResponse(e); - return; - } - - scheduleInvocation(); - } - - protected void findRestOperation() { - MicroserviceMeta selfMicroserviceMeta = SCBEngine.getInstance().getProducerMicroserviceMeta(); - findRestOperation(selfMicroserviceMeta); - } - - @Override - protected OperationLocator locateOperation(ServicePathManager servicePathManager) { - return servicePathManager.producerLocateOperation(requestEx.getRequestURI(), requestEx.getMethod()); - } - - @Override - protected void createInvocation() { - this.invocation = InvocationFactory.forProvider(transport.getEndpoint(), - restOperationMeta.getOperationMeta(), - null); - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java index 0cbdc15cd8c..5a6c09d3912 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreator.java @@ -16,29 +16,27 @@ */ package org.apache.servicecomb.common.rest; -import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_CLIENT; +import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; import static org.apache.servicecomb.core.exception.ExceptionCodes.NOT_DEFINED_ANY_SCHEMA; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; -import javax.annotation.Nonnull; -import javax.ws.rs.core.HttpHeaders; - import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.config.YAMLUtil; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.core.invocation.InvocationCreator; import org.apache.servicecomb.core.invocation.InvocationFactory; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.slf4j.Logger; @@ -62,7 +60,7 @@ public abstract class RestProducerInvocationCreator implements InvocationCreator protected ProduceProcessor produceProcessor; public RestProducerInvocationCreator(MicroserviceMeta microserviceMeta, Endpoint endpoint, - @Nonnull HttpServletRequestEx requestEx, @Nonnull HttpServletResponseEx responseEx) { + HttpServletRequestEx requestEx, HttpServletResponseEx responseEx) { this.microserviceMeta = microserviceMeta; this.endpoint = endpoint; this.requestEx = requestEx; @@ -75,8 +73,7 @@ public CompletableFuture createAsync() { Invocation invocation = createInstance(); initInvocationContext(invocation); - - initProduceProcessor(); + addParameterContext(invocation); initTransportContext(invocation); invocation.addLocalContext(RestConst.REST_REQUEST, requestEx); @@ -89,7 +86,11 @@ protected Invocation createInstance() { } protected void initInvocationContext(Invocation invocation) { - String strCseContext = requestEx.getHeader(Const.CSE_CONTEXT); + if (!LegacyPropertyFactory.getBooleanProperty(RestConst.DECODE_INVOCATION_CONTEXT, true)) { + return; + } + + String strCseContext = requestEx.getHeader(CoreConst.CSE_CONTEXT); if (StringUtils.isEmpty(strCseContext)) { return; } @@ -99,6 +100,38 @@ protected void initInvocationContext(Invocation invocation) { invocation.mergeContext(invocationContext); } + protected void addParameterContext(Invocation invocation) { + String headerContextMapper = LegacyPropertyFactory + .getStringProperty(RestConst.HEADER_CONTEXT_MAPPER); + String queryContextMapper = LegacyPropertyFactory + .getStringProperty(RestConst.QUERY_CONTEXT_MAPPER); + + Map headerContextMappers; + if (headerContextMapper != null) { + headerContextMappers = YAMLUtil.yaml2Properties(headerContextMapper); + } else { + headerContextMappers = new HashMap<>(); + } + + Map queryContextMappers; + if (queryContextMapper != null) { + queryContextMappers = YAMLUtil.yaml2Properties(queryContextMapper); + } else { + queryContextMappers = new HashMap<>(); + } + + headerContextMappers.forEach((k, v) -> { + if (v instanceof String && requestEx.getHeader(k) != null) { + invocation.addContext((String) v, requestEx.getHeader(k)); + } + }); + queryContextMappers.forEach((k, v) -> { + if (v instanceof String && requestEx.getParameter(k) != null) { + invocation.addContext((String) v, requestEx.getParameter(k)); + } + }); + } + protected abstract void initTransportContext(Invocation invocation); protected void initRestOperation() { @@ -121,15 +154,4 @@ protected OperationLocator locateOperation(MicroserviceMeta microserviceMeta) { protected OperationLocator locateOperation(ServicePathManager servicePathManager) { return servicePathManager.producerLocateOperation(requestEx.getRequestURI(), requestEx.getMethod()); } - - private void initProduceProcessor() { - produceProcessor = restOperationMeta.ensureFindProduceProcessor(requestEx); - if (produceProcessor == null) { - LOGGER.error("Accept {} is not supported, operation={}.", requestEx.getHeader(HttpHeaders.ACCEPT), - restOperationMeta.getOperationMeta().getMicroserviceQualifiedName()); - - String msg = String.format("Accept %s is not supported", requestEx.getHeader(HttpHeaders.ACCEPT)); - throw Exceptions.create(NOT_ACCEPTABLE, GENERIC_CLIENT, msg); - } - } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationFlow.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationFlow.java index 70c3a5a3a01..727346c82d5 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationFlow.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestProducerInvocationFlow.java @@ -16,8 +16,6 @@ */ package org.apache.servicecomb.common.rest; -import static org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter.isDownloadFileResponseType; - import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter; @@ -25,7 +23,6 @@ import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.core.invocation.InvocationCreator; import org.apache.servicecomb.core.invocation.ProducerInvocationFlow; -import org.apache.servicecomb.foundation.common.utils.PartUtils; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.Response; @@ -47,40 +44,42 @@ public RestProducerInvocationFlow(InvocationCreator invocationCreator, protected Invocation sendCreateInvocationException(Throwable throwable) { try { Response response = Exceptions.toProducerResponse(null, throwable); - RestServerCodecFilter.encodeResponse(response, false, DEFAULT_PRODUCE_PROCESSOR, responseEx); + RestServerCodecFilter.encodeResponse(null, response, DEFAULT_PRODUCE_PROCESSOR, responseEx); } catch (Throwable e) { LOGGER.error("Failed to send response when prepare invocation failed, request uri:{}", requestEx.getRequestURI(), e); } - flushResponse("UNKNOWN_OPERATION"); + endResponse(null); return null; } @Override - protected void sendResponse(Invocation invocation, Response response) { - if (isDownloadFileResponseType(invocation, response)) { - responseEx.sendPart(PartUtils.getSinglePart(null, response.getResult())) - .whenComplete((r, e) -> flushResponse(invocation.getMicroserviceQualifiedName())); - return; - } + protected void endResponse(Invocation invocation, Response response) { + invocation.getInvocationStageTrace().startProviderSendResponse(); - flushResponse(invocation.getMicroserviceQualifiedName()); + endResponse(invocation); } - private void flushResponse(String operationName) { + private void endResponse(Invocation invocation) { try { - responseEx.flushBuffer(); + responseEx.endResponse(); } catch (Throwable flushException) { LOGGER.error("Failed to flush rest response, operation:{}, request uri:{}", - operationName, requestEx.getRequestURI(), flushException); + invocation == null ? "NA" : + invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), flushException); } try { requestEx.getAsyncContext().complete(); } catch (Throwable completeException) { LOGGER.error("Failed to complete async rest response, operation:{}, request uri:{}", - operationName, requestEx.getRequestURI(), completeException); + invocation == null ? "NA" : + invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), completeException); + } + + if (invocation != null) { + invocation.getInvocationStageTrace().finishProviderSendResponse(); } } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java index fcae4c7ab7f..83f14c64eca 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/RestVertxProducerInvocationCreator.java @@ -16,8 +16,6 @@ */ package org.apache.servicecomb.common.rest; -import javax.annotation.Nonnull; - import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.MicroserviceMeta; @@ -29,17 +27,16 @@ public class RestVertxProducerInvocationCreator extends RestProducerInvocationCreator { private final RoutingContext routingContext; - public RestVertxProducerInvocationCreator(@Nonnull RoutingContext routingContext, + public RestVertxProducerInvocationCreator(RoutingContext routingContext, MicroserviceMeta microserviceMeta, Endpoint endpoint, - @Nonnull HttpServletRequestEx requestEx, @Nonnull HttpServletResponseEx responseEx) { + HttpServletRequestEx requestEx, HttpServletResponseEx responseEx) { super(microserviceMeta, endpoint, requestEx, responseEx); this.routingContext = routingContext; } @Override protected void initTransportContext(Invocation invocation) { - VertxHttpTransportContext transportContext = new VertxHttpTransportContext(routingContext, requestEx, responseEx, - produceProcessor); + VertxHttpTransportContext transportContext = new VertxHttpTransportContext(routingContext, requestEx, responseEx); invocation.setTransportContext(transportContext); routingContext.put(RestConst.REST_INVOCATION_CONTEXT, invocation); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/ServerWebSocketInvocationCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/ServerWebSocketInvocationCreator.java new file mode 100644 index 00000000000..46d8b705138 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/ServerWebSocketInvocationCreator.java @@ -0,0 +1,136 @@ +/* + * 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.common.rest; + +import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; +import static org.apache.servicecomb.core.exception.ExceptionCodes.NOT_DEFINED_ANY_SCHEMA; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.common.rest.definition.RestOperationMeta; +import org.apache.servicecomb.common.rest.locator.OperationLocator; +import org.apache.servicecomb.common.rest.locator.ServicePathManager; +import org.apache.servicecomb.config.YAMLUtil; +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Endpoint; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.exception.Exceptions; +import org.apache.servicecomb.core.invocation.InvocationCreator; +import org.apache.servicecomb.core.invocation.InvocationFactory; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.ServerWebSocket; +import io.vertx.core.json.Json; + +public abstract class ServerWebSocketInvocationCreator implements InvocationCreator { + private static final Logger LOGGER = LoggerFactory.getLogger(RestVertxProducerInvocationCreator.class); + + protected MicroserviceMeta microserviceMeta; + + protected final Endpoint endpoint; + + protected final ServerWebSocket websocket; + + protected RestOperationMeta restOperationMeta; + + public ServerWebSocketInvocationCreator(MicroserviceMeta microserviceMeta, Endpoint endpoint, + ServerWebSocket websocket) { + this.microserviceMeta = microserviceMeta; + this.endpoint = endpoint; + this.websocket = websocket; + } + + @Override + public CompletableFuture createAsync() { + initRestOperation(); + + Invocation invocation = createInstance(); + initInvocationContext(invocation); + addParameterContext(invocation); + initTransportContext(invocation); + + return CompletableFuture.completedFuture(invocation); + } + + protected Invocation createInstance() { + return InvocationFactory.forProvider(endpoint, restOperationMeta.getOperationMeta(), null); + } + + protected void initInvocationContext(Invocation invocation) { + if (!LegacyPropertyFactory.getBooleanProperty(RestConst.DECODE_INVOCATION_CONTEXT, true)) { + return; + } + + String strCseContext = websocket.headers().get(CoreConst.CSE_CONTEXT); + if (StringUtils.isEmpty(strCseContext)) { + return; + } + + @SuppressWarnings("unchecked") + Map invocationContext = Json.decodeValue(strCseContext, Map.class); + invocation.mergeContext(invocationContext); + } + + // No queries for websocket + protected void addParameterContext(Invocation invocation) { + String headerContextMapper = LegacyPropertyFactory + .getStringProperty(RestConst.HEADER_CONTEXT_MAPPER); + + Map headerContextMappers; + if (headerContextMapper != null) { + headerContextMappers = YAMLUtil.yaml2Properties(headerContextMapper); + } else { + headerContextMappers = new HashMap<>(); + } + + headerContextMappers.forEach((k, v) -> { + if (v instanceof String && websocket.headers().get(k) != null) { + invocation.addContext((String) v, websocket.headers().get(k)); + } + }); + } + + protected abstract void initTransportContext(Invocation invocation); + + protected void initRestOperation() { + OperationLocator locator = locateOperation(microserviceMeta); + restOperationMeta = locator.getOperation(); + } + + protected OperationLocator locateOperation(MicroserviceMeta microserviceMeta) { + ServicePathManager servicePathManager = ServicePathManager.getServicePathManager(microserviceMeta); + if (servicePathManager == null) { + LOGGER.error("No schema defined for {}:{}.", this.microserviceMeta.getAppId(), + this.microserviceMeta.getMicroserviceName()); + throw Exceptions.create(NOT_FOUND, NOT_DEFINED_ANY_SCHEMA, NOT_FOUND.getReasonPhrase()); + } + + return locateOperation(servicePathManager); + } + + protected OperationLocator locateOperation(ServicePathManager servicePathManager) { + return servicePathManager.producerLocateOperation(websocket.path(), HttpMethod.POST.name()); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java index b487a966fba..ff564234124 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/UploadConfig.java @@ -16,87 +16,51 @@ */ package org.apache.servicecomb.common.rest; -import javax.servlet.MultipartConfigElement; +import org.springframework.core.env.Environment; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicPropertyFactory; +import jakarta.servlet.MultipartConfigElement; public class UploadConfig { - private static final Logger LOGGER = LoggerFactory.getLogger(UploadConfig.class); + private final Environment environment; + + public UploadConfig(Environment environment) { + this.environment = environment; + } /** * null means not support upload */ - private String location; + public String getLocation() { + return environment.getProperty(RestConst.UPLOAD_DIR, RestConst.UPLOAD_DEFAULT_DIR); + } /** * limit of one upload file, only available for servlet rest transport */ - private long maxFileSize; + public long getMaxFileSize() { + return environment.getProperty(RestConst.UPLOAD_MAX_FILE_SIZE, long.class, -1L); + } /** * limit of upload request body */ - private long maxSize; - - /** - * the size threshold after which files will be written to disk, only available for servlet rest transport - */ - private int fileSizeThreshold; - - public UploadConfig() { - location = DynamicPropertyFactory.getInstance().getStringProperty(RestConst.UPLOAD_DIR, null).get(); - maxFileSize = DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_FILE_SIZE, -1L).get(); - maxSize = DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_SIZE, -1L).get(); - fileSizeThreshold = DynamicPropertyFactory.getInstance().getIntProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, 0) - .get(); - } - - public String getLocation() { - return location; - } - - public void setLocation(String location) { - this.location = location; - } - - public long getMaxFileSize() { - return maxFileSize; - } - - public void setMaxFileSize(long maxFileSize) { - this.maxFileSize = maxFileSize; - } - public long getMaxSize() { - return maxSize; + return environment.getProperty(RestConst.UPLOAD_MAX_SIZE, long.class, -1L); } - public void setMaxSize(long maxSize) { - this.maxSize = maxSize; - } + /** + * the size threshold after which files will be written to disk, only available for servlet rest transport + */ public int getFileSizeThreshold() { - return fileSizeThreshold; - } - - public void setFileSizeThreshold(int fileSizeThreshold) { - this.fileSizeThreshold = fileSizeThreshold; + return environment.getProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, int.class, 0); } public MultipartConfigElement toMultipartConfigElement() { - String location = DynamicPropertyFactory.getInstance().getStringProperty(RestConst.UPLOAD_DIR, null).get(); - if (location == null) { - LOGGER.info("{} is null, not support upload.", RestConst.UPLOAD_DIR); - return null; - } - return new MultipartConfigElement( - location, - DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_FILE_SIZE, -1L).get(), - DynamicPropertyFactory.getInstance().getLongProperty(RestConst.UPLOAD_MAX_SIZE, -1L).get(), - DynamicPropertyFactory.getInstance().getIntProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, 0).get()); + getLocation(), + getMaxFileSize(), + getMaxSize(), + getFileSizeThreshold()); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxHttpTransportContext.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxHttpTransportContext.java index 607dccbffa6..55576022edd 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxHttpTransportContext.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxHttpTransportContext.java @@ -16,7 +16,6 @@ */ package org.apache.servicecomb.common.rest; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.context.VertxTransportContext; @@ -26,13 +25,13 @@ import io.vertx.ext.web.RoutingContext; public class VertxHttpTransportContext extends HttpTransportContext implements VertxTransportContext { - private RoutingContext routingContext; + private final RoutingContext routingContext; - private Context vertxContext; + private final Context vertxContext; public VertxHttpTransportContext(RoutingContext routingContext, HttpServletRequestEx requestEx, - HttpServletResponseEx responseEx, ProduceProcessor produceProcessor) { - super(requestEx, responseEx, produceProcessor); + HttpServletResponseEx responseEx) { + super(requestEx, responseEx); this.routingContext = routingContext; this.vertxContext = Vertx.currentContext(); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxRestInvocation.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxRestInvocation.java deleted file mode 100644 index c2a664a090c..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/VertxRestInvocation.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.common.rest; - -import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; - -import io.vertx.ext.web.RoutingContext; - -public class VertxRestInvocation extends RestProducerInvocation { - @Override - protected void createInvocation() { - super.createInvocation(); - - RoutingContext routingContext = ((VertxServerRequestToHttpServletRequest) this.requestEx).getContext(); - VertxHttpTransportContext transportContext = new VertxHttpTransportContext(routingContext, requestEx, responseEx, - produceProcessor); - - invocation.setTransportContext(transportContext); - routingContext.put(RestConst.REST_INVOCATION_CONTEXT, this.invocation); - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/WebSocketTransportContext.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/WebSocketTransportContext.java new file mode 100644 index 00000000000..738b09788ff --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/WebSocketTransportContext.java @@ -0,0 +1,34 @@ +/* + * 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.common.rest; + +import org.apache.servicecomb.swagger.invocation.context.TransportContext; + +import io.vertx.core.http.ServerWebSocket; + +public class WebSocketTransportContext implements TransportContext { + private final ServerWebSocket serverWebSocket; + + public WebSocketTransportContext(ServerWebSocket serverWebSocket) { + this.serverWebSocket = serverWebSocket; + } + + public ServerWebSocket getServerWebSocket() { + return this.serverWebSocket; + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java index 62d768847e6..74967694a90 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestClientRequest.java @@ -20,6 +20,7 @@ import io.vertx.core.Future; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClientRequest; /** * vertx的HttpClientRequest没有getHeader的能力 @@ -41,4 +42,6 @@ public interface RestClientRequest { Buffer getBodyBuffer() throws Exception; void attach(String name, Object partOrList); + + HttpClientRequest getHttpClientRequest(); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java index e879c205c25..260ac0d4cb1 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestCodec.java @@ -21,21 +21,15 @@ import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.common.rest.definition.RestParam; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import com.netflix.config.DynamicPropertyFactory; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; public final class RestCodec { - private static final Logger LOG = LoggerFactory.getLogger(RestCodec.class); - private RestCodec() { } @@ -57,24 +51,17 @@ public static Map restToArgs(HttpServletRequest request, List paramList = restOperation.getParamList(); Map paramValues = new HashMap<>(); - for (int idx = 0; idx < paramList.size(); idx++) { - RestParam param = paramList.get(idx); + for (RestParam param : paramList) { try { paramValues.put(param.getParamName(), param.getParamProcessor().getValue(request)); } catch (Exception e) { - // Avoid information leak of user input, and add option for debug use. String message = String - .format("Parameter is not valid for operation [%s]. Parameter is [%s]. Processor is [%s].", + .format("Parameter is not valid for operation [%s]. Parameter is [%s]. Processor is [%s]. Message is [%s].", restOperation.getOperationMeta().getMicroserviceQualifiedName(), param.getParamName(), - param.getParamProcessor().getProcessorType()); - if (DynamicPropertyFactory.getInstance().getBooleanProperty( - RestConst.PRINT_CODEC_ERROR_MESSGAGE, false).get()) { - LOG.error(message, e); - } else { - LOG.error("{} Add {}=true to print the details.", message, RestConst.PRINT_CODEC_ERROR_MESSGAGE); - } - throw new InvocationException(Status.BAD_REQUEST, message); + param.getParamProcessor().getProcessorType(), + e.getMessage()); + throw new InvocationException(Status.BAD_REQUEST, new CommonExceptionData(message), e); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java index 6c70b202cf3..d54800a07cb 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/RestObjectMapperFactory.java @@ -32,7 +32,7 @@ public class RestObjectMapperFactory { private static AbstractRestObjectMapper defaultMapper = new RestObjectMapper(); - private static AbstractRestObjectMapper viewMapper = new RestObjectMapper(); + private static final AbstractRestObjectMapper viewMapper = new RestObjectMapper(); private static AbstractRestObjectMapper consumerWriterMapper = defaultMapper; @@ -45,7 +45,7 @@ private static void registerModules(ObjectMapper mapper) { // not use mapper.findAndRegisterModules() // because we need to sort modules, so that customers can override our default module List modules = SPIServiceUtils.getOrLoadSortedService(Module.class); - mapper.registerModules(modules.toArray(new Module[modules.size()])); + mapper.registerModules(modules.toArray(new Module[0])); } public static AbstractRestObjectMapper getConsumerWriterMapper() { diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodec.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodec.java new file mode 100644 index 00000000000..6b6e06f41e1 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodec.java @@ -0,0 +1,45 @@ +/* + * 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.common.rest.codec.header; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.common.rest.codec.param.HeaderProcessorCreator.HeaderProcessor; + +import jakarta.servlet.http.HttpServletRequest; + +public interface HeaderCodec { + static String encodeValue(Object value) throws UnsupportedEncodingException { + return URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.name()); + } + + // can not be replaced by value.toString() because of date serialize + static String convertToString(Object value) throws Exception { + return RestObjectMapperFactory.getRestObjectMapper().convertToString(value); + } + + String getCodecName(); + + void encode(RestClientRequest clientRequest, String name, Object value) throws Exception; + + Object decode(HeaderProcessor processor, HttpServletRequest request); +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecCsv.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecCsv.java new file mode 100644 index 00000000000..26d86bbf2b7 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecCsv.java @@ -0,0 +1,28 @@ +/* + * 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.common.rest.codec.header; + +public class HeaderCodecCsv extends HeaderCodecWithDelimiter { + public static final String CODEC_NAME = "form:0"; + + public static final String DELIMITER = ","; + + public HeaderCodecCsv() { + super(CODEC_NAME, DELIMITER, DELIMITER); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecMulti.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecMulti.java new file mode 100644 index 00000000000..7a61e0fa125 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecMulti.java @@ -0,0 +1,66 @@ +/* + * 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.common.rest.codec.header; + +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; + +import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.common.rest.codec.param.HeaderProcessorCreator.HeaderProcessor; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; + +public class HeaderCodecMulti implements HeaderCodec { + public static final String NAME = "form:1"; + + @Override + public String getCodecName() { + return NAME; + } + + @Override + public void encode(RestClientRequest clientRequest, String name, Object value) throws Exception { + if (null == value) { + // if value is empty, header should not be set to clientRequest to avoid NullPointerException in Netty. + return; + } + if (!(value instanceof Collection)) { + throw new InvocationException(Status.BAD_REQUEST, + new CommonExceptionData("Array type of header should be Collection")); + } + for (Object item : ((Collection) value)) { + clientRequest.putHeader(name, + RestObjectMapperFactory.getConsumerWriterMapper().convertToString(item)); + } + } + + @Override + public Object decode(HeaderProcessor processor, HttpServletRequest request) { + Enumeration headerValues = request.getHeaders(processor.getParameterPath()); + if (headerValues == null) { + //Even if the paramPath does not exist, headerValues won't be null at now + return null; + } + return processor.convertValue(Collections.list(headerValues), processor.getTargetType()); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecPipes.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecPipes.java new file mode 100644 index 00000000000..f458946ba61 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecPipes.java @@ -0,0 +1,30 @@ +/* + * 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.common.rest.codec.header; + +public class HeaderCodecPipes extends HeaderCodecWithDelimiter { + public static final String CODEC_NAME = "pipeDelimited:0"; + + public static final String JOIN_DELIMITER = "|"; + + public static final String SPLIT_DELIMITER = "\\|"; + + public HeaderCodecPipes() { + super(CODEC_NAME, JOIN_DELIMITER, SPLIT_DELIMITER); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecSimple.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecSimple.java new file mode 100644 index 00000000000..0dd46a86b90 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecSimple.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.common.rest.codec.header; + +import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.common.rest.codec.param.HeaderProcessorCreator.HeaderProcessor; + +import jakarta.servlet.http.HttpServletRequest; + +public class HeaderCodecSimple implements HeaderCodec { + public static final String NAME = "simple"; + + @Override + public String getCodecName() { + return NAME; + } + + @Override + public void encode(RestClientRequest clientRequest, String name, Object value) throws Exception { + if (null == value) { + // if value is empty, header should not be set to clientRequest to avoid NullPointerException in Netty. + return; + } + clientRequest.putHeader(name, + RestObjectMapperFactory.getConsumerWriterMapper().convertToString(value)); + } + + @Override + public Object decode(HeaderProcessor processor, HttpServletRequest request) { + Object value = request.getHeader(processor.getParameterPath()); + if (value == null) { + value = processor.checkRequiredAndDefaultValue(); + } + return processor.convertValue(value, processor.getTargetType()); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecSsv.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecSsv.java new file mode 100644 index 00000000000..a9266f043ef --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecSsv.java @@ -0,0 +1,28 @@ +/* + * 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.common.rest.codec.header; + +public class HeaderCodecSsv extends HeaderCodecWithDelimiter { + public static final String CODEC_NAME = "spaceDelimited:0"; + + public static final String DELIMITER = " "; + + public HeaderCodecSsv() { + super(CODEC_NAME, DELIMITER, DELIMITER); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecWithDelimiter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecWithDelimiter.java new file mode 100644 index 00000000000..c85742b5549 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecWithDelimiter.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.common.rest.codec.header; + +import java.util.Collection; +import java.util.List; +import java.util.StringJoiner; + +import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.common.rest.codec.param.HeaderProcessorCreator.HeaderProcessor; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; + +public abstract class HeaderCodecWithDelimiter implements HeaderCodec { + private final String name; + + private final String joinDelimiter; + + private final String splitDelimiter; + + public HeaderCodecWithDelimiter(String name, String joinDelimiter, String splitDelimiter) { + this.name = name; + this.joinDelimiter = joinDelimiter; + this.splitDelimiter = splitDelimiter; + } + + + @Override + public String getCodecName() { + return name; + } + + @Override + public void encode(RestClientRequest clientRequest, String name, Object value) throws Exception { + if (null == value) { + // if value is empty, header should not be set to clientRequest to avoid NullPointerException in Netty. + return; + } + if (!(value instanceof Collection)) { + throw new InvocationException(Status.BAD_REQUEST, + new CommonExceptionData("Array type of header should be Collection")); + } + clientRequest.putHeader(name, join((Collection) value)); + } + + protected String join(Collection values) throws Exception { + StringJoiner joiner = new StringJoiner(joinDelimiter); + for (Object value : values) { + String strValue = RestObjectMapperFactory.getConsumerWriterMapper().convertToString(value); + joiner.add(strValue); + } + + return joiner.toString(); + } + + @Override + public Object decode(HeaderProcessor processor, HttpServletRequest request) { + String headerValues = request.getHeader(processor.getParameterPath()); + if (headerValues == null) { + headerValues = (String) processor.checkRequiredAndDefaultValue(); + } + + return processor.convertValue(List.of(headerValues.split(splitDelimiter)), processor.getTargetType()); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecsUtils.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecsUtils.java new file mode 100644 index 00000000000..fb9509a1f90 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/header/HeaderCodecsUtils.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.common.rest.codec.header; + +import java.util.HashMap; +import java.util.Map; + +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; + +public class HeaderCodecsUtils { + private static final Map CODECS; + + static { + CODECS = new HashMap<>(); + CODECS.put(HeaderCodecSimple.NAME, new HeaderCodecSimple()); + CODECS.put(HeaderCodecMulti.NAME, new HeaderCodecMulti()); + CODECS.put(HeaderCodecCsv.CODEC_NAME, new HeaderCodecCsv()); + CODECS.put(HeaderCodecPipes.CODEC_NAME, new HeaderCodecPipes()); + CODECS.put(HeaderCodecSsv.CODEC_NAME, new HeaderCodecSsv()); + } + + private HeaderCodecsUtils() { + } + + public static HeaderCodec find(Parameter.StyleEnum styleEnum, Boolean explode) { + return CODECS.get(formatName(styleEnum, explode)); + } + + private static String formatName(StyleEnum styleEnum, Boolean explode) { + if (styleEnum == null) { + return HeaderCodecSimple.NAME; + } + return styleEnum + ":" + + (explode != null && explode ? "1" : "0"); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java index 5d92d3dddff..e789038c467 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/BodyProcessorCreator.java @@ -21,74 +21,130 @@ import java.io.InputStream; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; -import java.util.Locale; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.entity.ContentType; +import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.protobuf.ProtoMapper; +import org.apache.servicecomb.foundation.protobuf.RootDeserializer; +import org.apache.servicecomb.foundation.protobuf.RootSerializer; +import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper; import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; import org.apache.servicecomb.swagger.SwaggerUtils; -import org.apache.servicecomb.swagger.converter.ConverterMgr; import org.apache.servicecomb.swagger.generator.SwaggerConst; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.type.SimpleType; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.netflix.config.DynamicPropertyFactory; -import io.swagger.models.Model; -import io.swagger.models.ModelImpl; -import io.swagger.models.parameters.BodyParameter; -import io.swagger.models.parameters.Parameter; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.parameters.RequestBody; import io.vertx.core.buffer.Buffer; import io.vertx.core.buffer.impl.BufferImpl; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response.Status; + +public class BodyProcessorCreator implements ParamValueProcessorCreator { -public class BodyProcessorCreator implements ParamValueProcessorCreator { private static final Logger LOGGER = LoggerFactory.getLogger(BodyProcessorCreator.class); - public static final String PARAMTYPE = "body"; + public static final String REQUEST_BODY_NAME = "X_REQUEST"; + + public static final String EXT_ID = "protobuf"; + + public static final String PARAM_TYPE = "body"; private static final JavaType OBJECT_TYPE = SimpleType.constructUnsafe(Object.class); - // This configuration is used for temporary use only. Do not use it if you are sure how it works. And may be deleted in future. - private static boolean decodeAsObject = DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.rest.parameter.decodeAsObject", false).get(); + private static final Object LOCK = new Object(); + + // This configuration is used for temporary use only. + // Do not use it if you are sure how it works. And may be deleted in the future. + public static final String PARAM_DECODE_AS_OBJECT = "servicecomb.rest.parameter.decodeAsObject"; + + public static final String PARAM_DEFAULT_REQUEST_ENCODING = "servicecomb.rest.parameter.default-request-encoding"; + + private static Boolean decodeAsObject; + + private static String defaultRequestEncoding; public static class BodyProcessor implements ParamValueProcessor { + // Producer target type. For consumer, is null. protected JavaType targetType; protected Class serialViewClass; - private boolean isString; - protected boolean isRequired; - public BodyProcessor(JavaType targetType, boolean isString, boolean isRequired) { - this(targetType, null, isString, isRequired); - } + protected OpenAPI openAPI; - public BodyProcessor(JavaType targetType, String serialViewClass, boolean isString, boolean isRequired) { - if (!StringUtils.isEmpty(serialViewClass)) { + protected ScopedProtobufSchemaManager scopedProtobufSchemaManager; + + protected List supportedContentTypes = new ArrayList<>(); + + protected OperationMeta operationMeta; + + protected RequestBody requestBody; + + public BodyProcessor(OperationMeta operationMeta, JavaType targetType, RequestBody requestBody) { + this.requestBody = requestBody; + if (!StringUtils.isEmpty((String) this.requestBody.getExtensions() + .get(SwaggerConst.EXT_JSON_VIEW))) { try { - this.serialViewClass = Class.forName(serialViewClass); + this.serialViewClass = Class.forName((String) this.requestBody.getExtensions() + .get(SwaggerConst.EXT_JSON_VIEW)); } catch (Throwable e) { //ignore LOGGER.warn("Failed to create body processor {}, annotation @JsonView may be invalid", serialViewClass, e); } } + this.targetType = targetType; - this.isString = isString; - this.isRequired = isRequired; + this.isRequired = this.requestBody.getRequired() != null && this.requestBody.getRequired(); + if (this.requestBody.getContent() != null) { + supportedContentTypes.addAll(this.requestBody.getContent().keySet()); + } + + if (operationMeta != null) { + this.operationMeta = operationMeta; + this.openAPI = operationMeta.getSchemaMeta().getSwagger(); + if (supportedContentTypes.contains(SwaggerConst.PROTOBUF_TYPE)) { + this.scopedProtobufSchemaManager = getOrCreateScopedProtobufSchemaManager( + operationMeta.getMicroserviceMeta()); + } + } + } + + private ScopedProtobufSchemaManager getOrCreateScopedProtobufSchemaManager(MicroserviceMeta microserviceMeta) { + ScopedProtobufSchemaManager scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID); + if (scopedProtobufSchemaManager == null) { + synchronized (LOCK) { + scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID); + if (scopedProtobufSchemaManager == null) { + scopedProtobufSchemaManager = new ScopedProtobufSchemaManager(); + microserviceMeta.putExtData(EXT_ID, scopedProtobufSchemaManager); + } + } + } + return scopedProtobufSchemaManager; } @Override @@ -98,16 +154,25 @@ public Class getSerialViewClass() { @Override public Object getValue(HttpServletRequest request) throws Exception { + Object result = getValueImpl(request); + if (result == null && this.isRequired) { + throw new InvocationException(Status.BAD_REQUEST, "Body parameter is required."); + } + return result; + } + + private Object getValueImpl(HttpServletRequest request) throws IOException { Object body = request.getAttribute(RestConst.BODY_PARAMETER); if (body != null) { return convertValue(body, targetType); } // edge support convert from form-data or x-www-form-urlencoded to json automatically - String contentType = request.getContentType(); - contentType = contentType == null ? "" : contentType.toLowerCase(Locale.US); - if (contentType.startsWith(MediaType.MULTIPART_FORM_DATA) - || contentType.startsWith(MediaType.APPLICATION_FORM_URLENCODED)) { + String contentType = validContentType(request.getContentType()); + + // support RFC 7231, ignore case for content-type + if (StringUtils.equalsIgnoreCase(contentType, MediaType.MULTIPART_FORM_DATA) + || StringUtils.equalsIgnoreCase(contentType, MediaType.APPLICATION_FORM_URLENCODED)) { return convertValue(request.getParameterMap(), targetType); } @@ -119,67 +184,124 @@ public Object getValue(HttpServletRequest request) throws Exception { return null; } - if (!contentType.isEmpty() && !contentType.startsWith(MediaType.APPLICATION_JSON)) { - // TODO: we should consider body encoding - return IOUtils.toString(inputStream, StandardCharsets.UTF_8); + if (StringUtils.equalsIgnoreCase(contentType, MediaType.APPLICATION_JSON)) { + try { + ObjectReader reader = serialViewClass != null + ? RestObjectMapperFactory.getRestObjectMapper().readerWithView(serialViewClass) + : RestObjectMapperFactory.getRestObjectMapper().reader(); + if (decodeAsObject()) { + return reader.forType(OBJECT_TYPE).readValue(inputStream); + } + return reader.forType(targetType == null ? OBJECT_TYPE : targetType) + .readValue(inputStream); + } catch (MismatchedInputException e) { + // there is no way to detect InputStream is empty, so have to catch the exception + if (!isRequired && e.getMessage().contains("No content to map due to end-of-input")) { + LOGGER.info("Empty content and required is false, taken as null"); + return null; + } + throw e; + } } - try { - ObjectReader reader = serialViewClass != null - ? RestObjectMapperFactory.getRestObjectMapper().readerWithView(serialViewClass) - : RestObjectMapperFactory.getRestObjectMapper().reader(); - if (decodeAsObject) { - return reader.forType(OBJECT_TYPE).readValue(inputStream); + + if (StringUtils.equalsIgnoreCase(contentType, SwaggerConst.PROTOBUF_TYPE)) { + ProtoMapper protoMapper = scopedProtobufSchemaManager + .getOrCreateProtoMapper(openAPI, operationMeta.getSchemaId(), + REQUEST_BODY_NAME, + requestBody.getContent().get(SwaggerConst.PROTOBUF_TYPE).getSchema()); + RootDeserializer> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage(REQUEST_BODY_NAME), + targetType == null ? OBJECT_TYPE : targetType); + PropertyWrapper result = deserializer.deserialize(inputStream.readAllBytes()); + return result.getValue(); + } + + if (StringUtils.equalsIgnoreCase(contentType, MediaType.TEXT_PLAIN)) { + try { + if (targetType != null && String.class.equals(targetType.getRawClass())) { + return IOUtils.toString(inputStream, StandardCharsets.UTF_8); + } + ObjectReader reader = serialViewClass != null + ? RestObjectMapperFactory.getRestObjectMapper().readerWithView(serialViewClass) + : RestObjectMapperFactory.getRestObjectMapper().reader(); + if (decodeAsObject()) { + return reader.forType(OBJECT_TYPE).readValue(inputStream); + } + return reader.forType(targetType == null ? OBJECT_TYPE : targetType) + .readValue(inputStream); + } catch (MismatchedInputException e) { + // there is no way to detect InputStream is empty, so have to catch the exception + if (!isRequired && e.getMessage().contains("No content to map due to end-of-input")) { + LOGGER.info("Empty content and required is false, taken as null"); + return null; + } + throw e; + } + } + + throw new IllegalArgumentException(String.format("operation %s not support content-type %s", + operationMeta.getSchemaQualifiedName(), contentType)); + } + + private String validContentType(String type) { + if (StringUtils.isEmpty(type)) { + if (supportedContentTypes.size() == 0) { + throw new IllegalArgumentException("operation do not have any content type support."); } - return reader.forType(targetType == null ? OBJECT_TYPE : targetType) - .readValue(inputStream); - } catch (MismatchedInputException e) { - // there is no way to detect InputStream is empty, so have to catch the exception - if (!isRequired && e.getMessage().contains("No content to map due to end-of-input")) { - LOGGER.info("Empty content and required is false, taken as null"); - return null; + if (supportedContentTypes.contains(clientEncodingDefault())) { + return clientEncodingDefault(); } - throw e; + return supportedContentTypes.get(0); } + ContentType contentType = ContentType.parse(type); + return contentType.getMimeType(); } @Override public void setValue(RestClientRequest clientRequest, Object arg) throws Exception { - ensureContentType(clientRequest); + String userContentType = clientRequest.getHeaders().get(HttpHeaders.CONTENT_TYPE); + String contentType = validContentType(userContentType); + if (StringUtils.isEmpty(userContentType)) { + clientRequest.putHeader(HttpHeaders.CONTENT_TYPE, contentType); + } if (arg != null) { - Buffer buffer = createBodyBuffer(clientRequest.getHeaders().get(HttpHeaders.CONTENT_TYPE), arg); + Buffer buffer = createBodyBuffer(contentType, arg); clientRequest.write(buffer); } } /** - * Deserialize body object into body buffer, according to the Content-Type. - * - * @param contentType the Content-Type of request - * @param arg body param object - * @return the deserialized body buffer - * @throws IOException + * Serialize body object into body buffer, according to the Content-Type. */ private Buffer createBodyBuffer(String contentType, Object arg) throws IOException { - if (MediaType.TEXT_PLAIN.equals(contentType)) { - if (!(arg instanceof String)) { - throw new IllegalArgumentException("Content-Type is text/plain while arg type is not String"); + if (MediaType.APPLICATION_JSON.equals(contentType)) { + try (BufferOutputStream output = new BufferOutputStream()) { + RestObjectMapperFactory.getConsumerWriterMapper().writeValue(output, arg); + return output.getBuffer(); } - return new BufferImpl().appendBytes(((String) arg).getBytes()); } - try (BufferOutputStream output = new BufferOutputStream()) { - RestObjectMapperFactory.getConsumerWriterMapper().writeValue(output, arg); - return output.getBuffer(); + if (SwaggerConst.PROTOBUF_TYPE.equals(contentType)) { + ProtoMapper protoMapper = scopedProtobufSchemaManager + .getOrCreateProtoMapper(openAPI, operationMeta.getSchemaId(), + REQUEST_BODY_NAME, + requestBody.getContent().get(SwaggerConst.PROTOBUF_TYPE).getSchema()); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage(REQUEST_BODY_NAME), + Object.class); + Map bodyArg = new HashMap<>(1); + bodyArg.put("value", arg); + return new BufferImpl().appendBytes(serializer.serialize(bodyArg)); } - } - /** - * If the Content-Type has not been set yet, set application/json as default value. - */ - private void ensureContentType(RestClientRequest clientRequest) { - if (null == clientRequest.getHeaders() - || StringUtils.isEmpty(clientRequest.getHeaders().get(HttpHeaders.CONTENT_TYPE))) { - clientRequest.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); + // For text/plain + try (BufferOutputStream output = new BufferOutputStream()) { + if (arg instanceof String) { + output.write(((String) arg).getBytes(StandardCharsets.UTF_8)); + } else { + RestObjectMapperFactory.getConsumerWriterMapper().writeValue(output, arg); + } + return output.getBuffer(); } } @@ -190,17 +312,32 @@ public String getParameterPath() { @Override public String getProcessorType() { - return PARAMTYPE; + return PARAM_TYPE; } } - public static class RawJsonBodyProcessor extends BodyProcessor { - public RawJsonBodyProcessor(JavaType targetType, boolean isString, boolean isRequired) { - this(targetType, null, isString, isRequired); + public static class RawJsonBodyProcessor implements ParamValueProcessor { + protected JavaType targetType; + + protected Class serialViewClass; + + protected boolean isRequired; + + public RawJsonBodyProcessor(JavaType targetType, boolean isRequired) { + this(targetType, null, isRequired); } - public RawJsonBodyProcessor(JavaType targetType, String serialViewClass, boolean isString, boolean isRequired) { - super(targetType, serialViewClass, isString, isRequired); + public RawJsonBodyProcessor(JavaType targetType, String serialViewClass, boolean isRequired) { + if (!StringUtils.isEmpty(serialViewClass)) { + try { + this.serialViewClass = Class.forName(serialViewClass); + } catch (Throwable e) { + //ignore + LOGGER.warn("Failed to create body processor {}, annotation @JsonView may be invalid", serialViewClass, e); + } + } + this.targetType = targetType; + this.isRequired = isRequired; } @Override @@ -215,7 +352,6 @@ public Object getValue(HttpServletRequest request) throws Exception { return null; } - // TODO: we should consider body encoding return IOUtils.toString(inputStream, StandardCharsets.UTF_8); } @@ -227,32 +363,52 @@ public void setValue(RestClientRequest clientRequest, Object arg) throws Excepti return; } - super.setValue(clientRequest, arg); + throw new IllegalArgumentException("@RawJsonRequestBody only supports string type."); + } + + @Override + public String getParameterPath() { + return ""; + } + + @Override + public String getProcessorType() { + return PARAM_TYPE; } } public BodyProcessorCreator() { - ParamValueProcessorCreatorManager.INSTANCE.register(PARAMTYPE, this); + ParamValueProcessorCreatorManager.INSTANCE.register(PARAM_TYPE, this); } @Override - public ParamValueProcessor create(Parameter parameter, Type genericParamType) { - Model model = ((BodyParameter) parameter).getSchema(); - JavaType swaggerType = null; - if (model instanceof ModelImpl) { - swaggerType = ConverterMgr.findJavaType(((ModelImpl) model).getType(), ((ModelImpl) model).getFormat()); - } - boolean isString = swaggerType != null && swaggerType.getRawClass().equals(String.class); - + public ParamValueProcessor create(OperationMeta operationMeta, String parameterName, + RequestBody parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); boolean rawJson = SwaggerUtils.isRawJsonType(parameter); if (rawJson) { - return new RawJsonBodyProcessor(targetType, (String) parameter.getVendorExtensions() - .get(SwaggerConst.EXT_JSON_VIEW), isString, parameter.getRequired()); + return new RawJsonBodyProcessor(targetType, (String) parameter.getExtensions() + .get(SwaggerConst.EXT_JSON_VIEW), + parameter.getRequired() != null && parameter.getRequired()); + } + + return new BodyProcessor(operationMeta, targetType, parameter); + } + + private static boolean decodeAsObject() { + if (decodeAsObject == null) { + decodeAsObject = LegacyPropertyFactory + .getBooleanProperty(PARAM_DECODE_AS_OBJECT, false); } + return decodeAsObject; + } - return new BodyProcessor(targetType, (String) parameter.getVendorExtensions() - .get(SwaggerConst.EXT_JSON_VIEW), isString, parameter.getRequired()); + private static String clientEncodingDefault() { + if (defaultRequestEncoding == null) { + defaultRequestEncoding = LegacyPropertyFactory + .getStringProperty(PARAM_DEFAULT_REQUEST_ENCODING, MediaType.APPLICATION_JSON); + } + return defaultRequestEncoding; } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java index a21c23719e5..9426cc2e232 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/CookieProcessorCreator.java @@ -20,21 +20,20 @@ import java.lang.reflect.Type; import java.util.Objects; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status; - import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.CookieParameter; -import io.swagger.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; -public class CookieProcessorCreator implements ParamValueProcessorCreator { +public class CookieProcessorCreator implements ParamValueProcessorCreator { public static final String PARAMTYPE = "cookie"; public static class CookieProcessor extends AbstractParamProcessor { @@ -87,10 +86,11 @@ public CookieProcessorCreator() { } @Override - public ParamValueProcessor create(Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); - return new CookieProcessor(parameter.getName(), targetType, ((CookieParameter) parameter).getDefaultValue(), - parameter.getRequired()); + return new CookieProcessor(parameterName, targetType, parameter.getSchema().getDefault(), + parameter.getRequired() != null && parameter.getRequired()); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java index 2675ea6ac83..740f57e039f 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/FormProcessorCreator.java @@ -23,42 +23,45 @@ import java.util.function.Function; import java.util.stream.Collectors; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.Part; -import javax.ws.rs.core.Response.Status; - import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.ParameterizedTypeUtil; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.apache.servicecomb.swagger.invocation.converter.Converter; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.google.inject.util.Types; -import io.swagger.models.parameters.FormParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.ArrayProperty; -import io.swagger.models.properties.FileProperty; -import io.swagger.models.properties.Property; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.RequestBody; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.Response.Status; -public class FormProcessorCreator implements ParamValueProcessorCreator { +@SuppressWarnings("unchecked") +public class FormProcessorCreator implements ParamValueProcessorCreator { public static final String PARAMTYPE = "formData"; public static class FormProcessor extends AbstractParamProcessor { - private boolean repeatedType; + private final boolean repeatedType; - public FormProcessor(FormParameter formParameter, JavaType targetType) { - super(formParameter.getName(), targetType, formParameter.getDefaultValue(), formParameter.getRequired()); + public FormProcessor(String paraName, RequestBody formParameter, String mediaType, JavaType targetType) { + super(paraName, targetType, + formParameter.getContent().get(mediaType).getSchema().getDefault(), + formParameter.getRequired() != null && formParameter.getRequired()); - this.repeatedType = ArrayProperty.isType(formParameter.getType()); + this.repeatedType = formParameter.getContent().get(mediaType) + .getSchema().getProperties().get(paraName) instanceof ArraySchema; } @Override public Object getValue(HttpServletRequest request) { - @SuppressWarnings("unchecked") - Map forms = (Map) request.getAttribute(RestConst.FORM_PARAMETERS); + Map forms = (Map) request.getAttribute(RestConst.BODY_PARAMETER); if (forms != null && !forms.isEmpty()) { return convertValue(forms.get(paramPath), targetType); } @@ -98,52 +101,62 @@ public FormProcessorCreator() { } @Override - public ParamValueProcessor create(Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String paramName, RequestBody parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); - if (isPart(parameter)) { - return new PartProcessor((FormParameter) parameter, genericParamType); + if (isPart(parameter, paramName)) { + return new PartProcessor(paramName, parameter, genericParamType); + } + String mediaType = SwaggerConst.FORM_MEDIA_TYPE; + if (parameter.getContent().get(SwaggerConst.FILE_MEDIA_TYPE) != null) { + mediaType = SwaggerConst.FILE_MEDIA_TYPE; } - return new FormProcessor((FormParameter) parameter, targetType); + return new FormProcessor(paramName, parameter, mediaType, targetType); } - private boolean isPart(Parameter parameter) { - // no need to check Part[][] and so on - FormParameter formParameter = (FormParameter) parameter; - if ("array".equals(formParameter.getType())) { - Property items = formParameter.getItems(); - return new FileProperty().getType().equals(items.getType()); + private boolean isPart(RequestBody parameter, String paramName) { + MediaType file = parameter.getContent().get(SwaggerConst.FILE_MEDIA_TYPE); + if (file != null) { + Schema schema = (Schema) file.getSchema().getProperties().get(paramName); + if (schema instanceof ArraySchema) { + return "string".equals(schema.getItems().getType()) && + "binary".equals(schema.getItems().getFormat()); + } else { + return ("string".equals(schema.getType()) && "binary".equals(schema.getFormat())); + } } - return new FileProperty().getType().equals(formParameter.getType()); + return false; } public static class PartProcessor extends AbstractParamProcessor { - private static Type partListType = Types.newParameterizedType(List.class, Part.class); + private static final Type partListType = ParameterizedTypeUtil.make(List.class, Part.class); // key is target type - private static Map partsToTargetConverters = SPIServiceUtils.getSortedService(Converter.class) + private static final Map partsToTargetConverters = SPIServiceUtils.getSortedService( + Converter.class) .stream() .filter(c -> partListType.equals(c.getSrcType())) .collect(Collectors.toMap(Converter::getTargetType, Function.identity())); // key is target type - private static Map partToTargetConverters = SPIServiceUtils.getSortedService(Converter.class) + private static final Map partToTargetConverters = SPIServiceUtils.getSortedService(Converter.class) .stream() .filter(c -> c.getSrcType() instanceof Class && Part.class.isAssignableFrom((Class) c.getSrcType())) .collect(Collectors.toMap(Converter::getTargetType, Function.identity())); - private boolean repeatedType; - - private Type genericParamType; + private final boolean repeatedType; private Converter converter; - PartProcessor(FormParameter formParameter, Type genericParamType) { - super(formParameter.getName(), null, formParameter.getDefaultValue(), formParameter.getRequired()); + PartProcessor(String paramName, RequestBody formParameter, Type genericParamType) { + super(paramName, null, + formParameter.getContent().get(SwaggerConst.FILE_MEDIA_TYPE).getSchema().getDefault(), + formParameter.getRequired() != null && formParameter.getRequired()); - this.genericParamType = genericParamType; - this.repeatedType = ArrayProperty.isType(formParameter.getType()); + this.repeatedType = formParameter.getContent().get(SwaggerConst.FILE_MEDIA_TYPE) + .getSchema().getProperties().get(paramName) instanceof ArraySchema; initConverter(genericParamType); } @@ -165,7 +178,7 @@ private void initNormalConverter(Type genericParamType) { private void initRepeatedConverter(Type genericParamType) { if (genericParamType instanceof JavaType) { - genericParamType = Types.newParameterizedType(((JavaType) genericParamType).getRawClass(), + genericParamType = ParameterizedTypeUtil.make(((JavaType) genericParamType).getRawClass(), ((JavaType) genericParamType).getContentType()); } converter = partsToTargetConverters.get(genericParamType); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java index 7e33183e116..3bfb2675046 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/HeaderProcessorCreator.java @@ -18,63 +18,52 @@ package org.apache.servicecomb.common.rest.codec.param; import java.lang.reflect.Type; -import java.util.Collections; -import java.util.Enumeration; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status; import org.apache.servicecomb.common.rest.codec.RestClientRequest; -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.common.rest.codec.header.HeaderCodec; +import org.apache.servicecomb.common.rest.codec.header.HeaderCodecsUtils; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.netflix.config.DynamicPropertyFactory; - -import io.swagger.models.parameters.HeaderParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.ArrayProperty; -public class HeaderProcessorCreator implements ParamValueProcessorCreator { - private static final Logger LOGGER = LoggerFactory.getLogger(HeaderProcessorCreator.class); +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.parameters.HeaderParameter; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; +public class HeaderProcessorCreator implements ParamValueProcessorCreator { public static final String PARAMTYPE = "header"; public static class HeaderProcessor extends AbstractParamProcessor { // This configuration is used for temporary use only. Do not use it if you are sure how it works. And may be deleted in future. - private boolean ignoreRequiredCheck = DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.rest.parameter.header.ignoreRequiredCheck", false).get(); + private final boolean ignoreRequiredCheck = LegacyPropertyFactory + .getBooleanProperty("servicecomb.rest.parameter.header.ignoreRequiredCheck", false); - private boolean repeatedType; + private final HeaderCodec headerCodec; public HeaderProcessor(HeaderParameter headerParameter, JavaType targetType) { - super(headerParameter.getName(), targetType, headerParameter.getDefaultValue(), headerParameter.getRequired()); - - this.repeatedType = ArrayProperty.isType(headerParameter.getType()); + super(headerParameter.getName(), targetType, headerParameter.getSchema().getDefault(), + headerParameter.getRequired() != null && headerParameter.getRequired()); + + if ((headerParameter.getSchema() instanceof ArraySchema) && headerParameter.getStyle() == null) { + // compatible to default settings + this.headerCodec = HeaderCodecsUtils.find(StyleEnum.FORM, true); + } else { + this.headerCodec = HeaderCodecsUtils.find(headerParameter.getStyle(), headerParameter.getExplode()); + } } @Override public Object getValue(HttpServletRequest request) { - if (repeatedType) { - Enumeration headerValues = request.getHeaders(paramPath); - if (headerValues == null) { - //Even if the paramPath does not exist, headerValues won't be null at now - return null; - } - return convertValue(Collections.list(headerValues), targetType); - } - - Object value = request.getHeader(paramPath); - if (value == null) { - value = checkRequiredAndDefaultValue(); - } - return convertValue(value, targetType); + return headerCodec.decode(this, request); } - private Object checkRequiredAndDefaultValue() { + public Object checkRequiredAndDefaultValue() { if (!ignoreRequiredCheck && isRequired()) { throw new InvocationException(Status.BAD_REQUEST, "Parameter is required."); } @@ -83,13 +72,7 @@ private Object checkRequiredAndDefaultValue() { @Override public void setValue(RestClientRequest clientRequest, Object arg) throws Exception { - if (null == arg) { - // null header should not be set to clientRequest to avoid NullPointerException in Netty. - LOGGER.debug("Header arg is null, will not be set into clientRequest. paramPath = [{}]", paramPath); - return; - } - clientRequest.putHeader(paramPath, - RestObjectMapperFactory.getConsumerWriterMapper().convertToString(arg)); + headerCodec.encode(clientRequest, paramPath, arg); } @Override @@ -103,7 +86,8 @@ public HeaderProcessorCreator() { } @Override - public ParamValueProcessor create(Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); return new HeaderProcessor((HeaderParameter) parameter, targetType); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java index 8c933a2a1d1..5d5dfc32cf0 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessor.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.common.rest.codec.param; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java index b5d87b2f286..1c3378dc6bb 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/ParamValueProcessorCreator.java @@ -19,8 +19,11 @@ import java.lang.reflect.Type; -import io.swagger.models.parameters.Parameter; +import org.apache.servicecomb.core.definition.OperationMeta; -public interface ParamValueProcessorCreator { - ParamValueProcessor create(Parameter parameter, Type genericParamType); +public interface ParamValueProcessorCreator { + default ParamValueProcessor create(OperationMeta operationMeta, String paramName, T parameter, + Type genericParamType) { + throw new IllegalStateException("not implemented"); + } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java index cffb1f47034..861b7490fea 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/PathProcessorCreator.java @@ -18,23 +18,21 @@ package org.apache.servicecomb.common.rest.codec.param; import java.lang.reflect.Type; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Map; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.springframework.util.StringUtils; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.PathParameter; -import org.springframework.util.StringUtils; +import io.swagger.v3.oas.models.parameters.Parameter; +import jakarta.servlet.http.HttpServletRequest; -public class PathProcessorCreator implements ParamValueProcessorCreator { +public class PathProcessorCreator implements ParamValueProcessorCreator { public static final String PARAMTYPE = "path"; public static class PathProcessor extends AbstractParamProcessor { @@ -73,9 +71,10 @@ public PathProcessorCreator() { } @Override - public ParamValueProcessor create(Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); - return new PathProcessor(parameter.getName(), targetType, ((PathParameter) parameter).getDefaultValue(), true); + return new PathProcessor(parameterName, targetType, parameter.getSchema().getDefault(), true); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java index c0449bf9cfb..8fef056867c 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/QueryProcessorCreator.java @@ -18,49 +18,52 @@ package org.apache.servicecomb.common.rest.codec.param; import java.lang.reflect.Type; +import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status; - -import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.query.QueryCodec; import org.apache.servicecomb.common.rest.codec.query.QueryCodecsUtils; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.netflix.config.DynamicPropertyFactory; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.QueryParameter; -import io.swagger.models.properties.ArrayProperty; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.QueryParameter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; -public class QueryProcessorCreator implements ParamValueProcessorCreator { +@SuppressWarnings("unchecked") +public class QueryProcessorCreator implements ParamValueProcessorCreator { public static final String PARAMTYPE = "query"; public static class QueryProcessor extends AbstractParamProcessor { // This configuration is used for temporary use only. Do not use it if you are sure how it works. And may be deleted in future. - private boolean emptyAsNull = DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.rest.parameter.query.emptyAsNull", false).get(); + private final boolean emptyAsNull = LegacyPropertyFactory + .getBooleanProperty("servicecomb.rest.parameter.query.emptyAsNull", false); // This configuration is used for temporary use only. Do not use it if you are sure how it works. And may be deleted in future. - private boolean ignoreDefaultValue = DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", false).get(); + private final boolean ignoreDefaultValue = LegacyPropertyFactory + .getBooleanProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", false); // This configuration is used for temporary use only. Do not use it if you are sure how it works. And may be deleted in future. - private boolean ignoreRequiredCheck = DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", false).get(); + private final boolean ignoreRequiredCheck = LegacyPropertyFactory + .getBooleanProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", false); - private boolean repeatedType; + private final boolean repeatedType; - private QueryCodec queryCodec; + private final QueryCodec queryCodec; public QueryProcessor(QueryParameter queryParameter, JavaType targetType) { - super(queryParameter.getName(), targetType, queryParameter.getDefaultValue(), queryParameter.getRequired()); + super(queryParameter.getName(), targetType, queryParameter.getSchema().getDefault(), + queryParameter.getRequired() != null && queryParameter.getRequired()); - this.repeatedType = ArrayProperty.isType(queryParameter.getType()); - this.queryCodec = QueryCodecsUtils.find(queryParameter.getCollectionFormat()); + this.repeatedType = queryParameter.getSchema() instanceof ArraySchema; + this.queryCodec = QueryCodecsUtils.find(queryParameter.getStyle(), queryParameter.getExplode()); } @Override @@ -70,8 +73,16 @@ public Object getValue(HttpServletRequest request) { public Object getAndCheckParameter(HttpServletRequest request) { Object value = request.getParameter(paramPath); + + // compatible to SpringMVC @RequestParam. BODY_PARAMETER is only set for SpringMVC. + if (value == null) { + Map forms = (Map) request.getAttribute(RestConst.BODY_PARAMETER); + value = (forms == null || forms.get(paramPath) == null) + ? null : forms.get(paramPath); + } + // make some old systems happy - if (emptyAsNull && StringUtils.isEmpty((String) value)) { + if (emptyAsNull && "".equals(value)) { value = null; } @@ -80,7 +91,8 @@ public Object getAndCheckParameter(HttpServletRequest request) { private Object checkRequiredAndDefaultValue() { if (!ignoreRequiredCheck && isRequired()) { - throw new InvocationException(Status.BAD_REQUEST, "Parameter is required."); + throw new InvocationException(Status.BAD_REQUEST, + String.format("Parameter %s is required.", paramPath)); } Object defaultValue = getDefaultValue(); if (!ignoreDefaultValue && defaultValue != null) { @@ -118,7 +130,8 @@ public QueryProcessorCreator() { } @Override - public ParamValueProcessor create(Parameter parameter, Type genericParamType) { + public ParamValueProcessor create(OperationMeta operationMeta, + String parameterName, Parameter parameter, Type genericParamType) { JavaType targetType = genericParamType == null ? null : TypeFactory.defaultInstance().constructType(genericParamType); return new QueryProcessor((QueryParameter) parameter, targetType); diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java deleted file mode 100644 index 1280af73fe6..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/param/RestClientRequestImpl.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * 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.common.rest.codec.param; - -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; -import static javax.ws.rs.core.MediaType.MULTIPART_FORM_DATA; - -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import javax.servlet.http.Part; -import javax.ws.rs.core.MediaType; - -import org.apache.servicecomb.common.rest.codec.RestClientRequest; -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.foundation.common.utils.PartUtils; -import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; -import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; -import org.apache.servicecomb.foundation.vertx.stream.InputStreamToReadStream; -import org.apache.servicecomb.foundation.vertx.stream.PumpFromPart; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Multimap; - -import io.vertx.core.Context; -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpClientRequest; -import io.vertx.core.http.HttpHeaders; - -public class RestClientRequestImpl implements RestClientRequest { - private static final Logger LOGGER = LoggerFactory.getLogger(RestClientRequestImpl.class); - - protected Context context; - - protected AsyncResponse asyncResp; - - private final Multimap uploads = ArrayListMultimap.create(); - - protected HttpClientRequest request; - - protected Map cookieMap; - - protected Map formMap; - - protected Buffer bodyBuffer; - - private final Handler throwableHandler; - - public RestClientRequestImpl(HttpClientRequest request, Context context, AsyncResponse asyncResp) { - this(request, context, asyncResp, null); - } - - public RestClientRequestImpl(HttpClientRequest request, Context context, AsyncResponse asyncResp, - Handler throwableHandler) { - this.context = context; - this.asyncResp = asyncResp; - this.request = request; - this.throwableHandler = throwableHandler; - } - - @Override - public void write(Buffer bodyBuffer) { - this.bodyBuffer = bodyBuffer; - } - - @Override - public Buffer getBodyBuffer() throws Exception { - genBodyBuffer(); - return bodyBuffer; - } - - @Override - @SuppressWarnings("unchecked") - public void attach(String name, Object partOrList) { - if (null == partOrList) { - LOGGER.debug("null file is ignored, file name = [{}]", name); - return; - } - - if (partOrList.getClass().isArray()) { - for (Object part : (Object[]) partOrList) { - uploads.put(name, PartUtils.getSinglePart(name, part)); - } - } - - if (List.class.isAssignableFrom(partOrList.getClass())) { - for (Object part : (List) partOrList) { - uploads.put(name, PartUtils.getSinglePart(name, part)); - } - return; - } - - uploads.put(name, PartUtils.getSinglePart(name, partOrList)); - } - - @Override - public Future end() { - writeCookies(); - - if (!uploads.isEmpty()) { - return doEndWithUpload(); - } - - return doEndNormal(); - } - - protected Future doEndWithUpload() { - request.setChunked(true); - - String boundary = "boundary" + UUID.randomUUID().toString(); - putHeader(CONTENT_TYPE, MULTIPART_FORM_DATA + "; charset=UTF-8; boundary=" + boundary); - - return genBodyForm(boundary).onSuccess(v -> attachFiles(boundary)).onFailure(e -> asyncResp.consumerFail(e)); - } - - private Future genBodyForm(String boundary) { - if (formMap == null) { - return Future.succeededFuture(); - } - - try { - try (BufferOutputStream output = new BufferOutputStream()) { - for (Entry entry : formMap.entrySet()) { - output.write(bytesOf("\r\n")); - output.write(bytesOf("--" + boundary + "\r\n")); - output.write(bytesOf("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"\r\n\r\n")); - if (entry.getValue() != null) { - String value = RestObjectMapperFactory.getRestObjectMapper().convertToString(entry.getValue()); - output.write(value.getBytes(StandardCharsets.UTF_8)); - } - } - - return writeBuffer(output.getBuffer()); - } - } catch (Exception e) { - return Future.failedFuture(e); - } - } - - private byte[] bytesOf(String string) { - return string.getBytes(StandardCharsets.UTF_8); - } - - protected Future doEndNormal() { - try { - genBodyBuffer(); - } catch (Exception e) { - asyncResp.consumerFail(e); - return Future.succeededFuture(); - } - - if (bodyBuffer == null) { - return request.end(); - } - - return request.end(bodyBuffer); - } - - private void attachFiles(String boundary) { - Iterator> uploadsIterator = uploads.entries().iterator(); - attachFile(boundary, uploadsIterator); - } - - private void attachFile(String boundary, Iterator> uploadsIterator) { - if (!uploadsIterator.hasNext()) { - writeBuffer(boundaryEndInfo(boundary)).onSuccess(v -> request.end()).onFailure(e -> asyncResp.consumerFail(e)); - return; - } - - Entry entry = uploadsIterator.next(); - // do not use part.getName() to get parameter name - // because pojo consumer not easy to set name to part - String name = entry.getKey(); - Part part = entry.getValue(); - String filename = part.getSubmittedFileName(); - - LOGGER.debug("Start attach file [{}:{}].", name, filename); - writeBuffer(fileBoundaryInfo(boundary, name, part)).onSuccess(r -> - new PumpFromPart(context, part).toWriteStream(request, throwableHandler).whenComplete((v, e) -> { - if (e != null) { - LOGGER.warn("Failed attach file [{}:{}].", name, filename, e); - asyncResp.consumerFail(e); - return; - } - - LOGGER.debug("Finish attach file [{}:{}].", name, filename); - attachFile(boundary, uploadsIterator); - })).onFailure(e -> asyncResp.consumerFail(e)); - } - - private Buffer boundaryEndInfo(String boundary) { - return Buffer.buffer() - .appendString("\r\n") - .appendString("--" + boundary + "--\r\n"); - } - - protected Buffer fileBoundaryInfo(String boundary, String name, Part part) { - Buffer buffer = Buffer.buffer(); - buffer.appendString("\r\n"); - buffer.appendString("--" + boundary + "\r\n"); - buffer.appendString("Content-Disposition: form-data; name=\"") - .appendString(name) - .appendString("\"; filename=\"") - .appendString(part.getSubmittedFileName() != null ? part.getSubmittedFileName() : "null") - .appendString("\"\r\n"); - buffer.appendString("Content-Type: ").appendString(part.getContentType()).appendString("\r\n"); - buffer.appendString("Content-Transfer-Encoding: binary\r\n"); - buffer.appendString("\r\n"); - return buffer; - } - - protected Future writeBuffer(Buffer buffer) { - return new InputStreamToReadStream(context, - new BufferInputStream(buffer.getByteBuf()), true).pipe().endOnComplete(false).to(request); - } - - private void genBodyBuffer() throws Exception { - if (bodyBuffer != null) { - return; - } - - if (formMap == null) { - return; - } - - request.putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED); - try (BufferOutputStream output = new BufferOutputStream()) { - for (Entry entry : formMap.entrySet()) { - output.write(entry.getKey().getBytes(StandardCharsets.UTF_8)); - output.write('='); - if (entry.getValue() != null) { - String value = RestObjectMapperFactory.getRestObjectMapper().convertToString(entry.getValue()); - value = URLEncoder.encode(value, StandardCharsets.UTF_8.name()); - output.write(value.getBytes(StandardCharsets.UTF_8)); - } - output.write('&'); - } - bodyBuffer = output.getBuffer(); - } - } - - private void writeCookies() { - if (cookieMap == null) { - return; - } - - StringBuilder builder = new StringBuilder(); - for (Entry entry : cookieMap.entrySet()) { - builder.append(entry.getKey()) - .append('=') - .append(entry.getValue()) - .append("; "); - } - request.putHeader(HttpHeaders.COOKIE, builder.toString()); - } - - public Context getContext() { - return context; - } - - public HttpClientRequest getRequest() { - return request; - } - - public Map getCookieMap() { - return cookieMap; - } - - @Override - public void addCookie(String name, String value) { - if (cookieMap == null) { - cookieMap = new HashMap<>(); - } - - cookieMap.put(name, value); - } - - @Override - public void addForm(String name, Object value) { - if (formMap == null) { - formMap = new HashMap<>(); - } - - if (value != null) { - formMap.put(name, value); - } - } - - @Override - public void putHeader(String name, String value) { - request.putHeader(name, value); - } - - @Override - public MultiMap getHeaders() { - return request.headers(); - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceEventStreamProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceEventStreamProcessor.java new file mode 100644 index 00000000000..64795bf817d --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceEventStreamProcessor.java @@ -0,0 +1,62 @@ +/* + * 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.common.rest.codec.produce; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; + +import com.fasterxml.jackson.databind.JavaType; + +import jakarta.ws.rs.core.MediaType; + +public class ProduceEventStreamProcessor implements ProduceProcessor { + private int writeIndex = 0; + + @Override + public String getName() { + return MediaType.SERVER_SENT_EVENTS; + } + + @Override + public int getOrder() { + return 0; + } + + @Override + public void doEncodeResponse(OutputStream output, Object result) throws Exception { + String buffer = "id: " + (writeIndex++) + "\n" + + "data: " + + RestObjectMapperFactory.getRestObjectMapper().writeValueAsString(result) + + "\n\n"; + output.write(buffer.getBytes(StandardCharsets.UTF_8)); + } + + @Override + public Object doDecodeResponse(InputStream input, JavaType type) throws Exception { + String buffer = new String(input.readAllBytes(), StandardCharsets.UTF_8); + for (String line : buffer.split("\n")) { + if (line.startsWith("data: ")) { + return RestObjectMapperFactory.getRestObjectMapper().readValue(line.substring(5), type); + } + } + return null; + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java index 61989afc7b0..e14451389e5 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceJsonProcessor.java @@ -20,7 +20,7 @@ import java.io.InputStream; import java.io.OutputStream; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java index bcf7cb74b2c..574c1e1b630 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessor.java @@ -72,7 +72,7 @@ default Object decodeResponse(Buffer buffer, JavaType type) throws Exception { return null; } - try (BufferInputStream input = new BufferInputStream(buffer.getByteBuf())) { + try (BufferInputStream input = new BufferInputStream(buffer)) { return doDecodeResponse(input, type); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java index 916ad4f603a..3fdcfec135f 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProcessorManager.java @@ -21,13 +21,18 @@ import java.util.List; import java.util.Map; -import javax.ws.rs.core.MediaType; - +import org.apache.http.entity.ContentType; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.RegisterManager; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.CollectionUtils; + +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import jakarta.ws.rs.core.MediaType; public final class ProduceProcessorManager extends RegisterManager> { private static final Logger LOGGER = LoggerFactory.getLogger(ProduceProcessorManager.class); @@ -37,24 +42,23 @@ public final class ProduceProcessorManager extends RegisterManager nonSerialViewMap = new HashMap<>(); + public static final String PARAM_DEFAULT_RESPONSE_ENCODING = "servicecomb.rest.parameter.default-response-encoding"; + + private static String defaultResponseEncoding; - private Map jsonProcessorMap; + private final Map jsonProcessorMap; - private Map plainProcessorMap; + private final Map plainProcessorMap; - private Map defaultProcessorMap; + private final Map defaultProcessorMap; private ProduceProcessorManager() { super(NAME); produceProcessor.forEach(processor -> { - nonSerialViewMap.put(processor.getName(), processor); Map prodProcessorMap = getObjMap() .computeIfAbsent(processor.getName(), key -> new HashMap<>()); prodProcessorMap.putIfAbsent(processor.getSerializationView(), processor); @@ -68,7 +72,7 @@ private static ProduceProcessor cloneNewProduceProcessor(Class serialViewClas Map produceViewMap) { ProduceProcessor newInstance; try { - newInstance = produceViewMap.get(DEFAULT_SERIAL_CLASS).getClass().newInstance(); + newInstance = produceViewMap.get(DEFAULT_SERIAL_CLASS).getClass().getDeclaredConstructor().newInstance(); newInstance.setSerializationView(serialViewClass); return newInstance; } catch (Throwable e) { @@ -78,30 +82,12 @@ private static ProduceProcessor cloneNewProduceProcessor(Class serialViewClas return produceViewMap.get(DEFAULT_SERIAL_CLASS); } - // key -> accept type - public Map getOrCreateAcceptMap(Class serialViewClass) { - if (serialViewClass == null) { - return nonSerialViewMap; - } - Map result = new HashMap<>(); - getObjMap().forEach((acceptKey, viewMap) -> { - ProduceProcessor produceProcessor = viewMap.computeIfAbsent(serialViewClass.getName(), - viewKey -> cloneNewProduceProcessor(serialViewClass, viewMap)); - result.put(acceptKey, produceProcessor); - }); - return result; - } - - public ProduceProcessor findProcessor(String acceptType, Class serialViewClass) { - Map viewMap = findValue(acceptType); - if (CollectionUtils.isEmpty(viewMap)) { - return null; - } - if (serialViewClass == null) { - return viewMap.get(DEFAULT_SERIAL_CLASS); + private static String defaultResponseEncoding() { + if (defaultResponseEncoding == null) { + defaultResponseEncoding = LegacyPropertyFactory + .getStringProperty(PARAM_DEFAULT_RESPONSE_ENCODING, MediaType.APPLICATION_JSON); } - return viewMap.computeIfAbsent(serialViewClass.getName(), - viewKey -> cloneNewProduceProcessor(serialViewClass, viewMap)); + return defaultResponseEncoding; } public ProduceProcessor findJsonProcessorByViewClass(Class serialViewClass) { @@ -112,14 +98,6 @@ public ProduceProcessor findJsonProcessorByViewClass(Class serialViewClass) { viewKey -> cloneNewProduceProcessor(serialViewClass, jsonProcessorMap)); } - public ProduceProcessor findDefaultProcessorByViewClass(Class serialViewClass) { - if (serialViewClass == null) { - return defaultProcessorMap.get(DEFAULT_SERIAL_CLASS); - } - return defaultProcessorMap.computeIfAbsent(serialViewClass.getName(), - viewKey -> cloneNewProduceProcessor(serialViewClass, defaultProcessorMap)); - } - public ProduceProcessor findPlainProcessorByViewClass(Class serialViewClass) { if (serialViewClass == null) { return plainProcessorMap.get(DEFAULT_SERIAL_CLASS); @@ -139,4 +117,59 @@ public ProduceProcessor findDefaultProcessor() { public ProduceProcessor findDefaultPlainProcessor() { return plainProcessorMap.get(DEFAULT_SERIAL_CLASS); } + + public ProduceProcessor createProduceProcessor(OperationMeta operationMeta, + int statusCode, String accept, Class serialViewClass) { + // If no produces defined, using default processor + ApiResponses responses = operationMeta.getSwaggerOperation().getResponses(); + ApiResponse response = responses.get(String.valueOf(statusCode)); + if (response == null || response.getContent() == null || + response.getContent().size() == 0) { + return findDefaultProcessor(); + } + + // check intersection of `Accept` and `Produces` + if (accept == null) { + if (response.getContent().get(defaultResponseEncoding()) != null) { + accept = defaultResponseEncoding(); + } else { + accept = response.getContent().keySet().iterator().next(); + } + } + + String actualAccept = null; + for (String item : accept.split(",")) { + ContentType contentType = ContentType.parse(item); + if (MediaType.WILDCARD.equals(contentType.getMimeType()) || + MediaType.MEDIA_TYPE_WILDCARD.equals(contentType.getMimeType())) { + if (response.getContent().get(defaultResponseEncoding()) != null) { + actualAccept = defaultResponseEncoding(); + } else { + actualAccept = response.getContent().keySet().iterator().next(); + } + break; + } + if (response.getContent().get(contentType.getMimeType()) != null) { + actualAccept = contentType.getMimeType(); + break; + } + } + + if (actualAccept == null) { + LOGGER.warn("Operation {} do not support accept type {}", operationMeta.getSchemaQualifiedName(), accept); + return findDefaultProcessor(); + } + if (MediaType.APPLICATION_JSON.equals(actualAccept)) { + return findJsonProcessorByViewClass(serialViewClass); + } + if (SwaggerConst.PROTOBUF_TYPE.equals(actualAccept)) { + return new ProduceProtoBufferProcessor(operationMeta, + operationMeta.getSchemaMeta().getSwagger(), response.getContent().get(actualAccept).getSchema()); + } + if (MediaType.SERVER_SENT_EVENTS.equals(actualAccept)) { + return new ProduceEventStreamProcessor(); + } + // text plain + return findPlainProcessorByViewClass(serialViewClass); + } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProtoBufferProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProtoBufferProcessor.java new file mode 100644 index 00000000000..61f56fcacdf --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceProtoBufferProcessor.java @@ -0,0 +1,107 @@ +/* + * 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.common.rest.codec.produce; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.codec.protobuf.utils.ScopedProtobufSchemaManager; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.protobuf.ProtoMapper; +import org.apache.servicecomb.foundation.protobuf.RootDeserializer; +import org.apache.servicecomb.foundation.protobuf.RootSerializer; +import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyWrapper; +import org.apache.servicecomb.swagger.generator.SwaggerConst; + +import com.fasterxml.jackson.databind.JavaType; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Schema; + +public class ProduceProtoBufferProcessor implements ProduceProcessor { + public static final String RESPONSE_MESSAGE_NAME = "X_RESPONSE"; + + public static final String EXT_ID = "protobuf"; + + private static final Object LOCK = new Object(); + + private final OperationMeta operationMeta; + + private final OpenAPI openAPI; + + private final Schema schema; + + private final ScopedProtobufSchemaManager scopedProtobufSchemaManager; + + public ProduceProtoBufferProcessor(OperationMeta operationMeta, OpenAPI openAPI, Schema schema) { + this.operationMeta = operationMeta; + this.openAPI = openAPI; + this.schema = schema; + this.scopedProtobufSchemaManager = getOrCreateScopedProtobufSchemaManager(operationMeta.getMicroserviceMeta()); + } + + private ScopedProtobufSchemaManager getOrCreateScopedProtobufSchemaManager(MicroserviceMeta microserviceMeta) { + ScopedProtobufSchemaManager scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID); + if (scopedProtobufSchemaManager == null) { + synchronized (LOCK) { + scopedProtobufSchemaManager = microserviceMeta.getExtData(EXT_ID); + if (scopedProtobufSchemaManager == null) { + scopedProtobufSchemaManager = new ScopedProtobufSchemaManager(); + microserviceMeta.putExtData(EXT_ID, scopedProtobufSchemaManager); + } + } + } + return scopedProtobufSchemaManager; + } + + @Override + public String getName() { + return SwaggerConst.PROTOBUF_TYPE; + } + + @Override + public int getOrder() { + return 0; + } + + @Override + public void doEncodeResponse(OutputStream output, Object result) throws Exception { + ProtoMapper protoMapper = scopedProtobufSchemaManager + .getOrCreateProtoMapper(openAPI, operationMeta.getSchemaId(), + RESPONSE_MESSAGE_NAME, schema); + RootSerializer serializer = protoMapper.getSerializerSchemaManager() + .createRootSerializer(protoMapper.getProto().getMessage(RESPONSE_MESSAGE_NAME), + Object.class); + Map bodyArg = new HashMap<>(1); + bodyArg.put("value", result); + output.write(serializer.serialize(bodyArg)); + } + + @Override + public Object doDecodeResponse(InputStream input, JavaType type) throws Exception { + ProtoMapper protoMapper = scopedProtobufSchemaManager + .getOrCreateProtoMapper(openAPI, operationMeta.getSchemaId(), + RESPONSE_MESSAGE_NAME, schema); + RootDeserializer> deserializer = protoMapper.getDeserializerSchemaManager() + .createRootDeserializer(protoMapper.getProto().getMessage(RESPONSE_MESSAGE_NAME), type); + PropertyWrapper result = deserializer.deserialize(input.readAllBytes()); + return result.getValue(); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java index 0fa64ba9305..21d73688dc4 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/produce/ProduceTextPlainProcessor.java @@ -21,13 +21,13 @@ import java.io.OutputStream; import java.nio.charset.StandardCharsets; -import javax.ws.rs.core.MediaType; - import org.apache.commons.io.IOUtils; import com.fasterxml.jackson.databind.JavaType; -public class ProduceTextPlainProcessor implements ProduceProcessor { +import jakarta.ws.rs.core.MediaType; + +public class ProduceTextPlainProcessor extends ProduceJsonProcessor { @Override public String getName() { return MediaType.TEXT_PLAIN; @@ -35,17 +35,18 @@ public String getName() { @Override public void doEncodeResponse(OutputStream output, Object result) throws Exception { - output.write(String.valueOf(result).getBytes(StandardCharsets.UTF_8)); + if (result instanceof String) { + output.write(((String) result).getBytes(StandardCharsets.UTF_8)); + return; + } + super.doEncodeResponse(output, result); } @Override public Object doDecodeResponse(InputStream input, JavaType type) throws Exception { - // plainText类型,肯定是返回string的,想不出有其他类型的场景 - return IOUtils.toString(input, StandardCharsets.UTF_8); - } - - @Override - public int getOrder() { - return 0; + if (String.class.equals(type.getRawClass())) { + return IOUtils.toString(input, StandardCharsets.UTF_8); + } + return super.doDecodeResponse(input, type); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/AbstractQueryCodec.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/AbstractQueryCodec.java index 2817f9da830..0ba395bb43f 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/AbstractQueryCodec.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/AbstractQueryCodec.java @@ -20,9 +20,7 @@ import java.util.Collection; import java.util.Collections; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; public abstract class AbstractQueryCodec implements QueryCodec { @@ -39,13 +37,17 @@ public String getCodecName() { @Override @SuppressWarnings("unchecked") - public void encode(URLPathStringBuilder builder, String name, @Nullable Object value) throws Exception { + public void encode(URLPathStringBuilder builder, String name, Object value) throws Exception { if (value == null) { // not write query key to express "null" return; } if (value.getClass().isArray()) { + if (!(value instanceof Object[])) { + value = RestObjectMapperFactory.getRestObjectMapper() + .convertValue(value, Object[].class); + } encode(builder, name, Arrays.asList((Object[]) value)); return; } @@ -58,5 +60,5 @@ public void encode(URLPathStringBuilder builder, String name, @Nullable Object v encode(builder, name, Collections.singletonList(value)); } - abstract void encode(URLPathStringBuilder builder, String name, @Nonnull Collection values) throws Exception; + abstract void encode(URLPathStringBuilder builder, String name, Collection values) throws Exception; } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java index 61364a806fe..b9bfd1b7130 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodec.java @@ -20,25 +20,23 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; import org.springframework.core.Ordered; +import jakarta.servlet.http.HttpServletRequest; + /** * bigger order will override the same name codec */ public interface QueryCodec extends Ordered { - static String encodeValue(@Nonnull Object value) throws UnsupportedEncodingException { + static String encodeValue(Object value) throws UnsupportedEncodingException { return URLEncoder.encode(value.toString(), StandardCharsets.UTF_8.name()); } - // can not replaced by value.toString() because of date serialize - static String convertToString(@Nonnull Object value) throws Exception { + // can not be replaced by value.toString() because of date serialize + static String convertToString(Object value) throws Exception { return RestObjectMapperFactory.getRestObjectMapper().convertToString(value); } @@ -49,7 +47,7 @@ default int getOrder() { String getCodecName(); - void encode(URLPathStringBuilder builder, String name, @Nullable Object value) throws Exception; + void encode(URLPathStringBuilder builder, String name, Object value) throws Exception; Object decode(QueryProcessor processor, HttpServletRequest request); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsv.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsv.java index 706835b5303..dd745c54b73 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsv.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsv.java @@ -16,11 +16,11 @@ */ package org.apache.servicecomb.common.rest.codec.query; -import org.springframework.stereotype.Component; - -@Component +/** + * ?query=x1,x2 + */ public class QueryCodecCsv extends QueryCodecWithDelimiter { - public static final String CODEC_NAME = "csv"; + public static final String CODEC_NAME = "form:0"; public static final String DELIMITER = ","; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecJson.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecJson.java deleted file mode 100644 index ccf4892735c..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecJson.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.common.rest.codec.query; - -import javax.annotation.Nullable; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; -import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; -import org.apache.servicecomb.core.exception.ExceptionCodes; -import org.apache.servicecomb.core.exception.Exceptions; -import org.springframework.stereotype.Component; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.type.TypeFactory; - -@Component -public class QueryCodecJson implements QueryCodec { - public static final String CODEC_NAME = "json"; - - private static final JavaType OBJECT_TYPE = TypeFactory.defaultInstance().constructType(Object.class); - - @Override - public String getCodecName() { - return CODEC_NAME; - } - - @Override - public void encode(URLPathStringBuilder builder, String name, @Nullable Object value) throws Exception { - if (value == null) { - return; - } - - String json = RestObjectMapperFactory.getRestObjectMapper().writeValueAsString(value); - builder.appendQuery(name, QueryCodec.encodeValue(json)); - } - - @Override - public Object decode(QueryProcessor processor, HttpServletRequest request) { - Object value = processor.getAndCheckParameter(request); - if (value == null) { - return null; - } - - try { - JavaType targetType = processor.getTargetType(); - if (targetType == null) { - targetType = OBJECT_TYPE; - } - return RestObjectMapperFactory.getRestObjectMapper().readValue(value.toString(), targetType); - } catch (JsonProcessingException e) { - throw Exceptions - .create(Status.BAD_REQUEST, ExceptionCodes.GENERIC_CLIENT, - "failed to decode query parameter, name=" + processor.getParameterPath()); - } - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMulti.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMulti.java index 2a0c19163ce..4c2f4287916 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMulti.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMulti.java @@ -17,24 +17,24 @@ package org.apache.servicecomb.common.rest.codec.query; import java.util.Collection; +import java.util.Map; -import javax.annotation.Nonnull; -import javax.servlet.http.HttpServletRequest; - +import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; -import org.springframework.stereotype.Component; -@Component +import jakarta.servlet.http.HttpServletRequest; + +@SuppressWarnings("unchecked") public class QueryCodecMulti extends AbstractQueryCodec { - public static final String CODEC_NAME = "multi"; + public static final String CODEC_NAME = "form:1"; public QueryCodecMulti() { super(CODEC_NAME); } @Override - public void encode(URLPathStringBuilder builder, String name, @Nonnull Collection values) throws Exception { + public void encode(URLPathStringBuilder builder, String name, Collection values) throws Exception { for (Object value : values) { if (value == null) { continue; @@ -50,6 +50,23 @@ public Object decode(QueryProcessor processor, HttpServletRequest request) { if (processor.isRepeatedType()) { //Even if the paramPath does not exist, value won't be null at now String[] values = request.getParameterValues(processor.getParameterPath()); + + // compatible to SpringMVC @RequestParam. BODY_PARAMETER is only set for SpringMVC. + if (values == null || values.length == 0) { + Map forms = (Map) request.getAttribute(RestConst.BODY_PARAMETER); + if (forms == null) { + return processor.convertValue(values); + } + Object formValue = forms.get(processor.getParameterPath()); + if (formValue == null) { + return processor.convertValue(values); + } + if (formValue instanceof String[]) { + values = (String[]) formValue; + } else { + values = new String[] {formValue.toString()}; + } + } return processor.convertValue(values); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipes.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipes.java index 2a5160d3a6e..68032f004f4 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipes.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipes.java @@ -16,11 +16,11 @@ */ package org.apache.servicecomb.common.rest.codec.query; -import org.springframework.stereotype.Component; - -@Component +/** + * ?query=x1|x2 + */ public class QueryCodecPipes extends QueryCodecWithDelimiter { - public static final String CODEC_NAME = "pipes"; + public static final String CODEC_NAME = "pipeDelimited:0"; public static final String JOIN_DELIMITER = "|"; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsv.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsv.java index 5c230d0cd8b..514e931d3a0 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsv.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsv.java @@ -16,11 +16,11 @@ */ package org.apache.servicecomb.common.rest.codec.query; -import org.springframework.stereotype.Component; - -@Component +/** + * ?query=x1%20x2 + */ public class QueryCodecSsv extends QueryCodecWithDelimiter { - public static final String CODEC_NAME = "ssv"; + public static final String CODEC_NAME = "spaceDelimited:0"; public static final String DELIMITER = " "; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTsv.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTsv.java deleted file mode 100644 index ee834f8b23a..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTsv.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.common.rest.codec.query; - -import org.springframework.stereotype.Component; - -@Component -public class QueryCodecTsv extends QueryCodecWithDelimiter { - public static final String CODEC_NAME = "tsv"; - - public static final String DELIMITER = "\t"; - - public QueryCodecTsv() { - super(CODEC_NAME, DELIMITER, DELIMITER); - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecWithDelimiter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecWithDelimiter.java index ba9a011666a..f3452bf371e 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecWithDelimiter.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecWithDelimiter.java @@ -19,12 +19,11 @@ import java.util.Collection; import java.util.StringJoiner; -import javax.annotation.Nonnull; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; +import jakarta.servlet.http.HttpServletRequest; + /** * can not support value with delimiter
* a csv example, a collection with two values:
@@ -44,7 +43,7 @@ public QueryCodecWithDelimiter(String codecName, String joinDelimiter, String sp } @Override - public void encode(URLPathStringBuilder builder, String name, @Nonnull Collection values) throws Exception { + public void encode(URLPathStringBuilder builder, String name, Collection values) throws Exception { String joined = join(values); if (joined == null) { return; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecs.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecs.java index 6be3c775bd1..41c5098ef52 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecs.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecs.java @@ -21,14 +21,9 @@ import java.util.List; import java.util.Map; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -@Component public class QueryCodecs { private static final Logger LOGGER = LoggerFactory.getLogger(QueryCodecs.class); @@ -37,7 +32,6 @@ static QueryCodecs createForTest() { new QueryCodecMulti(), new QueryCodecCsv(), new QueryCodecSsv(), - new QueryCodecTsv(), new QueryCodecPipes() )); } @@ -51,7 +45,7 @@ public QueryCodecs(List orderedCodecs) { defaultCodec = codecs.get(QueryCodecMulti.CODEC_NAME); } - private void register(@Nonnull QueryCodec codec) { + private void register(QueryCodec codec) { QueryCodec exists = codecs.put(codec.getCodecName(), codec); if (exists != null) { LOGGER.info("override QueryCodec, exists={}, new={}.", @@ -59,8 +53,7 @@ private void register(@Nonnull QueryCodec codec) { } } - @Nonnull - public QueryCodec find(@Nullable String name) { + public QueryCodec find(String name) { if (name == null) { return defaultCodec; } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsUtils.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsUtils.java index d66a6d84c1a..4b54210c7a0 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsUtils.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsUtils.java @@ -16,12 +16,9 @@ */ package org.apache.servicecomb.common.rest.codec.query; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; -import org.springframework.stereotype.Component; - -@Component public class QueryCodecsUtils { // create a default instance, so that more friendly to UT private static QueryCodecs queryCodecs = QueryCodecs.createForTest(); @@ -30,8 +27,15 @@ public QueryCodecsUtils(QueryCodecs queryCodecs) { QueryCodecsUtils.queryCodecs = queryCodecs; } - @Nonnull - public static QueryCodec find(@Nullable String name) { - return queryCodecs.find(name); + public static QueryCodec find(Parameter.StyleEnum styleEnum, Boolean explode) { + return queryCodecs.find(formatName(styleEnum, explode)); + } + + private static String formatName(StyleEnum styleEnum, Boolean explode) { + if (styleEnum == null) { + return null; + } + return styleEnum + ":" + + (explode != null && explode ? "1" : "0"); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java index 0809656b07d..580175ec680 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestOperationMeta.java @@ -17,57 +17,43 @@ package org.apache.servicecomb.common.rest.definition; -import java.lang.annotation.Annotation; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.common.rest.codec.param.FormProcessorCreator.PartProcessor; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; import org.apache.servicecomb.common.rest.definition.path.PathRegExp; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.utils.MimeTypesUtils; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.fasterxml.jackson.annotation.JsonView; - -import io.swagger.models.Model; -import io.swagger.models.ModelImpl; -import io.swagger.models.Operation; -import io.swagger.models.Response; -import io.swagger.models.Swagger; -import io.swagger.models.parameters.BodyParameter; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.properties.FileProperty; -import io.swagger.models.properties.Property; -import io.swagger.models.properties.StringProperty; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; +import jakarta.ws.rs.core.MediaType; +@SuppressWarnings("rawtypes") public class RestOperationMeta { private static final Logger LOGGER = LoggerFactory.getLogger(RestOperationMeta.class); protected OperationMeta operationMeta; - protected List produces; - protected boolean formData; // make sure if response is file protected boolean downloadFile; + protected boolean serverSendEvents; + protected List paramList = new ArrayList<>(); // key为参数名 @@ -75,12 +61,6 @@ public class RestOperationMeta { protected List fileKeys = new ArrayList<>(); - // key为数据类型,比如json之类 - private Map produceProcessorMap = new LinkedHashMap<>(); - - // 不一定等于mgr中的default,因为本operation可能不支持mgr中的default - private ProduceProcessor defaultProcessor; - protected String absolutePath; protected PathRegExp absolutePathRegExp; @@ -91,69 +71,92 @@ public class RestOperationMeta { public void init(OperationMeta operationMeta) { this.operationMeta = operationMeta; - Swagger swagger = operationMeta.getSchemaMeta().getSwagger(); + OpenAPI swagger = operationMeta.getSchemaMeta().getSwagger(); Operation operation = operationMeta.getSwaggerOperation(); - this.produces = operation.getProduces(); - if (produces == null) { - this.produces = swagger.getProduces(); - } this.downloadFile = checkDownloadFileFlag(); - this.createProduceProcessors(); - - // 初始化所有rest param - for (int swaggerParameterIdx = 0; swaggerParameterIdx < operation.getParameters().size(); swaggerParameterIdx++) { - Parameter parameter = operation.getParameters().get(swaggerParameterIdx); + this.serverSendEvents = checkServerSendEvents(); + + if (operation.getParameters() != null) { + for (int swaggerParameterIdx = 0; swaggerParameterIdx < operation.getParameters().size(); swaggerParameterIdx++) { + Parameter parameter = operation.getParameters().get(swaggerParameterIdx); + Type type = operationMeta.getSwaggerProducerOperation() != null ? operationMeta.getSwaggerProducerOperation() + .getSwaggerParameterTypes().get(parameter.getName()) : null; + RestParam param = new RestParam(operationMeta, parameter, type); + addParam(param); + } + } - if ("formData".equals(parameter.getIn())) { + if (operation.getRequestBody() != null) { + if (isFormParameters(operation)) { formData = true; + Schema formSchema = formSchemas(operation); + if (formSchema != null) { + formSchema.getProperties().forEach((k, v) -> { + addRestParamByName(operationMeta, (String) k, operation); + }); + } + } else { + addRestParamByName(operationMeta, + (String) operation.getRequestBody().getExtensions().get(SwaggerConst.EXT_BODY_NAME), operation); } - - Type type = operationMeta.getSwaggerProducerOperation() != null ? operationMeta.getSwaggerProducerOperation() - .getSwaggerParameterTypes().get(parameter.getName()) : null; - type = correctFormBodyType(parameter, type); - RestParam param = new RestParam(parameter, type); - addParam(param); } - setAbsolutePath(concatPath(swagger.getBasePath(), operationMeta.getOperationPath())); + setAbsolutePath(SwaggerUtils.concatAbsolutePath(swagger, operationMeta.getOperationPath())); } - /** - * EdgeService cannot recognize the map type form body whose value type is String, - * so there should be this additional setting. - * @param parameter the swagger information of the parameter - * @param type the resolved param type - * @return the corrected param type - */ - private Type correctFormBodyType(Parameter parameter, Type type) { - if (null != type || !(parameter instanceof BodyParameter)) { - return type; - } - final BodyParameter bodyParameter = (BodyParameter) parameter; - if (!(bodyParameter.getSchema() instanceof ModelImpl)) { - return type; - } - final Property additionalProperties = ((ModelImpl) bodyParameter.getSchema()).getAdditionalProperties(); - if (additionalProperties instanceof StringProperty) { - type = RestObjectMapperFactory.getRestObjectMapper().getTypeFactory() - .constructMapType(Map.class, String.class, String.class); + private void addRestParamByName(OperationMeta operationMeta, String name, Operation operation) { + Type type = operationMeta.getSwaggerProducerOperation() != null ? operationMeta.getSwaggerProducerOperation() + .getSwaggerParameterTypes().get(name) : null; + RestParam param = new RestParam(operationMeta, name, operation.getRequestBody(), formData, type); + addParam(param); + } + + private boolean isFormParameters(Operation operation) { + return operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE) != null || + operation.getRequestBody().getContent().get(SwaggerConst.FILE_MEDIA_TYPE) != null; + } + + private Schema formSchemas(Operation operation) { + if (operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE) != null) { + return operation.getRequestBody().getContent().get(SwaggerConst.FORM_MEDIA_TYPE).getSchema(); } - return type; + return operation.getRequestBody().getContent().get(SwaggerConst.FILE_MEDIA_TYPE).getSchema(); } public boolean isDownloadFile() { return downloadFile; } - private boolean checkDownloadFileFlag() { - Response response = operationMeta.getSwaggerOperation().getResponses().get("200"); - if (response != null) { - Model model = response.getResponseSchema(); - return model instanceof ModelImpl && - FileProperty.isType(((ModelImpl) model).getType(), ((ModelImpl) model).getFormat()); + public boolean isServerSendEvents() { + return serverSendEvents; + } + + private boolean checkServerSendEvents() { + ApiResponses responses = operationMeta.getSwaggerOperation().getResponses(); + if (responses == null) { + return false; } + ApiResponse response = responses.get(SwaggerConst.SUCCESS_KEY); + return response != null && response.getContent() != null + && response.getContent().get(MediaType.SERVER_SENT_EVENTS) != null; + } + private boolean checkDownloadFileFlag() { + ApiResponses responses = operationMeta.getSwaggerOperation().getResponses(); + if (responses == null) { + return false; + } + ApiResponse response = responses.get(SwaggerConst.SUCCESS_KEY); + if (response != null && response.getContent() != null) { + for (io.swagger.v3.oas.models.media.MediaType mediaType : response.getContent().values()) { + if (mediaType.getSchema() != null + && "string".equals(mediaType.getSchema().getType()) + && "binary".equals(mediaType.getSchema().getFormat())) { + return true; + } + } + } return false; } @@ -165,16 +168,6 @@ public void setOperationMeta(OperationMeta operationMeta) { this.operationMeta = operationMeta; } - // 输出b/c/形式的url - private String concatPath(String basePath, String operationPath) { - return ("/" + nonNullify(basePath) + "/" + nonNullify(operationPath) + "/") - .replaceAll("/{2,}", "/"); - } - - private String nonNullify(String path) { - return path == null ? "" : path; - } - public String getAbsolutePath() { return this.absolutePath; } @@ -198,7 +191,7 @@ protected PathRegExp createPathRegExp(String path) { throw new Error("null rest url is not supported"); } try { - return new PathRegExp(path); + return new PathRegExp(OperationLocator.getStandardPath(path)); } catch (Exception e) { LOGGER.error(e.getMessage()); return null; @@ -209,72 +202,10 @@ public RestParam getParamByName(String name) { return paramMap.get(name); } - public RestParam getParamByIndex(int index) { - return paramList.get(index); - } - public OperationMeta getOperationMeta() { return operationMeta; } - protected void createProduceProcessors() { - SwaggerProducerOperation producerOperation = operationMeta.getExtData(Const.PRODUCER_OPERATION); - if (producerOperation != null && producerOperation.getProducerMethod() != null) { - createProduceProcessors(producerOperation.getProducerMethod().getDeclaredAnnotations()); - return; - } - createProduceProcessors(null); - } - - // serialViewClass is deterministic for each operation - protected void createProduceProcessors(Annotation[] annotations) { - if (annotations == null || annotations.length < 1) { - doCreateProduceProcessors(null); - return; - } - for (Annotation annotation : annotations) { - if (annotation.annotationType() == JsonView.class) { - Class[] value = ((JsonView) annotation).value(); - if (value.length != 1) { - throw new IllegalArgumentException( - "@JsonView only supported for exactly 1 class argument "); - } - doCreateProduceProcessors(value[0]); - return; - } - } - doCreateProduceProcessors(null); - } - - // 为operation创建支持的多种produce processor - protected void doCreateProduceProcessors(Class serialViewClass) { - if (null == produces || produces.isEmpty()) { - produceProcessorMap.putAll( - ProduceProcessorManager.INSTANCE.getOrCreateAcceptMap(serialViewClass)); - } else { - for (String produce : produces) { - if (produce.contains(";")) { - produce = produce.substring(0, produce.indexOf(";")); - } - ProduceProcessor processor = ProduceProcessorManager.INSTANCE.findProcessor(produce, serialViewClass); - if (processor == null) { - LOGGER.error("produce {} is not supported, operation={}.", produce, - operationMeta.getMicroserviceQualifiedName()); - continue; - } - this.produceProcessorMap.put(produce, processor); - } - - if (produceProcessorMap.isEmpty()) { - produceProcessorMap.put(ProduceProcessorManager.DEFAULT_TYPE, - ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(serialViewClass)); - } - } - - defaultProcessor = produceProcessorMap.values().stream().findFirst().get(); - produceProcessorMap.putIfAbsent(MediaType.WILDCARD, defaultProcessor); - } - public URLPathBuilder getPathBuilder() { return this.pathBuilder; } @@ -291,37 +222,6 @@ private void addParam(RestParam param) { paramMap.put(param.getParamName(), param); } - public ProduceProcessor findProduceProcessor(String type) { - return this.produceProcessorMap.get(type); - } - - // 选择与accept匹配的produce processor或者缺省的 - public ProduceProcessor ensureFindProduceProcessor(HttpServletRequestEx requestEx) { - String acceptType = requestEx.getHeader(HttpHeaders.ACCEPT); - return ensureFindProduceProcessor(acceptType); - } - - public ProduceProcessor ensureFindProduceProcessor(String acceptType) { - if (downloadFile) { - //do not check accept type, when the produces of provider is text/plain there will return text/plain processor - //when the produces of provider is application/json there will return the application/json processor - //so do not care what accept type the consumer will set. - return this.produceProcessorMap.get(MediaType.WILDCARD); - } - if (StringUtils.isEmpty(acceptType)) { - return defaultProcessor; - } - List mimeTypes = MimeTypesUtils.getSortedAcceptableMimeTypes(acceptType.toLowerCase(Locale.US)); - for (String mime : mimeTypes) { - ProduceProcessor processor = this.produceProcessorMap.get(mime); - if (null != processor) { - return processor; - } - } - - return null; - } - public String getHttpMethod() { return operationMeta.getHttpMethod(); } @@ -329,8 +229,4 @@ public String getHttpMethod() { public List getFileKeys() { return fileKeys; } - - public List getProduces() { - return produces; - } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java index 2615646ea37..a2b44674c6f 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/RestParam.java @@ -21,15 +21,20 @@ import java.util.Collection; import java.util.Map; +import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator; +import org.apache.servicecomb.common.rest.codec.param.FormProcessorCreator; import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessor; import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessorCreator; import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessorCreatorManager; +import org.apache.servicecomb.core.definition.OperationMeta; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.RequestBody; +@SuppressWarnings({"rawtypes", "unchecked"}) public class RestParam { private static final JavaType STRING_ARRAY_TYPE = TypeFactory.defaultInstance().constructArrayType(String.class); @@ -37,12 +42,20 @@ public class RestParam { protected String paramName; - public RestParam(Parameter parameter, Type genericParamType) { + public RestParam(OperationMeta operationMeta, Parameter parameter, Type genericParamType) { this.paramName = parameter.getName(); - init(parameter, genericParamType); + init(operationMeta, parameter, genericParamType); } + public RestParam(OperationMeta operationMeta, + String paramName, RequestBody parameter, boolean isForm, Type genericParamType) { + this.paramName = paramName; + + init(operationMeta, parameter, isForm, genericParamType); + } + + public ParamValueProcessor getParamProcessor() { return this.paramProcessor; } @@ -55,15 +68,28 @@ public String getParamName() { return paramName; } - protected void init(Parameter parameter, Type genericParamType) { + protected void init(OperationMeta operationMeta, Parameter parameter, Type genericParamType) { String paramType = parameter.getIn(); ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.ensureFindValue(paramType); - this.setParamProcessor(creator.create(parameter, genericParamType)); + this.setParamProcessor(creator.create(operationMeta, parameter.getName(), parameter, genericParamType)); + } + + protected void init(OperationMeta operationMeta, RequestBody parameter, boolean isForm, Type genericParamType) { + ParamValueProcessorCreator creator; + if (isForm) { + creator = + ParamValueProcessorCreatorManager.INSTANCE.ensureFindValue(FormProcessorCreator.PARAMTYPE); + } else { + creator = + ParamValueProcessorCreatorManager.INSTANCE.ensureFindValue(BodyProcessorCreator.PARAM_TYPE); + } + + this.setParamProcessor(creator.create(operationMeta, this.paramName, + parameter, genericParamType)); } - @SuppressWarnings("unchecked") public T getValue(Map args) { return (T) args.get(paramName); } @@ -74,7 +100,7 @@ public String[] getValueAsStrings(Map args) { return null; } - if (value.getClass().isArray() || Collection.class.isInstance(value)) { + if (value.getClass().isArray() || value instanceof Collection) { return (String[]) paramProcessor.convertValue(value, STRING_ARRAY_TYPE); } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/AbstractUrlParamWriter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/AbstractUrlParamWriter.java index 2ab28c15a5f..d4eca87d86c 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/AbstractUrlParamWriter.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/AbstractUrlParamWriter.java @@ -19,12 +19,14 @@ import java.util.Map; +import com.google.common.annotations.VisibleForTesting; import org.apache.servicecomb.common.rest.definition.RestParam; public abstract class AbstractUrlParamWriter implements UrlParamWriter { protected RestParam param; - protected Object getParamValue(Map args) { + @VisibleForTesting + public Object getParamValue(Map args) { if (param == null) { // Wrong server definition // @GetMapping(path = "/getLocalDateTime/{paramX}") diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/StaticUrlParamWriter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/StaticUrlParamWriter.java index 42814eb9a3f..ff9e9658f7b 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/StaticUrlParamWriter.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/StaticUrlParamWriter.java @@ -23,7 +23,7 @@ public class StaticUrlParamWriter implements UrlParamWriter { - private String staticPath; + private final String staticPath; public StaticUrlParamWriter(String staticPath) { this.staticPath = staticPath; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilder.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilder.java index c66dece6be5..a59c904ff41 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilder.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilder.java @@ -21,8 +21,6 @@ import java.util.List; import java.util.Map; -import javax.annotation.Nonnull; - import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator; import org.apache.servicecomb.common.rest.definition.RestParam; @@ -31,9 +29,9 @@ */ public class URLPathBuilder { - private List pathParamWriterList = new ArrayList<>(); + private final List pathParamWriterList = new ArrayList<>(); - private List queryParamWriterList = new ArrayList<>(); + private final List queryParamWriterList = new ArrayList<>(); private static final String SLASH = "/"; @@ -54,10 +52,6 @@ private void initQueryWriterList(Map paramMap) { } private void initPathWriterList(String rawPath, Map paramMap) { - // 去掉末尾'/' - if (rawPath.endsWith(SLASH)) { - rawPath = rawPath.substring(0, rawPath.length() - 1); - } // 首部加上'/' if (!rawPath.startsWith(SLASH)) { rawPath = SLASH + rawPath; @@ -120,7 +114,7 @@ private void genQueryString(URLPathStringBuilder builder, Map ar } public static class URLPathStringBuilder { - private StringBuilder stringBuilder = new StringBuilder(); + private final StringBuilder stringBuilder = new StringBuilder(); private boolean queryPrefixNotWrite = true; @@ -129,7 +123,7 @@ public URLPathStringBuilder appendPath(String s) { return this; } - public URLPathStringBuilder appendQuery(@Nonnull String name, @Nonnull String encodedValue) { + public URLPathStringBuilder appendQuery(String name, String encodedValue) { if (queryPrefixNotWrite) { stringBuilder.append('?'); queryPrefixNotWrite = false; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java deleted file mode 100644 index a139712c14c..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpClientFilter.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.common.rest.filter; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; - -public interface HttpClientFilter { - default boolean enabled() { - return true; - } - - int getOrder(); - - void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx); - - // if finished, then return a none null response - // if return a null response, then sdk will call next filter.afterReceive - Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx); -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java deleted file mode 100644 index b809660a48a..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.common.rest.filter; - -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; - -public interface HttpServerFilter { - int getOrder(); - - default boolean enabled() { - return true; - } - - default boolean needCacheRequest(OperationMeta operationMeta) { - return false; - } - - /** - * @return if finished, then return a none null response
- * if return a null response, then sdk will call next filter.afterReceiveRequest - */ - Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx); - - /** - * @param invocation maybe null - */ - default CompletableFuture beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) { - CompletableFuture future = new CompletableFuture<>(); - try { - beforeSendResponse(invocation, responseEx); - future.complete(null); - } catch (Throwable e) { - future.completeExceptionally(e); - } - return future; - } - - /** - * @param invocation maybe null - */ - default void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) { - - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilterBeforeSendResponseExecutor.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilterBeforeSendResponseExecutor.java deleted file mode 100644 index d96f3f8ec8a..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/HttpServerFilterBeforeSendResponseExecutor.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.common.rest.filter; - -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; - -public class HttpServerFilterBeforeSendResponseExecutor { - private List httpServerFilters; - - private Invocation invocation; - - private HttpServletResponseEx responseEx; - - private int currentIndex; - - private CompletableFuture future = new CompletableFuture(); - - public HttpServerFilterBeforeSendResponseExecutor(List httpServerFilters, Invocation invocation, - HttpServletResponseEx responseEx) { - this.httpServerFilters = httpServerFilters; - this.invocation = invocation; - this.responseEx = responseEx; - } - - public CompletableFuture run() { - doRun(); - - return future; - } - - protected CompletableFuture safeInvoke(HttpServerFilter httpServerFilter) { - try { - if (httpServerFilter.enabled()) { - CompletableFuture future = httpServerFilter.beforeSendResponseAsync(invocation, responseEx); - if (future == null) { - future = new CompletableFuture<>(); - future.completeExceptionally(new IllegalStateException( - "HttpServerFilter beforeSendResponseAsync can not return null, do not override it. Class=" - + httpServerFilter.getClass() - .getName())); - } - return future; - } else { - CompletableFuture eFuture = new CompletableFuture<>(); - eFuture.complete(null); - return eFuture; - } - } catch (Throwable e) { - CompletableFuture eFuture = new CompletableFuture<>(); - eFuture.completeExceptionally(e); - return eFuture; - } - } - - protected void doRun() { - if (currentIndex == httpServerFilters.size()) { - future.complete(null); - return; - } - - HttpServerFilter httpServerFilter = httpServerFilters.get(currentIndex); - currentIndex++; - - CompletableFuture stepFuture = safeInvoke(httpServerFilter); - stepFuture.whenComplete((v, e) -> { - if (e == null) { - doRun(); - return; - } - - future.completeExceptionally(e); - }); - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java deleted file mode 100644 index 8babd970190..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ClientRestArgsFilter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.common.rest.filter.inner; - -import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.RestCodec; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.common.rest.filter.HttpClientFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; - -public class ClientRestArgsFilter implements HttpClientFilter { - - @Override - public int getOrder() { - return -100; - } - - @Override - @SuppressWarnings("unchecked") - public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) { - RestClientRequestImpl restClientRequest = (RestClientRequestImpl) invocation.getHandlerContext() - .get(RestConst.INVOCATION_HANDLER_REQUESTCLIENT); - OperationMeta operationMeta = invocation.getOperationMeta(); - RestOperationMeta swaggerRestOperation = operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - try { - RestCodec.argsToRest(invocation.getSwaggerArguments(), swaggerRestOperation, - restClientRequest); - requestEx.setBodyBuffer(restClientRequest.getBodyBuffer()); - } catch (Throwable e) { - throw ExceptionFactory.convertConsumerException(e); - } - } - - @Override - public Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx) { - return null; - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java index a6d166eca3a..1d21e9c8bbd 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java @@ -21,42 +21,64 @@ import static com.google.common.net.HttpHeaders.TRANSFER_ENCODING; import static org.apache.servicecomb.core.exception.Exceptions.toProducerResponse; +import java.io.IOException; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.CompletableFuture; -import javax.annotation.Nonnull; -import javax.servlet.http.Part; - import org.apache.servicecomb.common.rest.HttpTransportContext; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestCodec; import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; +import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.filter.ProducerFilter; -import org.apache.servicecomb.foundation.common.utils.AsyncUtils; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.foundation.common.utils.PartUtils; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; +import org.apache.servicecomb.swagger.invocation.context.TransportContext; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import io.netty.buffer.Unpooled; import io.vertx.core.MultiMap; +import io.vertx.core.buffer.Buffer; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.HttpHeaders; + +public class RestServerCodecFilter extends AbstractFilter implements ProviderFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(RestServerCodecFilter.class); -@Component -public class RestServerCodecFilter implements ProducerFilter { public static final String NAME = "rest-server-codec"; - @Nonnull @Override public String getName() { return NAME; } + @Override + public int getOrder() { + // almost time, should be the first filter. + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 2000; + } + + @Override + public boolean enabledForTransport(String transport) { + return CoreConst.RESTFUL.equals(transport); + } + @Override public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { return CompletableFuture.completedFuture(invocation) @@ -67,51 +89,149 @@ public CompletableFuture onFilter(Invocation invocation, FilterNode ne } protected CompletableFuture invokeNext(Invocation invocation, FilterNode nextNode) { + if (invocation.isEdge()) { + TransportContext transportContext = invocation.getTransportContext(); + return nextNode.onFilter(invocation).whenComplete((r, e) -> invocation.setTransportContext(transportContext)); + } return nextNode.onFilter(invocation); } - protected Void decodeRequest(Invocation invocation) { + protected void decodeRequest(Invocation invocation) { + invocation.getInvocationStageTrace().startProviderDecodeRequest(); HttpServletRequestEx requestEx = invocation.getRequestEx(); OperationMeta operationMeta = invocation.getOperationMeta(); RestOperationMeta restOperationMeta = operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); Map swaggerArguments = RestCodec.restToArgs(requestEx, restOperationMeta); invocation.setSwaggerArguments(swaggerArguments); - - return null; + invocation.getInvocationStageTrace().finishProviderDecodeRequest(); } protected CompletableFuture encodeResponse(Invocation invocation, Response response) { invocation.onEncodeResponseStart(response); - HttpTransportContext transportContext = invocation.getTransportContext(); - ProduceProcessor produceProcessor = transportContext.getProduceProcessor(); HttpServletResponseEx responseEx = transportContext.getResponseEx(); - boolean download = isDownloadFileResponseType(invocation, response); + // TODO: response support JsonView + ProduceProcessor produceProcessor = ProduceProcessorManager.INSTANCE + .createProduceProcessor(invocation.getOperationMeta(), response.getStatusCode(), + invocation.getRequestEx().getHeader(HttpHeaders.ACCEPT), null); - return encodeResponse(response, download, produceProcessor, responseEx); + return encodeResponse(invocation, response, produceProcessor, responseEx) + .whenComplete((r, e) -> invocation.onEncodeResponseFinish()); } - @SuppressWarnings("deprecation") - public static CompletableFuture encodeResponse(Response response, boolean download, - ProduceProcessor produceProcessor, HttpServletResponseEx responseEx) { - responseEx.setStatus(response.getStatusCode(), response.getReasonPhrase()); - copyHeadersToHttpResponse(response.getHeaders(), responseEx); + private static boolean isFailedResponse(Response response) { + return response.getResult() instanceof InvocationException; + } + + private static CompletableFuture writePart( + HttpServletResponseEx responseEx, Object data, Response response) { + CompletableFuture result = new CompletableFuture<>(); + responseEx.sendPart(PartUtils.getSinglePart(null, data)) + .whenComplete((r, e) -> { + if (e != null) { + result.completeExceptionally(e); + return; + } + result.complete(response); + }); + return result; + } + + private static CompletableFuture writeResponse( + HttpServletResponseEx responseEx, ProduceProcessor produceProcessor, Object data, Response response, + boolean commit) { + try (BufferOutputStream output = new BufferOutputStream(Buffer.buffer())) { + produceProcessor.encodeResponse(output, data); - if (download) { - return CompletableFuture.completedFuture(response); + CompletableFuture result = new CompletableFuture<>(); + responseEx.setBodyBuffer(output.getBuffer()); // For extensions usage + if (commit) { + responseEx.setContentLength(output.getBuffer().length()); + } + responseEx.sendBuffer(output.getBuffer()).whenComplete((v, e) -> { + if (e != null) { + result.completeExceptionally(e); + return; + } + if (!commit) { + try { + responseEx.flushBuffer(); + } catch (IOException ex) { + LOGGER.warn("Failed to flush buffer for Server Send Events", ex); + } + } + result.complete(response); + }); + return result; + } catch (Throwable e) { + LOGGER.error("internal service error must be fixed.", e); + responseEx.setStatus(500); + return CompletableFuture.failedFuture(e); } + } + + public static CompletableFuture encodeResponse(Invocation invocation, Response response, + ProduceProcessor produceProcessor, HttpServletResponseEx responseEx) { + responseEx.setStatus(response.getStatusCode()); + copyHeadersToHttpResponse(invocation, response.getHeaders(), responseEx); - responseEx.setContentType(produceProcessor.getName() + "; charset=utf-8"); - try (BufferOutputStream output = new BufferOutputStream(Unpooled.compositeBuffer())) { - produceProcessor.encodeResponse(output, response.getResult()); + if (isFailedResponse(response)) { + responseEx.setContentType(produceProcessor.getName()); + return writeResponse(responseEx, produceProcessor, ((InvocationException) response.getResult()).getErrorData(), + response, true); + } - responseEx.setBodyBuffer(output.getBuffer()); + if (isDownloadFileResponseType(invocation, response)) { + return writePart(responseEx, response.getResult(), response); + } - return CompletableFuture.completedFuture(response); - } catch (Throwable e) { - return AsyncUtils.completeExceptionally(e); + if (isServerSendEvent(response)) { + responseEx.setContentType(produceProcessor.getName()); + return writeServerSendEvent(response, produceProcessor, responseEx); } + + responseEx.setContentType(produceProcessor.getName()); + return writeResponse(responseEx, produceProcessor, response.getResult(), response, true); + } + + private static CompletableFuture writeServerSendEvent(Response response, ProduceProcessor produceProcessor, + HttpServletResponseEx responseEx) { + responseEx.setChunked(true); + CompletableFuture result = new CompletableFuture<>(); + Publisher publisher = response.getResult(); + publisher.subscribe(new Subscriber() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + s.request(1); + subscription = s; + } + + @Override + public void onNext(Object o) { + writeResponse(responseEx, produceProcessor, o, response, false).whenComplete((r, e) -> { + if (e != null) { + subscription.cancel(); + result.completeExceptionally(e); + return; + } + subscription.request(1); + }); + } + + @Override + public void onError(Throwable t) { + result.completeExceptionally(t); + } + + @Override + public void onComplete() { + result.complete(response); + } + }); + return result; } /** @@ -125,15 +245,22 @@ public static boolean isDownloadFileResponseType(Invocation invocation, Response invocation.findResponseType(response.getStatusCode()).getRawClass()); } - public static void copyHeadersToHttpResponse(MultiMap headers, HttpServletResponseEx responseEx) { - if (headers == null) { - return; + public static boolean isServerSendEvent(Response response) { + return response.getResult() instanceof Publisher; + } + + public static void copyHeadersToHttpResponse(Invocation invocation, MultiMap headers, + HttpServletResponseEx responseEx) { + if (headers != null) { + headers.remove(CONTENT_LENGTH); + headers.remove(TRANSFER_ENCODING); + for (Entry entry : headers.entries()) { + responseEx.addHeader(entry.getKey(), entry.getValue()); + } } - headers.remove(CONTENT_LENGTH); - headers.remove(TRANSFER_ENCODING); - for (Entry entry : headers.entries()) { - responseEx.addHeader(entry.getKey(), entry.getValue()); + if (invocation != null && responseEx.getHeader(CoreConst.TRACE_ID_NAME) == null) { + responseEx.addHeader(CoreConst.TRACE_ID_NAME, invocation.getTraceId()); } } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ServerRestArgsFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ServerRestArgsFilter.java deleted file mode 100644 index 63ae8eea92a..00000000000 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/ServerRestArgsFilter.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.common.rest.filter.inner; - -import static org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter.isDownloadFileResponseType; - -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.RestCodec; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.utils.PartUtils; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -import com.netflix.config.DynamicPropertyFactory; - -import io.netty.buffer.Unpooled; - -public class ServerRestArgsFilter implements HttpServerFilter { - private static final boolean enabled = DynamicPropertyFactory.getInstance().getBooleanProperty - ("servicecomb.http.filter.server.serverRestArgs.enabled", true).get(); - - @Override - public int getOrder() { - return -100; - } - - @Override - public boolean enabled() { - return enabled; - } - - @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { - OperationMeta operationMeta = invocation.getOperationMeta(); - RestOperationMeta restOperationMeta = operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - Map swaggerArguments = RestCodec.restToArgs(requestEx, restOperationMeta); - invocation.setSwaggerArguments(swaggerArguments); - return null; - } - - @Override - public CompletableFuture beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) { - Response response = (Response) responseEx.getAttribute(RestConst.INVOCATION_HANDLER_RESPONSE); - ProduceProcessor produceProcessor = - (ProduceProcessor) responseEx.getAttribute(RestConst.INVOCATION_HANDLER_PROCESSOR); - Object body = response.getResult(); - if (response.isFailed()) { - body = ((InvocationException) body).getErrorData(); - } - - if (null != invocation && isDownloadFileResponseType(invocation, response)) { - return responseEx.sendPart(PartUtils.getSinglePart(null, body)); - } - - responseEx.setContentType(produceProcessor.getName() + "; charset=utf-8"); - - CompletableFuture future = new CompletableFuture<>(); - try (BufferOutputStream output = new BufferOutputStream(Unpooled.compositeBuffer())) { - produceProcessor.encodeResponse(output, body); - - responseEx.setBodyBuffer(output.getBuffer()); - future.complete(null); - } catch (Throwable e) { - future.completeExceptionally(ExceptionFactory.convertProducerException(e)); - } - return future; - } -} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/WebSocketServerCodecFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/WebSocketServerCodecFilter.java new file mode 100644 index 00000000000..79e7368520b --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/WebSocketServerCodecFilter.java @@ -0,0 +1,124 @@ +/* + * 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.common.rest.filter.inner; + +import static org.apache.servicecomb.core.exception.Exceptions.toProducerResponse; + +import java.util.HashMap; +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.common.rest.WebSocketTransportContext; +import org.apache.servicecomb.common.rest.codec.produce.ProduceJsonProcessor; +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.context.TransportContext; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.ServerWebSocket; + +public class WebSocketServerCodecFilter extends AbstractFilter implements ProviderFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketServerCodecFilter.class); + + public static final String NAME = "websocket-codec"; + + @Override + public String getName() { + return NAME; + } + + @Override + public int getOrder() { + // almost time, should be the first filter. + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 2000; + } + + @Override + public boolean enabledForTransport(String transport) { + return CoreConst.WEBSOCKET.equals(transport); + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + return CompletableFuture.completedFuture(invocation) + .thenCompose(this::decodeRequest) + .thenCompose(v -> invokeNext(invocation, nextNode)) + .exceptionally(exception -> toProducerResponse(invocation, exception)) + .thenCompose(response -> encodeResponse(invocation, response)); + } + + protected CompletableFuture invokeNext(Invocation invocation, FilterNode nextNode) { + if (invocation.isEdge()) { + TransportContext transportContext = invocation.getTransportContext(); + return nextNode.onFilter(invocation).whenComplete((r, e) -> invocation.setTransportContext(transportContext)); + } + return nextNode.onFilter(invocation); + } + + protected CompletableFuture decodeRequest(Invocation invocation) { + invocation.getInvocationStageTrace().startProviderDecodeRequest(); + invocation.setSwaggerArguments(new HashMap<>()); // set context parameters and do nothing else. + invocation.getInvocationStageTrace().finishProviderDecodeRequest(); + return CompletableFuture.completedFuture(null); + } + + protected CompletableFuture encodeResponse(Invocation invocation, Response response) { + invocation.onEncodeResponseStart(response); + WebSocketTransportContext context = invocation.getTransportContext(); + + return encodeResponse(response, context.getServerWebSocket()) + .whenComplete((r, e) -> invocation.onEncodeResponseFinish()); + } + + private static boolean isFailedResponse(Response response) { + return response.getResult() instanceof InvocationException; + } + + private static CompletableFuture writeResponse( + ServerWebSocket webSocket, Object data, Response response) { + try (BufferOutputStream output = new BufferOutputStream(Buffer.buffer())) { + ProduceJsonProcessor produceProcessor = new ProduceJsonProcessor(); + produceProcessor.encodeResponse(output, data); + CompletableFuture result = new CompletableFuture<>(); + webSocket.write(output.getBuffer()).onComplete(v -> + result.complete(response), result::completeExceptionally); + + return result; + } catch (Throwable e) { + LOGGER.error("internal service error must be fixed.", e); + return CompletableFuture.failedFuture(e); + } + } + + public static CompletableFuture encodeResponse(Response response, ServerWebSocket webSocket) { + if (isFailedResponse(response)) { + return writeResponse(webSocket, ((InvocationException) response.getResult()).getErrorData(), + response); + } + return CompletableFuture.completedFuture(response); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/MicroservicePaths.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/MicroservicePaths.java index 2137a043052..3df5c699403 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/MicroservicePaths.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/MicroservicePaths.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -44,7 +43,7 @@ public class MicroservicePaths { public void sortPath() { RestOperationComparator comparator = new RestOperationComparator(); - Collections.sort(this.dynamicPathOperationsList, comparator); + this.dynamicPathOperationsList.sort(comparator); } public void addResource(RestOperationMeta swaggerRestOperation) { @@ -59,7 +58,7 @@ public void addResource(RestOperationMeta swaggerRestOperation) { protected void addStaticPathResource(RestOperationMeta operation) { String httpMethod = operation.getHttpMethod(); - String path = operation.getAbsolutePath(); + String path = OperationLocator.getStandardPath(operation.getAbsolutePath()); OperationGroup group = staticPathOperations.get(path); if (group == null) { group = new OperationGroup(); @@ -98,10 +97,9 @@ protected void printPath(Collection operations) { for (RestOperationMeta operation : operations) { SwaggerProducerOperation producerOperation = operation.getOperationMeta().getSwaggerProducerOperation(); - LOGGER.info("Swagger mapped \"{[{}], method=[{}], produces={}}\" onto {}", + LOGGER.debug("Swagger mapped \"{[{}], method=[{}]}\" onto {}", operation.getAbsolutePath(), operation.getHttpMethod(), - operation.getProduces(), producerOperation.getProducerMethod()); } } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/OperationLocator.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/OperationLocator.java index 9a088e70d85..4b94cee9e36 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/OperationLocator.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/OperationLocator.java @@ -21,13 +21,13 @@ import java.util.HashMap; import java.util.Map; -import javax.ws.rs.core.Response.Status; - import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jakarta.ws.rs.core.Response.Status; + /** * 从path和http method定位到具体的operation */ @@ -107,9 +107,9 @@ protected boolean checkHttpMethod(RestOperationMeta operation, String httpMethod return operation.getHttpMethod().equals(httpMethod); } - // TODO: almost always change path, this make performance lower. - // Path: /a/b/c -> /a/b/c/ - static String getStandardPath(String path) { + // Make path standard in order to build path mapping and find path operation. + // NOTE: Path: /a/b/c -> /a/b/c/. Almost change path every time, this make performance lower. + public static String getStandardPath(String path) { if (path.length() > 0 && !path.endsWith(SLASH)) { path += SLASH; } diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/ServicePathManager.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/ServicePathManager.java index 28656da46d3..d59d7019bc9 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/ServicePathManager.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/locator/ServicePathManager.java @@ -19,6 +19,7 @@ import java.util.Collection; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.core.definition.MicroserviceMeta; @@ -26,16 +27,12 @@ import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.foundation.common.utils.ClassLoaderScopeContext; import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; + /** * 对静态路径和动态路径的operation进行预先处理,加速operation的查询定位 */ public class ServicePathManager { - private static final Logger LOGGER = LoggerFactory.getLogger(ServicePathManager.class); - private static final String REST_PATH_MANAGER = "RestServicePathManager"; protected MicroserviceMeta microserviceMeta; @@ -70,11 +67,6 @@ private void addSchema(SchemaMeta schemaMeta) { operationMeta.putExtData(RestConst.SWAGGER_REST_OPERATION, restOperationMeta); addResource(restOperationMeta); } - - LOGGER.info("add schema to service paths. {}:{}:{}.", - schemaMeta.getAppId(), - schemaMeta.getMicroserviceName(), - schemaMeta.getSchemaId()); } public OperationLocator consumerLocateOperation(String path, String httpMethod) { diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/ClassPathStaticResourceHandler.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/ClassPathStaticResourceHandler.java index 1bc6fa8e429..3884d85a86c 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/ClassPathStaticResourceHandler.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/ClassPathStaticResourceHandler.java @@ -19,7 +19,7 @@ import java.io.IOException; import java.net.URL; -import javax.servlet.http.Part; +import jakarta.servlet.http.Part; import org.apache.servicecomb.foundation.common.part.InputStreamPart; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/StaticResourceHandler.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/StaticResourceHandler.java index e5655321a06..a01813fbd70 100644 --- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/StaticResourceHandler.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/resource/StaticResourceHandler.java @@ -19,9 +19,9 @@ import java.io.IOException; import java.net.URI; -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.Status; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationItem.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/URLMappedConfigurationItem.java similarity index 97% rename from edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationItem.java rename to common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/URLMappedConfigurationItem.java index 2fa38461faa..d884e49e453 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationItem.java +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/URLMappedConfigurationItem.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.edge.core; +package org.apache.servicecomb.common.rest.route; import java.util.regex.Pattern; diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/URLMappedConfigurationLoader.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/URLMappedConfigurationLoader.java new file mode 100644 index 00000000000..5c3df2c3355 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/URLMappedConfigurationLoader.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.common.rest.route; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.ConfigUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; + +public class URLMappedConfigurationLoader { + private static final Logger LOG = LoggerFactory.getLogger(URLMappedConfigurationLoader.class); + + private static final String KEY_MAPPING_PATH = ".path"; + + private static final String KEY_MAPPING_SERVICE_NAME = "%s.%s.microserviceName"; + + private static final String KEY_MAPPING_VERSION_RULE = "%s.%s.versionRule"; + + private static final String KEY_MAPPING_PREFIX_SEGMENT_COUNT = "%s.%s.prefixSegmentCount"; + + public static Map loadConfigurations( + Environment environment, String configPrefix) { + Map configurations = new HashMap<>(); + Set configsItems = ConfigUtil.propertiesWithPrefix((ConfigurableEnvironment) environment, configPrefix); + for (String pathKey : configsItems) { + if (pathKey.endsWith(KEY_MAPPING_PATH)) { + URLMappedConfigurationItem configurationItem = new URLMappedConfigurationItem(); + String pattern = environment.getProperty(pathKey); + if (StringUtils.isEmpty(pattern)) { + continue; + } + configurationItem.setPattern(Pattern.compile(pattern)); + configurationItem.setStringPattern(pattern); + String pathKeyItem = pathKey + .substring(configPrefix.length() + 1, pathKey.length() - KEY_MAPPING_PATH.length()); + configurationItem.setMicroserviceName(environment.getProperty( + String.format(KEY_MAPPING_SERVICE_NAME, configPrefix, pathKeyItem))); + if (StringUtils.isEmpty(configurationItem.getMicroserviceName())) { + continue; + } + configurationItem.setPrefixSegmentCount(environment.getProperty( + String.format(KEY_MAPPING_PREFIX_SEGMENT_COUNT, configPrefix, pathKeyItem), int.class, 0)); + configurationItem.setVersionRule(environment.getProperty( + String.format(KEY_MAPPING_VERSION_RULE, configPrefix, pathKeyItem), "0.0.0+")); + configurations.put(pathKeyItem, configurationItem); + } + } + logConfigurations(configurations); + return configurations; + } + + private static void logConfigurations(Map configurations) { + configurations.forEach((key, item) -> LOG.info("config item: key=" + key + ";pattern=" + item.getStringPattern() + + ";service=" + item.getMicroserviceName() + ";versionRule=" + item.getVersionRule())); + } +} diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/Utils.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/Utils.java new file mode 100644 index 00000000000..0e1f64291c9 --- /dev/null +++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/route/Utils.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.common.rest.route; + +/** + * Commonly used methods in this package. + */ +public final class Utils { + private Utils() { + + } + + /** + * Get the actual path without prefix + * @param path full path + * @param pathIndex the index of / that after prefix + * @return actual path + */ + public static String findActualPath(String path, int pathIndex) { + if (pathIndex <= 0) { + return path; + } + + int fromIndex = 0; + int counter = pathIndex; + char[] chars = path.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (chars[i] == '/') { + if (--counter < 0) { + fromIndex = i; + break; + } + } + } + return fromIndex > 0 ? path.substring(fromIndex) : ""; + } +} diff --git a/foundations/foundation-common/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module b/common/common-rest/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module similarity index 92% rename from foundations/foundation-common/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module rename to common/common-rest/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module index 70251186a5a..65a6c38a587 100644 --- a/foundations/foundation-common/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module +++ b/common/common-rest/src/main/resources/META-INF/services/com.fasterxml.jackson.databind.Module @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.foundation.common.utils.json.PartModule \ No newline at end of file +org.apache.servicecomb.foundation.common.utils.json.PartModule diff --git a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor index 9353b9dce7c..c13dc4dac85 100644 --- a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor +++ b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor @@ -16,4 +16,4 @@ # org.apache.servicecomb.common.rest.codec.produce.ProduceJsonProcessor -org.apache.servicecomb.common.rest.codec.produce.ProduceTextPlainProcessor \ No newline at end of file +org.apache.servicecomb.common.rest.codec.produce.ProduceTextPlainProcessor diff --git a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter deleted file mode 100644 index 6fccbe3e684..00000000000 --- a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.common.rest.filter.inner.ClientRestArgsFilter \ No newline at end of file diff --git a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter deleted file mode 100644 index 8b2ffebbc50..00000000000 --- a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.common.rest.filter.inner.ServerRestArgsFilter \ No newline at end of file diff --git a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener deleted file mode 100644 index 607552cd9af..00000000000 --- a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.common.rest.RestEngineSchemaListener \ No newline at end of file diff --git a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider index cf4b594be98..94be435a96b 100644 --- a/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider +++ b/common/common-rest/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.common.rest.filter.RestFilterProvider \ No newline at end of file +org.apache.servicecomb.common.rest.filter.RestFilterProvider diff --git a/common/common-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/common/common-rest/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..8784e8798e8 --- /dev/null +++ b/common/common-rest/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.servicecomb.common.rest.CommonRestConfiguration diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java index f8159a60e42..50b3e8329d5 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/RestProducerInvocationCreatorTest.java @@ -17,168 +17,187 @@ package org.apache.servicecomb.common.rest; -import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; +import static org.apache.servicecomb.common.rest.RestConst.DECODE_INVOCATION_CONTEXT; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; -import javax.ws.rs.core.HttpHeaders; - import org.apache.servicecomb.common.rest.definition.RestOperationMeta; +import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.apache.servicecomb.core.definition.InvocationRuntimeType; import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import io.vertx.core.json.Json; import io.vertx.ext.web.RoutingContext; -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mocked; -import mockit.Verifications; public class RestProducerInvocationCreatorTest { - @Injectable - RoutingContext routingContext; - @Injectable - MicroserviceMeta microserviceMeta; + final RoutingContext routingContext = Mockito.mock(RoutingContext.class); + + final MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); + + final ServicePathManager servicePathManager = Mockito.mock(ServicePathManager.class); + + final RestOperationMeta restOperationMeta = Mockito.mock(RestOperationMeta.class); + + final Endpoint endpoint = Mockito.mock(Endpoint.class); + + final HttpServletRequestEx requestEx = Mockito.mock(HttpServletRequestEx.class); - @Injectable - ServicePathManager servicePathManager; + final HttpServletResponseEx responseEx = Mockito.mock(HttpServletResponseEx.class); - @Mocked - RestOperationMeta restOperationMeta; + final OperationLocator locator = Mockito.mock(OperationLocator.class); - @Injectable - Endpoint endpoint; + final InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); - @Injectable - HttpServletRequestEx requestEx; + final OperationMeta operationMeta = Mockito.mock(OperationMeta.class); - @Injectable - HttpServletResponseEx responseEx; + final SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); RestProducerInvocationCreator creator; static SCBEngine engine; - @BeforeClass - public static void beforeClass() { - ArchaiusUtils.resetConfig(); - ConfigUtil.installDynamicConfig(); + static Environment environment; - engine = SCBBootstrap.createSCBEngineForTest(); + @BeforeAll + public static void beforeClass() { + environment = Mockito.mock(Environment.class); + engine = SCBBootstrap.createSCBEngineForTest(environment); engine.setStatus(SCBStatus.UP); + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + engine.setEnvironment(environment); } - @AfterClass + @AfterAll public static void afterClass() { engine.destroy(); - ArchaiusUtils.resetConfig(); } - @Before + @BeforeEach public void setUp() { creator = new RestVertxProducerInvocationCreator(routingContext, microserviceMeta, endpoint, requestEx, responseEx); - } - - private void mockGetServicePathManager() { - mockGetServicePathManager(servicePathManager); - } - - private void mockGetServicePathManager(final ServicePathManager servicePathManager) { - new Expectations(ServicePathManager.class) { - { - ServicePathManager.getServicePathManager(microserviceMeta); - result = servicePathManager; - } - }; + creator = Mockito.spy(creator); } @Test public void should_failed_when_not_defined_any_schema() { - mockGetServicePathManager(null); - - InvocationException throwable = (InvocationException) catchThrowable(() -> creator.createAsync().join()); - CommonExceptionData data = (CommonExceptionData) throwable.getErrorData(); + try (MockedStatic mockedStatic = Mockito.mockStatic(ServicePathManager.class)) { + mockedStatic.when(() -> ServicePathManager.getServicePathManager(null)).thenReturn(servicePathManager); - assertThat(throwable.getStatusCode()).isEqualTo(NOT_FOUND.getStatusCode()); - assertThat(Json.encode(data)).isEqualTo("{\"code\":\"SCB.00000002\",\"message\":\"Not Found\"}"); - } + InvocationException throwable = (InvocationException) catchThrowable(() -> creator.createAsync().join()); + CommonExceptionData data = (CommonExceptionData) throwable.getErrorData(); - @Test - public void should_failed_when_accept_is_not_support() { - mockGetServicePathManager(); - new Expectations() { - { - requestEx.getHeader(HttpHeaders.ACCEPT); - result = "test-type"; - - restOperationMeta.ensureFindProduceProcessor(requestEx); - result = null; - } - }; - - InvocationException throwable = (InvocationException) catchThrowable(() -> creator.createAsync().join()); - CommonExceptionData data = (CommonExceptionData) throwable.getErrorData(); - - assertThat(throwable.getStatusCode()).isEqualTo(NOT_ACCEPTABLE.getStatusCode()); - assertThat(Json.encode(data)) - .isEqualTo("{\"code\":\"SCB.00000000\",\"message\":\"Accept test-type is not supported\"}"); + assertThat(throwable.getStatusCode()).isEqualTo(NOT_FOUND.getStatusCode()); + assertThat(Json.encode(data)).isIn("{\"code\":\"SCB.00000002\",\"message\":\"Not Found\"}", + "{\"message\":\"Not Found\",\"code\":\"SCB.00000002\"}"); + } } @Test public void should_save_requestEx_in_invocation_context() { - mockGetServicePathManager(); - - Invocation invocation = creator.createAsync().join(); - - Object request = invocation.getLocalContext(RestConst.REST_REQUEST); - assertThat(request).isSameAs(requestEx); + try (MockedStatic mockedStatic = Mockito.mockStatic(ServicePathManager.class)) { + mockedStatic.when(() -> ServicePathManager.getServicePathManager(microserviceMeta)) + .thenReturn(servicePathManager); + Mockito.when(creator.locateOperation(microserviceMeta)).thenReturn(locator); + Mockito.when(locator.getOperation()).thenReturn(restOperationMeta); + Mockito.when(restOperationMeta.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(operationMeta.buildBaseProviderRuntimeType()).thenReturn(invocationRuntimeType); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + + Invocation invocation = creator.createAsync().join(); + + Object request = invocation.getLocalContext(RestConst.REST_REQUEST); + assertThat(request).isSameAs(requestEx); + } } @Test public void should_save_path_var_map_in_requestEx() { - mockGetServicePathManager(); - - creator.createAsync().join(); - - new Verifications() { - { - requestEx.setAttribute(RestConst.PATH_PARAMETERS, any); - times = 1; - } - }; + try (MockedStatic mockedStatic = Mockito.mockStatic(ServicePathManager.class)) { + mockedStatic.when(() -> ServicePathManager.getServicePathManager(microserviceMeta)) + .thenReturn(servicePathManager); + Mockito.when(creator.locateOperation(microserviceMeta)).thenReturn(locator); + Mockito.when(locator.getOperation()).thenReturn(restOperationMeta); + Mockito.when(restOperationMeta.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(operationMeta.buildBaseProviderRuntimeType()).thenReturn(invocationRuntimeType); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + + creator.createAsync().join(); + + Mockito.verify(requestEx, Mockito.times(1)).setAttribute(Mockito.eq(RestConst.PATH_PARAMETERS), Mockito.any()); + } } @Test public void should_merge_invocation_context_from_request() { - mockGetServicePathManager(); - new Expectations() { - { - requestEx.getHeader(Const.CSE_CONTEXT); - result = "{\"k\":\"v\"}"; - } - }; - - Invocation invocation = creator.createAsync().join(); + Mockito.when(environment.getProperty(DECODE_INVOCATION_CONTEXT, boolean.class, true)) + .thenReturn(true); + try (MockedStatic mockedStatic = Mockito.mockStatic(ServicePathManager.class)) { + mockedStatic.when(() -> ServicePathManager.getServicePathManager(microserviceMeta)) + .thenReturn(servicePathManager); + Mockito.when(creator.locateOperation(microserviceMeta)).thenReturn(locator); + Mockito.when(locator.getOperation()).thenReturn(restOperationMeta); + Mockito.when(restOperationMeta.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(operationMeta.buildBaseProviderRuntimeType()).thenReturn(invocationRuntimeType); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + Mockito.when(requestEx.getHeader(CoreConst.CSE_CONTEXT)).thenReturn("{\"k\":\"v\"}"); + + Invocation invocation = creator.createAsync().join(); + + assertThat(invocation.getContext("k")).isEqualTo("v"); + } + } - assertThat(invocation.getContext("k")).isEqualTo("v"); + @Test + public void should_not_merge_invocation_context_from_request() { + Mockito.when(environment.getProperty(DECODE_INVOCATION_CONTEXT, boolean.class, true)) + .thenReturn(false); + try (MockedStatic mockedStatic = Mockito.mockStatic(ServicePathManager.class)) { + mockedStatic.when(() -> ServicePathManager.getServicePathManager(microserviceMeta)) + .thenReturn(servicePathManager); + Mockito.when(creator.locateOperation(microserviceMeta)).thenReturn(locator); + Mockito.when(locator.getOperation()).thenReturn(restOperationMeta); + Mockito.when(restOperationMeta.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(operationMeta.buildBaseProviderRuntimeType()).thenReturn(invocationRuntimeType); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + Mockito.when(requestEx.getHeader(CoreConst.CSE_CONTEXT)).thenReturn("{\"k\":\"v\"}"); + + Invocation invocation = creator.createAsync().join(); + + assertThat(invocation.getContext("k")).isNull(); + } } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java deleted file mode 100644 index 0cb92a87e2c..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestAbstractRestInvocation.java +++ /dev/null @@ -1,1163 +0,0 @@ -/* - * 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.common.rest; - -import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; -import static com.google.common.net.HttpHeaders.TRANSFER_ENCODING; -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; - -import javax.servlet.AsyncContext; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; -import org.apache.servicecomb.common.rest.definition.RestMetaUtils; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.common.rest.filter.HttpServerFilterBaseForTest; -import org.apache.servicecomb.common.rest.locator.OperationLocator; -import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.common.rest.locator.TestPathSchema; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.core.event.InvocationFinishEvent; -import org.apache.servicecomb.core.event.InvocationStartEvent; -import org.apache.servicecomb.core.executor.ReactiveExecutor; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; -import org.apache.servicecomb.foundation.vertx.http.AbstractHttpServletRequest; -import org.apache.servicecomb.foundation.vertx.http.AbstractHttpServletResponse; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.foundation.vertx.http.StandardHttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.context.HttpStatus; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.google.common.eventbus.Subscribe; - -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestAbstractRestInvocation { - @Mocked - HttpServletRequestEx requestEx; - - @Mocked - HttpServletResponse servletResponse; - - HttpServletResponseEx responseEx; - - @Mocked - ReferenceConfig endpoint; - - @Mocked - Map arguments; - - Invocation invocation; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - static SCBEngine scbEngine; - - static OperationMeta operationMeta; - - static RestOperationMeta restOperation; - - class AbstractHttpServletRequestForTest extends AbstractHttpServletRequest { - @Override - public String getHeader(String name) { - return null; - } - } - - class AbstractRestInvocationForTest extends AbstractRestInvocation { - @Override - protected OperationLocator locateOperation(ServicePathManager servicePathManager) { - return null; - } - - @Override - protected void createInvocation() { - this.invocation = TestAbstractRestInvocation.this.invocation; - } - } - - AbstractRestInvocation restInvocation = new AbstractRestInvocationForTest(); - - static long nanoTime = 123; - - @Before - public void setup() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest() - .addProducerMeta("sid1", new TestPathSchema()) - .run(); - operationMeta = scbEngine.getProducerMicroserviceMeta().operationMetas().get("test.sid1.dynamicId"); - restOperation = RestMetaUtils.getRestOperationMeta(operationMeta); - - new MockUp() { - @Mock - long nanoTime() { - return nanoTime; - } - }; - - if (responseEx == null) { - responseEx = new StandardHttpServletResponseEx(servletResponse); - } - - invocation = new Invocation(endpoint, operationMeta, operationMeta.buildBaseConsumerRuntimeType(), arguments); - - initRestInvocation(); - List httpServerFilters = SPIServiceUtils.getSortedService(HttpServerFilter.class); - restInvocation.setHttpServerFilters(httpServerFilters); - } - - @After - public void teardown() { - ArchaiusUtils.resetConfig(); - scbEngine.destroy(); - } - - private void initRestInvocation() { - restInvocation.produceProcessor = ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(); - restInvocation.requestEx = requestEx; - restInvocation.responseEx = responseEx; - restInvocation.invocation = invocation; - restInvocation.restOperationMeta = restOperation; - } - - @Test - public void setHttpServerFilters(@Mocked List httpServerFilters) { - restInvocation.setHttpServerFilters(httpServerFilters); - - Assert.assertSame(httpServerFilters, restInvocation.httpServerFilters); - } - - @Test - public void initProduceProcessorNull() { - new Expectations() { - { - requestEx.getHeader(HttpHeaders.ACCEPT); - result = "notExistType"; - } - }; - restInvocation = new AbstractRestInvocationForTest() { - @Override - public void sendFailResponse(Throwable throwable) { - } - }; - initRestInvocation(); - - expectedException.expect(InvocationException.class); - expectedException - .expectMessage( - "InvocationException: code=406;msg=CommonExceptionData [message=Accept notExistType is not supported]"); - - restInvocation.initProduceProcessor(); - } - - @Test - public void initProduceProcessorNormal() { - new Expectations() { - { - requestEx.getHeader(HttpHeaders.ACCEPT); - result = MediaType.APPLICATION_JSON; - } - }; - // not throw exception - restInvocation.initProduceProcessor(); - } - - @Test - public void setContextNull() throws Exception { - new Expectations() { - { - requestEx.getHeader(Const.CSE_CONTEXT); - result = null; - } - }; - - Map context = invocation.getContext(); - restInvocation.setContext(); - Assert.assertSame(context, invocation.getContext()); - } - - @Test - public void setContextEmpty() throws Exception { - new Expectations() { - { - requestEx.getHeader(Const.CSE_CONTEXT); - result = ""; - } - }; - - Map context = invocation.getContext(); - restInvocation.setContext(); - Assert.assertSame(context, invocation.getContext()); - } - - @Test - public void setContextNormal() throws Exception { - Map context = new HashMap<>(); - context.put("name", "value"); - new Expectations() { - { - requestEx.getHeader(Const.CSE_CONTEXT); - result = JsonUtils.writeValueAsString(context); - } - }; - - restInvocation.setContext(); - Assert.assertThat(invocation.getContext().size(), Matchers.is(1)); - Assert.assertThat(invocation.getContext(), Matchers.hasEntry("name", "value")); - } - - @Test - public void setContextTraceId() throws Exception { - Map context = new HashMap<>(); - new Expectations() { - { - requestEx.getHeader(Const.CSE_CONTEXT); - result = JsonUtils.writeValueAsString(context); - } - }; - invocation.addContext("X-B3-traceId", "value1"); - //if request has no traceId, use invocation's traceId - restInvocation.setContext(); - Assert.assertThat(invocation.getContext().size(), Matchers.is(1)); - Assert.assertThat(invocation.getContext(), Matchers.hasEntry("X-B3-traceId", "value1")); - - context.put("X-B3-traceId", "value2"); - new Expectations() { - { - requestEx.getHeader(Const.CSE_CONTEXT); - result = JsonUtils.writeValueAsString(context); - } - }; - //if request has traceId, use request's traceId - restInvocation.setContext(); - Assert.assertThat(invocation.getContext().size(), Matchers.is(1)); - Assert.assertThat(invocation.getContext(), Matchers.hasEntry("X-B3-traceId", "value2")); - } - - @Test - public void getContext() { - invocation.addContext("key", "test"); - assertEquals("test", restInvocation.getContext("key")); - } - - @Test - public void getContextNull() { - Assert.assertNull(restInvocation.getContext("key")); - } - - @Test - public void invokeFilterHaveResponse(@Mocked HttpServerFilter filter) { - Response response = Response.ok(""); - new Expectations() { - { - filter.enabled(); - result = true; - filter.afterReceiveRequest(invocation, requestEx); - result = response; - } - }; - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - result.value = Response.ok("not run to here"); - } - - @Override - protected void sendResponseQuietly(Response response) { - result.value = response; - } - }; - initRestInvocation(); - restInvocation.httpServerFilters = Arrays.asList(filter); - - restInvocation.invoke(); - - Assert.assertSame(response, result.value); - } - - @Test - public void invokeFilterNoResponse(@Mocked HttpServerFilter filter) { - new Expectations() { - { - filter.enabled(); - result = true; - filter.afterReceiveRequest(invocation, requestEx); - result = null; - } - }; - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - result.value = true; - } - }; - initRestInvocation(); - restInvocation.httpServerFilters = Arrays.asList(filter); - - restInvocation.invoke(); - - Assert.assertTrue(result.value); - } - - @Test - public void invokeFilterNoResponseDisableFilter(@Mocked HttpServerFilter filter) { - new Expectations() { - { - filter.enabled(); - result = false; - } - }; - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - result.value = true; - } - }; - initRestInvocation(); - restInvocation.httpServerFilters = Arrays.asList(filter); - - restInvocation.invoke(); - - Assert.assertTrue(result.value); - } - - @Test - public void invokeFilterException(@Mocked HttpServerFilter filter) { - Exception error = new RuntimeExceptionWithoutStackTrace(); - new Expectations() { - { - filter.enabled(); - result = true; - filter.afterReceiveRequest(invocation, requestEx); - result = error; - } - }; - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - public void sendFailResponse(Throwable throwable) { - result.value = throwable; - } - - @Override - protected void doInvoke() { - - } - }; - initRestInvocation(); - restInvocation.httpServerFilters = Arrays.asList(filter); - - restInvocation.invoke(); - - Assert.assertSame(error, result.value); - } - - @Test - public void invokeNormal(@Mocked HttpServerFilter filter) { - new Expectations() { - { - filter.enabled(); - result = true; - filter.afterReceiveRequest(invocation, requestEx); - result = null; - } - }; - - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - } - - @Override - public void sendFailResponse(Throwable throwable) { - Assert.fail("must not fail"); - } - }; - initRestInvocation(); - restInvocation.httpServerFilters = Arrays.asList(filter); - - restInvocation.invoke(); - - assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartServerFiltersRequest()); - } - - @Test - public void sendFailResponseNoProduceProcessor() { - invocation.onStart(0); - - restInvocation.produceProcessor = null; - restInvocation.sendFailResponse(new RuntimeExceptionWithoutStackTrace()); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(), - restInvocation.produceProcessor); - } - - @Test - public void sendFailResponseHaveProduceProcessor() { - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - } - - @Override - protected void sendResponseQuietly(Response response) { - result.value = response; - } - }; - initRestInvocation(); - restInvocation.produceProcessor = ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(); - - Throwable e = new InvocationException(Status.BAD_GATEWAY, ""); - restInvocation.sendFailResponse(e); - Assert.assertSame(e, result.value.getResult()); - Assert.assertSame( - ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(), restInvocation.produceProcessor); - } - - public static class SendResponseQuietlyNormalEventHandler { - private Holder eventHolder; - - public SendResponseQuietlyNormalEventHandler(Holder eventHolder) { - this.eventHolder = eventHolder; - } - - @Subscribe - public void onFinished(InvocationFinishEvent event) { - eventHolder.value = event; - } - } - - @Test - public void sendResponseQuietlyNormal(@Mocked Response response) { - Holder eventHolder = new Holder<>(); - SendResponseQuietlyNormalEventHandler subscriber = new SendResponseQuietlyNormalEventHandler(eventHolder); - EventManager.register(subscriber); - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - } - - @Override - protected void sendResponse(Response response) { - result.value = response; - super.sendResponse(response); - } - }; - invocation.onStart(0); - initRestInvocation(); - - restInvocation.sendResponseQuietly(response); - - EventManager.unregister(subscriber); - - Assert.assertSame(invocation, eventHolder.value.getInvocation()); - Assert.assertSame(response, result.value); - } - - @Test - public void sendResponseQuietlyException(@Mocked Response response) { - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - } - - @Override - protected void sendResponse(Response response) { - throw new RuntimeExceptionWithoutStackTrace(); - } - }; - initRestInvocation(); - - restInvocation.sendResponseQuietly(response); - - // just log, check nothing - } - - @Test - public void sendResponseQuietlyExceptionOnNullInvocation(@Mocked Response response) { - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void doInvoke() { - } - - @Override - protected void sendResponse(Response response) { - throw new RuntimeExceptionWithoutStackTrace(""); - } - }; - initRestInvocation(); - restInvocation.invocation = null; - - restInvocation.sendResponseQuietly(response); - - // just log, check nothing, and should not throw NPE - } - - @Test - public void executeHttpServerFiltersNullInvocation(@Mocked Response response) { - Holder flag = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void onExecuteHttpServerFiltersFinish(Response response, Throwable e) { - super.onExecuteHttpServerFiltersFinish(response, e); - flag.value = true; - } - }; - initRestInvocation(); - restInvocation.invocation = null; - - restInvocation.executeHttpServerFilters(response); - - Assert.assertTrue(flag.value); - } - - @Test - public void sendResponseStatusAndContentTypeAndHeader(@Mocked Response response) { - new Expectations() { - { - response.getStatusCode(); - result = 123; - response.getReasonPhrase(); - result = "reason"; - response.getResult(); - result = "result"; - } - }; - - Map result = new HashMap<>(); - responseEx = new MockUp() { - private Map attributes = new HashMap<>(); - - @Mock - public void setAttribute(String key, Object value) { - this.attributes.put(key, value); - } - - @Mock - public Object getAttribute(String key) { - return this.attributes.get(key); - } - - @Mock - void setStatus(int sc, String sm) { - result.put("statusCode", sc); - result.put("reasonPhrase", sm); - } - - @Mock - void setContentType(String type) { - result.put("contentType", type); - } - }.getMockInstance(); - - Map expected = new HashMap<>(); - expected.put("statusCode", 123); - expected.put("reasonPhrase", "reason"); - expected.put("contentType", "application/json; charset=utf-8"); - - invocation.onStart(0); - initRestInvocation(); - - restInvocation.sendResponse(response); - assertEquals(expected, result); - } - - @Test - public void should_ignore_content_length_and_transfer_encoding_when_copy_header_to_http_response( - @Mocked Response response) { - MultiMap headers = MultiMap.caseInsensitiveMultiMap() - .set(CONTENT_LENGTH, "10") - .set(TRANSFER_ENCODING, "encoding"); - - new Expectations() { - { - response.getResult(); - result = new RuntimeExceptionWithoutStackTrace("stop"); - response.getHeaders(); - result = headers; - } - }; - - MultiMap resultHeaders = MultiMap.caseInsensitiveMultiMap(); - responseEx = new MockUp() { - private Map attributes = new HashMap<>(); - - @Mock - public void setAttribute(String key, Object value) { - this.attributes.put(key, value); - } - - @Mock - public Object getAttribute(String key) { - return this.attributes.get(key); - } - - @Mock - void addHeader(String name, String value) { - resultHeaders.add(name, value); - } - }.getMockInstance(); - - invocation.onStart(0); - initRestInvocation(); - - restInvocation.sendResponse(response); - assertThat(headers).isEmpty(); - assertThat(resultHeaders).isEmpty(); - } - - @Test - public void testDoSendResponseHeaderNormal(@Mocked Response response) { - MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - headers.add("h1", "h1v1"); - headers.add("h1", "h1v2"); - headers.add("h2", "h2v"); - - new Expectations() { - { - response.getResult(); - result = new RuntimeExceptionWithoutStackTrace("stop"); - response.getHeaders(); - result = headers; - } - }; - - MultiMap resultHeaders = MultiMap.caseInsensitiveMultiMap(); - responseEx = new MockUp() { - private Map attributes = new HashMap<>(); - - @Mock - public void setAttribute(String key, Object value) { - this.attributes.put(key, value); - } - - @Mock - public Object getAttribute(String key) { - return this.attributes.get(key); - } - - @Mock - void addHeader(String name, String value) { - resultHeaders.add(name, value); - } - }.getMockInstance(); - - invocation.onStart(0); - initRestInvocation(); - - try { - restInvocation.sendResponse(response); - Assert.fail("must throw exception"); - } catch (Error e) { - assertEquals(headers.toString(), resultHeaders.toString()); - } - } - - @Test - public void testDoSendResponseResultOK(@Mocked Response response) { - new Expectations() { - { - response.getResult(); - result = "ok"; - } - }; - - Buffer buffer = Buffer.buffer(); - responseEx = new MockUp() { - private Map attributes = new HashMap<>(); - - @Mock - public void setAttribute(String key, Object value) { - this.attributes.put(key, value); - } - - @Mock - public Object getAttribute(String key) { - return this.attributes.get(key); - } - - @Mock - void setBodyBuffer(Buffer bodyBuffer) { - buffer.appendBuffer(bodyBuffer); - } - }.getMockInstance(); - - invocation.onStart(0); - initRestInvocation(); - - restInvocation.sendResponse(response); - assertEquals("\"ok\"", buffer.toString()); - assertEquals(nanoTime, invocation.getInvocationStageTrace().getFinishServerFiltersResponse()); - } - - @Test - public void testDoSendResponseResultOKFilter(@Mocked Response response) { - MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - headers.set("Content-Type", "application/json"); - new Expectations() { - { - response.getHeaders(); - result = headers; - response.getStatusCode(); - result = 123; - response.getReasonPhrase(); - result = "reason"; - response.getResult(); - result = "ok"; - } - }; - - Buffer buffer = Buffer.buffer(); - responseEx = new MockUp() { - private Map attributes = new HashMap<>(); - - @Mock - public void setAttribute(String key, Object value) { - this.attributes.put(key, value); - } - - @Mock - public Object getAttribute(String key) { - return this.attributes.get(key); - } - - @Mock - void setBodyBuffer(Buffer bodyBuffer) { - buffer.appendBuffer(bodyBuffer); - } - }.getMockInstance(); - - HttpServerFilter filter = new HttpServerFilterBaseForTest() { - @Override - public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) { - buffer.appendString("-filter"); - } - }; - - invocation.onStart(0); - initRestInvocation(); - List httpServerFilters = SPIServiceUtils.loadSortedService(HttpServerFilter.class); - httpServerFilters.add(filter); - restInvocation.setHttpServerFilters(httpServerFilters); - - restInvocation.sendResponse(response); - assertEquals("\"ok\"-filter", buffer.toString()); - } - - @Test - public void findRestOperationServicePathManagerNull(@Mocked MicroserviceMeta microserviceMeta) { - new Expectations(ServicePathManager.class) { - { - requestEx.getHeader(Const.TARGET_MICROSERVICE); - result = "ms"; - ServicePathManager.getServicePathManager(microserviceMeta); - result = null; - } - }; - - expectedException.expect(InvocationException.class); - expectedException.expectMessage("CommonExceptionData [message=Not Found]"); - restInvocation.findRestOperation(microserviceMeta); - } - - @Test - public void findRestOperationNormal(@Mocked MicroserviceMeta microserviceMeta, - @Mocked ServicePathManager servicePathManager, @Mocked OperationLocator locator) { - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected OperationLocator locateOperation(ServicePathManager servicePathManager) { - return locator; - } - }; - - requestEx = new AbstractHttpServletRequest() { - }; - restInvocation.requestEx = requestEx; - Map pathVars = new HashMap<>(); - new Expectations(ServicePathManager.class) { - { - ServicePathManager.getServicePathManager(microserviceMeta); - result = servicePathManager; - locator.getPathVarMap(); - result = pathVars; - locator.getOperation(); - result = restOperation; - } - }; - - restInvocation.findRestOperation(microserviceMeta); - Assert.assertSame(restOperation, restInvocation.restOperationMeta); - Assert.assertSame(pathVars, requestEx.getAttribute(RestConst.PATH_PARAMETERS)); - } - - @Test - public void scheduleInvocationException(@Mocked OperationMeta operationMeta) { - Executor executor = new ReactiveExecutor(); - requestEx = new AbstractHttpServletRequestForTest(); - requestEx.setAttribute(RestConst.REST_REQUEST, requestEx); - new Expectations() { - { - restOperation.getOperationMeta(); - result = operationMeta; - operationMeta.getExecutor(); - result = executor; - } - }; - - Holder result = new Holder<>(); - RuntimeException error = new RuntimeExceptionWithoutStackTrace("run on executor"); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void runOnExecutor() { - throw error; - } - - @Override - public void sendFailResponse(Throwable throwable) { - result.value = throwable; - - invocation.onFinish(Response.ok(null)); - } - }; - restInvocation.requestEx = requestEx; - restInvocation.restOperationMeta = restOperation; - - restInvocation.scheduleInvocation(); - - Assert.assertSame(error, result.value); - } - - @Test - public void scheduleInvocationTimeout(@Mocked OperationMeta operationMeta) { - Executor executor = Runnable::run; - - new Expectations() { - { - restOperation.getOperationMeta(); - result = operationMeta; - operationMeta.getExecutor(); - result = executor; - operationMeta.getMicroserviceQualifiedName(); - result = "sayHi"; - } - }; - - requestEx = new AbstractHttpServletRequestForTest(); - - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void runOnExecutor() { - throw new RuntimeExceptionWithoutStackTrace("run on executor"); - } - }; - restInvocation.requestEx = requestEx; - restInvocation.restOperationMeta = restOperation; - - // will not throw exception - restInvocation.scheduleInvocation(); - - invocation.onFinish(Response.ok(null)); - } - - @Test - public void threadPoolReject(@Mocked OperationMeta operationMeta) { - RejectedExecutionException rejectedExecutionException = new RejectedExecutionException("reject"); - Executor executor = (task) -> { - throw rejectedExecutionException; - }; - - new Expectations() { - { - restOperation.getOperationMeta(); - result = operationMeta; - operationMeta.getExecutor(); - result = executor; - } - }; - - Holder holder = new Holder<>(); - requestEx = new AbstractHttpServletRequestForTest(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - public void sendFailResponse(Throwable throwable) { - holder.value = throwable; - - invocation.onFinish(Response.ok(null)); - } - }; - restInvocation.requestEx = requestEx; - restInvocation.restOperationMeta = restOperation; - - restInvocation.scheduleInvocation(); - - Assert.assertSame(rejectedExecutionException, holder.value); - } - - public static class ScheduleInvocationEventHandler { - private Holder eventHolder; - - public ScheduleInvocationEventHandler(Holder eventHolder) { - this.eventHolder = eventHolder; - } - - @Subscribe - public void onFinished(InvocationStartEvent event) { - eventHolder.value = event; - } - } - - @Test - public void scheduleInvocationNormal(@Mocked OperationMeta operationMeta) { - Holder eventHolder = new Holder<>(); - Object subscriber = new ScheduleInvocationEventHandler(eventHolder); - EventManager.register(subscriber); - - Executor executor = new ReactiveExecutor(); - requestEx = new AbstractHttpServletRequestForTest(); - requestEx.setAttribute(RestConst.REST_REQUEST, requestEx); - new Expectations(requestEx) { - { - restOperation.getOperationMeta(); - result = operationMeta; - operationMeta.getExecutor(); - result = executor; - requestEx.getHeader(Const.TRACE_ID_NAME); - result = "tid"; - } - }; - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void runOnExecutor() { - result.value = true; - - invocation.onFinish(Response.ok(null)); - } - }; - restInvocation.requestEx = requestEx; - restInvocation.restOperationMeta = restOperation; - - restInvocation.scheduleInvocation(); - EventManager.unregister(subscriber); - - Assert.assertTrue(result.value); - assertEquals(nanoTime, invocation.getInvocationStageTrace().getStart()); - assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartSchedule()); - Assert.assertSame(invocation, eventHolder.value.getInvocation()); - assertEquals("tid", invocation.getTraceId()); - } - - @Test - public void runOnExecutor() { - long time = 123; - new MockUp() { - @Mock - long nanoTime() { - return time; - } - }; - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - public void invoke() { - result.value = true; - } - }; - restInvocation.createInvocation(); - restInvocation.requestEx = requestEx; - restInvocation.restOperationMeta = restOperation; - - restInvocation.runOnExecutor(); - - Assert.assertTrue(result.value); - Assert.assertSame(invocation, restInvocation.invocation); - assertEquals(time, invocation.getInvocationStageTrace().getStartExecution()); - } - - @Test - public void doInvoke(@Mocked Endpoint endpoint, @Mocked OperationMeta operationMeta, - @Mocked Object[] swaggerArguments, @Mocked SchemaMeta schemaMeta) throws Throwable { - Response response = Response.ok("ok"); - Handler handler = (invocation, asyncResp) -> asyncResp.complete(response); - List handlerChain = Arrays.asList(handler); - Deencapsulation.setField(invocation, "handlerList", handlerChain); - - Holder result = new Holder<>(); - restInvocation = new AbstractRestInvocationForTest() { - @Override - protected void sendResponse(Response response) { - result.value = response; - } - }; - restInvocation.invocation = invocation; - - restInvocation.doInvoke(); - - Assert.assertSame(response, result.value); - assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartHandlersRequest()); - assertEquals(nanoTime, invocation.getInvocationStageTrace().getFinishHandlersResponse()); - } - - @Test - public void scheduleInvocation_invocationContextDeserializeError(@Mocked AsyncContext asyncContext) { - requestEx = new AbstractHttpServletRequest() { - @Override - public String getHeader(String name) { - return "{\"x-cse-src-microservice\":'source\"}"; - } - - @Override - public AsyncContext getAsyncContext() { - return asyncContext; - } - }; - Holder status = new Holder<>(); - Holder reasonPhrase = new Holder<>(); - Holder endCount = new Holder<>(0); - responseEx = new AbstractHttpServletResponse() { - @SuppressWarnings("deprecation") - @Override - public void setStatus(int sc, String sm) { - status.value = sc; - reasonPhrase.value = sm; - } - - @Override - public void flushBuffer() { - endCount.value = endCount.value + 1; - } - - @Override - public void setContentType(String type) { - assertEquals("application/json; charset=utf-8", type); - } - }; - restInvocation.requestEx = requestEx; - restInvocation.responseEx = responseEx; - - restInvocation.scheduleInvocation(); - - assertEquals(Integer.valueOf(590), status.value); - assertEquals("Unexpected producer error, please check logs for details", reasonPhrase.value); - assertEquals(Integer.valueOf(1), endCount.value); - } - - @SuppressWarnings("deprecation") - @Test - public void scheduleInvocation_flowControlReject() { - new Expectations(operationMeta) { - { - operationMeta.getProviderQpsFlowControlHandler(); - result = (Handler) (invocation, asyncResp) -> asyncResp.producerFail(new InvocationException( - new HttpStatus(429, "Too Many Requests"), - new CommonExceptionData("rejected by qps flowcontrol"))); - } - }; - Holder status = new Holder<>(); - Holder reasonPhrase = new Holder<>(); - Holder endCount = new Holder<>(0); - Holder responseBody = new Holder<>(); - responseEx = new AbstractHttpServletResponse() { - @SuppressWarnings("deprecation") - @Override - public void setStatus(int sc, String sm) { - status.value = sc; - reasonPhrase.value = sm; - } - - @Override - public void flushBuffer() { - endCount.value = endCount.value + 1; - } - - @Override - public void setContentType(String type) { - assertEquals("application/json; charset=utf-8", type); - } - - @Override - public void setBodyBuffer(Buffer bodyBuffer) { - responseBody.value = bodyBuffer.toString(); - } - }; - initRestInvocation(); - restInvocation.scheduleInvocation(); - - assertEquals(Integer.valueOf(429), status.value); - assertEquals("Too Many Requests", reasonPhrase.value); - assertEquals("{\"message\":\"rejected by qps flowcontrol\"}", responseBody.value); - assertEquals(Integer.valueOf(1), endCount.value); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestDefPath.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestDefPath.java index a288db17c95..e6b1f4bcf76 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestDefPath.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestDefPath.java @@ -18,21 +18,21 @@ package org.apache.servicecomb.common.rest; import org.apache.servicecomb.common.rest.definition.path.PathRegExp; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestDefPath { @Test public void testPathRegExp() throws Exception { PathRegExp oPathRegExp = new PathRegExp("//{test}//"); - Assert.assertEquals(1, oPathRegExp.getGroupCount()); - Assert.assertEquals(0, oPathRegExp.getGroupWithRegExpCount()); + Assertions.assertEquals(1, oPathRegExp.getGroupCount()); + Assertions.assertEquals(0, oPathRegExp.getGroupWithRegExpCount()); PathRegExp oSecondPathRegExp = new PathRegExp("{[^/:]+?}"); - Assert.assertEquals(1, oSecondPathRegExp.getGroupCount()); - Assert.assertEquals(1, oSecondPathRegExp.getGroupWithRegExpCount()); - Assert.assertEquals("test/", PathRegExp.ensureEndWithSlash("test/")); - Assert.assertEquals("test/", PathRegExp.ensureEndWithSlash("test")); - Assert.assertEquals(null, oSecondPathRegExp.match("{test/test}", null)); + Assertions.assertEquals(1, oSecondPathRegExp.getGroupCount()); + Assertions.assertEquals(1, oSecondPathRegExp.getGroupWithRegExpCount()); + Assertions.assertEquals("test/", PathRegExp.ensureEndWithSlash("test/")); + Assertions.assertEquals("test/", PathRegExp.ensureEndWithSlash("test")); + Assertions.assertNull(oSecondPathRegExp.match("{test/test}", null)); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestEngineSchemaListener.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestEngineSchemaListener.java index d1d3e072590..fa619acb725 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestEngineSchemaListener.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestEngineSchemaListener.java @@ -17,86 +17,109 @@ package org.apache.servicecomb.common.rest; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; + +import java.util.ArrayList; +import java.util.List; + import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.common.rest.locator.ServicePathManager; import org.apache.servicecomb.common.rest.locator.TestPathSchema; -import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.core.executor.ExecutorManager; +import org.apache.servicecomb.core.transport.TransportManager; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestRestEngineSchemaListener { static SCBEngine scbEngine; static ServicePathManager spm; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @BeforeClass + @BeforeAll public static void setup() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest() - .addProducerMeta("sid1", new TestPathSchema()) + Environment environment = Mockito.mock(Environment.class); + scbEngine = SCBBootstrap.createSCBEngineForTest(environment); + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + TransportManager transportManager = Mockito.mock(TransportManager.class); + scbEngine.setTransportManager(transportManager); + scbEngine.setExecutorManager(executorManager); + scbEngine.setEnvironment(environment); + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)) + .thenReturn(BootStrapProperties.DEFAULT_APPLICATION); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_NAME); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_ENVIRONMENT)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_ENVIRONMENT); + + List listeners = new ArrayList<>(); + listeners.add(new RestEngineSchemaListener()); + scbEngine.setBootListeners(listeners); + scbEngine.addProducerMeta("sid1", new TestPathSchema()) .run(); spm = ServicePathManager.getServicePathManager(scbEngine.getProducerMicroserviceMeta()); } - @AfterClass + @AfterAll public static void teardown() { scbEngine.destroy(); - ArchaiusUtils.resetConfig(); } @Test public void testLocateNotFound() { - expectedException.expect(InvocationException.class); - expectedException.expectMessage("InvocationException: code=404;msg=CommonExceptionData [message=Not Found]"); - - spm.producerLocateOperation("/notExist", "GET"); + InvocationException exception = Assertions.assertThrows(InvocationException.class, + () -> spm.producerLocateOperation("/notExist", "GET")); + Assertions.assertEquals("InvocationException: code=404;msg=CommonExceptionData [message=Not Found]", + exception.getMessage()); } @Test public void testLocateNotFoundDynamicRemained() { - expectedException.expect(InvocationException.class); - expectedException.expectMessage("InvocationException: code=404;msg=CommonExceptionData [message=Not Found]"); - - spm.producerLocateOperation("/dynamic/1/2", "GET"); + InvocationException exception = Assertions.assertThrows(InvocationException.class, + () -> spm.producerLocateOperation("/dynamic/1/2", "GET")); + Assertions.assertEquals("InvocationException: code=404;msg=CommonExceptionData [message=Not Found]", + exception.getMessage()); } @Test public void testLocateStaticMethodNotAllowed() { - expectedException.expect(InvocationException.class); - expectedException - .expectMessage("InvocationException: code=405;msg=CommonExceptionData [message=Method Not Allowed]"); - - spm.producerLocateOperation("/staticEx", "POST"); + InvocationException exception = Assertions.assertThrows(InvocationException.class, + () -> spm.producerLocateOperation("/staticEx", "POST")); + Assertions.assertEquals("InvocationException: code=405;msg=CommonExceptionData [message=Method Not Allowed]", + exception.getMessage()); } @Test public void testLocateDynamicMethodNotAllowed() { - expectedException.expect(InvocationException.class); - expectedException - .expectMessage("InvocationException: code=405;msg=CommonExceptionData [message=Method Not Allowed]"); - - spm.producerLocateOperation("/dynamic/1", "POST"); + InvocationException exception = Assertions.assertThrows(InvocationException.class, + () -> spm.producerLocateOperation("/dynamic/1", "POST")); + Assertions.assertEquals("InvocationException: code=405;msg=CommonExceptionData [message=Method Not Allowed]", + exception.getMessage()); } @Test public void testLocateStaticFound() { - Assert.assertNotNull(spm.producerLocateOperation("/staticEx", "GET")); + Assertions.assertNotNull(spm.producerLocateOperation("/staticEx", "GET")); } @Test public void testLocateDynamicFound() { OperationLocator locator = spm.producerLocateOperation("/dynamic/1", "GET"); - Assert.assertEquals("1", locator.getPathVarMap().get("id")); + Assertions.assertEquals("1", locator.getPathVarMap().get("id")); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestProducerInvocation.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestProducerInvocation.java deleted file mode 100644 index b0d6eeb23f5..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestRestProducerInvocation.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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.common.rest; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.common.rest.definition.RestMetaUtils; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.common.rest.locator.OperationLocator; -import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.common.rest.locator.TestPathSchema; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.vertx.http.AbstractHttpServletRequest; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestRestProducerInvocation { - @Mocked - Transport transport; - - @Mocked - HttpServletRequestEx requestEx; - - @Mocked - HttpServletResponseEx responseEx; - - RestProducerInvocation restProducerInvocation; - - Throwable throwableOfSendFailResponse; - - boolean scheduleInvocation; - - static List httpServerFilters = SPIServiceUtils.getSortedService(HttpServerFilter.class); - - static SCBEngine scbEngine; - - static OperationMeta operationMeta; - - static RestOperationMeta restOperationMeta; - - static MicroserviceMeta microserviceMeta; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @BeforeClass - public static void classSetup() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest() - .addProducerMeta("sid1", new TestPathSchema()) - .run(); - operationMeta = scbEngine.getProducerMicroserviceMeta().operationMetas().get("test.sid1.dynamicId"); - restOperationMeta = RestMetaUtils.getRestOperationMeta(operationMeta); - microserviceMeta = operationMeta.getMicroserviceMeta(); - } - - @AfterClass - public static void classTeardown() { - scbEngine.destroy(); - ArchaiusUtils.resetConfig(); - } - - private void initRestProducerInvocation() { - restProducerInvocation.transport = transport; - restProducerInvocation.requestEx = requestEx; - restProducerInvocation.responseEx = responseEx; - restProducerInvocation.restOperationMeta = restOperationMeta; - restProducerInvocation.httpServerFilters = httpServerFilters; - } - - @Test - public void invokeSendFail(@Mocked InvocationException expected) { - restProducerInvocation = new MockUp() { - @Mock - void sendFailResponse(Throwable throwable) { - throwableOfSendFailResponse = throwable; - } - - @Mock - void findRestOperation() { - throw expected; - } - - @Mock - void scheduleInvocation() { - throw new IllegalStateException("must not invoke scheduleInvocation"); - } - }.getMockInstance(); - - restProducerInvocation.invoke(transport, requestEx, responseEx, httpServerFilters); - - Assert.assertSame(expected, throwableOfSendFailResponse); - } - - @Test - public void invokeNormal() { - restProducerInvocation = new MockUp() { - @Mock - void findRestOperation() { - restProducerInvocation.restOperationMeta = restOperationMeta; - } - - @Mock - void scheduleInvocation() { - scheduleInvocation = true; - } - }.getMockInstance(); - - requestEx = new AbstractHttpServletRequest() { - }; - restProducerInvocation.invoke(transport, requestEx, responseEx, httpServerFilters); - - Assert.assertTrue(scheduleInvocation); - Assert.assertSame(requestEx, requestEx.getAttribute(RestConst.REST_REQUEST)); - } - - @Test - public void findRestOperationNameFromRegistry() { - Microservice microservice = new Microservice(); - microservice.setServiceName("ms"); - - new Expectations(ServicePathManager.class) { - { - //just make the method throw Exception - ServicePathManager.getServicePathManager(microserviceMeta); - result = null; - } - }; - restProducerInvocation = new RestProducerInvocation(); - initRestProducerInvocation(); - - expectedException.expect(Exception.class); - expectedException.expectMessage("[message=Not Found]"); - restProducerInvocation.findRestOperation(); - } - - @Test - public void findRestOperationNormal(@Mocked ServicePathManager servicePathManager, - @Mocked OperationLocator locator) { - requestEx = new AbstractHttpServletRequest() { - @Override - public String getRequestURI() { - return "/path"; - } - - @Override - public String getMethod() { - return "GET"; - } - - @Override - public String getHeader(String name) { - return "ms"; - } - }; - Map pathVars = new HashMap<>(); - new Expectations(ServicePathManager.class) { - { - ServicePathManager.getServicePathManager(microserviceMeta); - result = servicePathManager; - servicePathManager.producerLocateOperation(anyString, anyString); - result = locator; - locator.getPathVarMap(); - result = pathVars; - locator.getOperation(); - result = restOperationMeta; - } - }; - restProducerInvocation = new RestProducerInvocation(); - initRestProducerInvocation(); - - restProducerInvocation.findRestOperation(); - Assert.assertSame(restOperationMeta, restProducerInvocation.restOperationMeta); - Assert.assertSame(pathVars, requestEx.getAttribute(RestConst.PATH_PARAMETERS)); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestUploadConfig.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestUploadConfig.java deleted file mode 100644 index 00d6f746138..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/TestUploadConfig.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.common.rest; - -import javax.servlet.MultipartConfigElement; - -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestUploadConfig { - @Before - public void setUp() { - ArchaiusUtils.resetConfig(); - } - - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void getMultipartConfig_notSupport() { - UploadConfig uploadConfig = new UploadConfig(); - - Assert.assertNull(uploadConfig.toMultipartConfigElement()); - Assert.assertEquals(-1L, uploadConfig.getMaxFileSize()); - Assert.assertEquals(-1L, uploadConfig.getMaxSize()); - Assert.assertEquals(0, uploadConfig.getFileSizeThreshold()); - } - - @Test - public void getMultipartConfig_default() { - ArchaiusUtils.setProperty(RestConst.UPLOAD_DIR, "upload"); - - UploadConfig uploadConfig = new UploadConfig(); - MultipartConfigElement multipartConfigElement = uploadConfig.toMultipartConfigElement(); - - Assert.assertEquals("upload", uploadConfig.getLocation()); - Assert.assertEquals(-1L, uploadConfig.getMaxFileSize()); - Assert.assertEquals(-1L, uploadConfig.getMaxSize()); - Assert.assertEquals(0, uploadConfig.getFileSizeThreshold()); - - Assert.assertEquals("upload", multipartConfigElement.getLocation()); - Assert.assertEquals(-1L, multipartConfigElement.getMaxFileSize()); - Assert.assertEquals(-1L, multipartConfigElement.getMaxRequestSize()); - Assert.assertEquals(0, multipartConfigElement.getFileSizeThreshold()); - } - - @Test - public void getMultipartConfig_config() { - ArchaiusUtils.setProperty(RestConst.UPLOAD_DIR, "upload"); - ArchaiusUtils.setProperty(RestConst.UPLOAD_MAX_FILE_SIZE, 1); - ArchaiusUtils.setProperty(RestConst.UPLOAD_MAX_SIZE, 2); - ArchaiusUtils.setProperty(RestConst.UPLOAD_FILE_SIZE_THRESHOLD, 3); - - UploadConfig uploadConfig = new UploadConfig(); - MultipartConfigElement multipartConfigElement = uploadConfig.toMultipartConfigElement(); - - Assert.assertEquals("upload", uploadConfig.getLocation()); - Assert.assertEquals(1, uploadConfig.getMaxFileSize()); - Assert.assertEquals(2, uploadConfig.getMaxSize()); - Assert.assertEquals(3, uploadConfig.getFileSizeThreshold()); - - Assert.assertEquals("upload", multipartConfigElement.getLocation()); - Assert.assertEquals(1, multipartConfigElement.getMaxFileSize()); - Assert.assertEquals(2, multipartConfigElement.getMaxRequestSize()); - Assert.assertEquals(3, multipartConfigElement.getFileSizeThreshold()); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/VertxRestInvocationTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/VertxRestInvocationTest.java deleted file mode 100644 index 28ab24b89a2..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/VertxRestInvocationTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.common.rest; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; -import org.junit.Test; -import org.mockito.Mockito; - -import io.vertx.ext.web.RoutingContext; -import mockit.Deencapsulation; -import mockit.Mock; -import mockit.MockUp; - -public class VertxRestInvocationTest { - @Test - public void testCreateInvocation() { - new MockUp() { - /** - * Mock this method to avoid error - */ - @Mock - void createInvocation() { - } - }; - - VertxRestInvocation vertxRestInvocation = new VertxRestInvocation(); - VertxServerRequestToHttpServletRequest requestEx = Mockito.mock(VertxServerRequestToHttpServletRequest.class); - RoutingContext routingContext = Mockito.mock(RoutingContext.class); - Invocation invocation = Mockito.mock(Invocation.class); - - Deencapsulation.setField( - vertxRestInvocation, "requestEx", requestEx); - Deencapsulation.setField( - vertxRestInvocation, "invocation", invocation); - Mockito.when(requestEx.getContext()).thenReturn(routingContext); - - Deencapsulation.invoke(vertxRestInvocation, "createInvocation"); - - Mockito.verify(routingContext, Mockito.times(1)).put(RestConst.REST_INVOCATION_CONTEXT, invocation); - } -} \ No newline at end of file diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java index 529179af9ee..c134cb46558 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestCodec.java @@ -17,163 +17,144 @@ package org.apache.servicecomb.common.rest.codec; -import static org.mockito.Mockito.when; - import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response.Status; - import org.apache.servicecomb.common.rest.codec.param.ParamValueProcessor; -import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.common.rest.definition.RestParam; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import io.swagger.models.parameters.HeaderParameter; -import io.swagger.models.parameters.Parameter; -import mockit.Expectations; -import mockit.Mocked; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.HeaderParameter; +import io.swagger.v3.oas.models.parameters.Parameter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.Response.Status; public class TestRestCodec { private static RestOperationMeta restOperation; - private static Map header = new HashMap<>(); - - private static RestClientRequest clientRequest = new RestClientRequestImpl(null, null, null) { - public void putHeader(String name, String value) { - header.put(name, value); - } - }; - private static List paramList = null; - @BeforeClass + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.header.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + Parameter hp = new HeaderParameter(); hp.setName("header"); - RestParam restParam = new RestParam(hp, int.class); + hp.setSchema(new Schema<>()); + RestParam restParam = new RestParam(null, hp, int.class); restOperation = Mockito.mock(RestOperationMeta.class); - // clientRequest = Mockito.mock(RestClientRequest.class); paramList = new ArrayList<>(); - paramList.add(restParam); - when(restOperation.getParamList()).thenReturn(paramList); - when(restOperation.getParamByName("test")).thenReturn(restParam); + Mockito.when(restOperation.getParamList()).thenReturn(paramList); + Mockito.when(restOperation.getParamByName("test")).thenReturn(restParam); } - @AfterClass + @AfterAll public static void afterClass() { restOperation = null; - clientRequest = null; paramList.clear(); } @Test - public void testArgsToRest() { - try { - Map args = new HashMap<>(); - args.put("header", "abc"); - RestCodec.argsToRest(args, restOperation, clientRequest); - Assert.assertEquals("abc", header.get("header")); - } catch (Exception e) { - e.printStackTrace(); - Assert.assertTrue(false); - } - } - - @Test - public void testRestToArgs(@Mocked HttpServletRequest request, - @Mocked RestOperationMeta restOperation, @Mocked RestParam restParam, - @Mocked ParamValueProcessor processer) throws Exception { + public void testRestToArgs() throws Exception { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + RestOperationMeta restOperation = Mockito.mock(RestOperationMeta.class); + RestParam restParam = Mockito.mock(RestParam.class); + ParamValueProcessor processor = Mockito.mock(ParamValueProcessor.class); List params = new ArrayList<>(); params.add(restParam); String s = "my"; - - new Expectations() { - { - restOperation.getParamList(); - result = params; - restParam.getParamProcessor(); - result = processer; - processer.getValue(request); - result = s; - restParam.getParamName(); - result = "test"; - } - }; + Mockito.when(restOperation.getParamList()).thenReturn(params); + Mockito.when(restParam.getParamProcessor()).thenReturn(processor); + Mockito.when(processor.getValue(request)).thenReturn(s); + Mockito.when(restParam.getParamName()).thenReturn("test"); Map xx = RestCodec.restToArgs(request, restOperation); - Assert.assertEquals(xx.get("test"), s); + Assertions.assertEquals(xx.get("test"), s); } @Test - public void testRestToArgsExcetpion(@Mocked HttpServletRequest request, - @Mocked RestOperationMeta restOperation, @Mocked RestParam restParam, - @Mocked ParamValueProcessor processer) throws Exception { + public void testRestToArgsException() throws Exception { + ParamValueProcessor processor = Mockito.mock(ParamValueProcessor.class); + Mockito.when(processor.getValue(Mockito.any())).thenThrow(new Exception("bad request parame")); + + RestOperationMeta restOperation = Mockito.mock(RestOperationMeta.class); + RestParam restParam = Mockito.mock(RestParam.class); + Mockito.when(restParam.getParamProcessor()).thenReturn(processor); + List params = new ArrayList<>(); params.add(restParam); + Mockito.when(restOperation.getParamList()).thenReturn(params); - new Expectations() { - { - restOperation.getParamList(); - result = params; - restParam.getParamProcessor(); - result = processer; - processer.getValue(request); - result = new Exception("bad request parame"); - } - }; + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + Mockito.when(restOperation.getOperationMeta()).thenReturn(operationMeta); boolean success = false; try { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); RestCodec.restToArgs(request, restOperation); success = true; } catch (InvocationException e) { - Assert.assertEquals(400, e.getStatusCode()); - Assert.assertTrue(((CommonExceptionData) e.getErrorData()).getMessage().contains("Parameter is not valid")); + Assertions.assertEquals(400, e.getStatusCode()); + Assertions.assertTrue(e.getMessage().contains("Parameter is not valid")); } - Assert.assertEquals(success, false); + Assertions.assertFalse(success); } @Test - public void testRestToArgsInstanceExcetpion(@Mocked HttpServletRequest request, - @Mocked RestOperationMeta restOperation, @Mocked RestParam restParam, - @Mocked ParamValueProcessor processer) throws Exception { + public void testRestToArgsInstanceException() throws Exception { + InvocationException exception = new InvocationException(Status.BAD_REQUEST, "Parameter is not valid."); + ParamValueProcessor processor = Mockito.mock(ParamValueProcessor.class); + Mockito.when(processor.getValue(Mockito.any())).thenThrow(exception); + + RestOperationMeta restOperation = Mockito.mock(RestOperationMeta.class); + RestParam restParam = Mockito.mock(RestParam.class); + Mockito.when(restParam.getParamProcessor()).thenReturn(processor); + List params = new ArrayList<>(); params.add(restParam); - InvocationException exception = new InvocationException(Status.BAD_REQUEST, "Parameter is not valid."); + Mockito.when(restOperation.getParamList()).thenReturn(params); - new Expectations() { - { - restOperation.getParamList(); - result = params; - restParam.getParamProcessor(); - result = processer; - processer.getValue(request); - result = exception; - } - }; + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + Mockito.when(restOperation.getOperationMeta()).thenReturn(operationMeta); boolean success = false; try { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); RestCodec.restToArgs(request, restOperation); success = true; } catch (InvocationException e) { - Assert.assertEquals(e.getStatusCode(), Status.BAD_REQUEST.getStatusCode()); + Assertions.assertEquals(e.getStatusCode(), Status.BAD_REQUEST.getStatusCode()); + Assertions.assertTrue(((CommonExceptionData) e.getErrorData()).getMessage() + .contains("Parameter is not valid for operation")); } - Assert.assertEquals(success, false); + Assertions.assertFalse(success); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java index c5a0d2d0754..57da9440e4f 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/TestRestObjectMapper.java @@ -17,15 +17,15 @@ package org.apache.servicecomb.common.rest.codec; -import static org.junit.Assert.assertFalse; - import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.Date; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.exc.StreamConstraintsException; +import com.google.common.base.Strings; import org.apache.servicecomb.foundation.common.utils.RestObjectMapper; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.core.JsonParser.Feature; import com.fasterxml.jackson.databind.DeserializationFeature; @@ -34,36 +34,37 @@ import com.fasterxml.jackson.databind.type.TypeFactory; import io.vertx.core.json.JsonObject; +import org.junit.jupiter.api.Test; public class TestRestObjectMapper { @Test - public void testFormateDate() throws Exception { + public void testFormatDate() throws Exception { RestObjectMapper mapper = new RestObjectMapper(); // must read/write ISO 8061 dates Date date = mapper.readValue("\"2017-07-21T17:32:28Z\"".getBytes(), Date.class); String dateStr = mapper.writeValueAsString(date); - Assert.assertEquals(dateStr, "\"2017-07-21T17:32:28.000+00:00\""); + Assertions.assertEquals(dateStr, "\"2017-07-21T17:32:28.000+00:00\""); date = mapper.readValue("\"2017-07-21T17:32:28.320+0100\"".getBytes(), Date.class); dateStr = mapper.writeValueAsString(date); - Assert.assertEquals(dateStr, "\"2017-07-21T16:32:28.320+00:00\""); // one hour later + Assertions.assertEquals(dateStr, "\"2017-07-21T16:32:28.320+00:00\""); // one hour later } @Test public void testAutoCloseSource() { - assertFalse(RestObjectMapperFactory.getRestObjectMapper().getFactory().isEnabled(Feature.AUTO_CLOSE_SOURCE)); + Assertions.assertFalse(RestObjectMapperFactory.getRestObjectMapper().getFactory().isEnabled(Feature.AUTO_CLOSE_SOURCE)); } @Test public void testDeserializationFeature() { - assertFalse( + Assertions.assertFalse( RestObjectMapperFactory.getRestObjectMapper().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)); } @Test public void testDefaultViewInclusionFeature() { - assertFalse(RestObjectMapperFactory.getRestObjectMapper().isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)); + Assertions.assertFalse(RestObjectMapperFactory.getRestObjectMapper().isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)); } @Test @@ -73,23 +74,37 @@ public void testJsonObjectWork() { obj.put("desc", "b"); PojoModel model = RestObjectMapperFactory.getRestObjectMapper() .convertValue(obj, TypeFactory.defaultInstance().constructType(PojoModel.class)); - Assert.assertEquals("a", model.getName()); - Assert.assertEquals("b", model.getDesc()); + Assertions.assertEquals("a", model.getName()); + Assertions.assertEquals("b", model.getDesc()); RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapper()); model = RestObjectMapperFactory.getRestObjectMapper() .convertValue(obj, TypeFactory.defaultInstance().constructType(PojoModel.class)); - Assert.assertEquals("a", model.getName()); - Assert.assertEquals("b", model.getDesc()); + Assertions.assertEquals("a", model.getName()); + Assertions.assertEquals("b", model.getDesc()); InputStream inputStream = new ByteArrayInputStream(new byte[0]); try { RestObjectMapperFactory.getRestObjectMapper().readValue(inputStream, PojoModel.class); - Assert.fail(); + Assertions.fail(); } catch (MismatchedInputException e) { // right place, nothing to do. } catch (Exception e) { - Assert.fail(); + Assertions.fail(); + } + } + + @Test + public void testReadValue() { + String content = "{\"desc\":" + Strings.repeat("9", 1001) + "}"; + try { + RestObjectMapperFactory.getRestObjectMapper().readValue(content, PojoModel.class); + Assertions.fail(); + } catch (StreamConstraintsException e) { + // right place, nothing to do. + } catch (JsonProcessingException ex) { + Assertions.fail(); } } + } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/fix/TestDoSFix.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/fix/TestDoSFix.java index 3b28c130c45..361a3844d4c 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/fix/TestDoSFix.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/fix/TestDoSFix.java @@ -23,26 +23,25 @@ import org.apache.servicecomb.foundation.common.utils.RestObjectMapper; import org.apache.servicecomb.foundation.test.scaffolding.model.Color; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.core.exc.InputCoercionException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.exc.InvalidFormatException; -import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.google.common.base.Strings; +import org.junit.jupiter.api.Test; public class TestDoSFix { - static ObjectMapper mapper = new RestObjectMapper(); + static final ObjectMapper mapper = new RestObjectMapper(); - static String invalidNum = Strings.repeat("9", 100_0000); + static final String invalidNum = Strings.repeat("9", 1000); - static String invalidStr = "\"" + invalidNum + "\""; + static final String invalidStr = "\"" + invalidNum + "\""; - static String invalidArrNum = "[" + invalidNum + "]"; + static final String invalidArrNum = "[" + invalidNum + "]"; - static String invalidArrStr = "[\"" + invalidNum + "\"]"; + static final String invalidArrStr = "[\"" + invalidNum + "\"]"; public static class Model { public Color color; @@ -80,18 +79,18 @@ void fastFail(Callable callable, Class eCls) { long start = System.currentTimeMillis(); try { Object ret = callable.call(); - Assert.fail("expect failed, but succes to be " + ret); + Assertions.fail("expect failed, but success to be " + ret); } catch (AssertionError e) { throw e; } catch (Throwable e) { if (eCls != e.getClass()) { e.printStackTrace(); } - Assert.assertEquals(eCls, e.getClass()); + Assertions.assertEquals(eCls, e.getClass()); } long time = System.currentTimeMillis() - start; - Assert.assertTrue("did not fix DoS problem, time:" + time, time < 1000); + Assertions.assertTrue(time < 1000, "did not fix DoS problem, time:" + time); } void fastFail(String input, Class cls, Class eCls) { @@ -177,7 +176,7 @@ Object fastSucc(Callable callable) { long start = System.currentTimeMillis(); try { Object ret = callable.call(); - Assert.assertTrue(System.currentTimeMillis() - start < 1000); + Assertions.assertTrue(System.currentTimeMillis() - start < 1000); return ret; } catch (Throwable e) { throw new IllegalStateException(e); @@ -196,24 +195,24 @@ Object fastSucc(InputStream input, Class cls) { } void batFastSucc(Class cls, Object expected) { - Assert.assertEquals(expected, fastSucc(invalidNum, cls)); - Assert.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidNum.getBytes()), cls)); + Assertions.assertEquals(expected, fastSucc(invalidNum, cls)); + Assertions.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidNum.getBytes()), cls)); - Assert.assertEquals(expected, fastSucc(invalidStr, cls)); - Assert.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidStr.getBytes()), cls)); + Assertions.assertEquals(expected, fastSucc(invalidStr, cls)); + Assertions.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidStr.getBytes()), cls)); - Assert.assertEquals(expected, fastSucc(invalidArrNum, cls)); - Assert.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidArrNum.getBytes()), cls)); + Assertions.assertEquals(expected, fastSucc(invalidArrNum, cls)); + Assertions.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidArrNum.getBytes()), cls)); - Assert.assertEquals(expected, fastSucc(invalidArrStr, cls)); - Assert.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidArrStr.getBytes()), cls)); + Assertions.assertEquals(expected, fastSucc(invalidArrStr, cls)); + Assertions.assertEquals(expected, fastSucc(new ByteArrayInputStream(invalidArrStr.getBytes()), cls)); } void checkField(Model model, String fieldName, Object expected) { try { Field field = Model.class.getField(fieldName); Object value = field.get(model); - Assert.assertEquals(expected, value); + Assertions.assertEquals(expected, value); } catch (Throwable e) { throw new IllegalStateException(e); } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java index b0f61d7e137..ab71e3a9e99 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessor.java @@ -17,89 +17,93 @@ package org.apache.servicecomb.common.rest.codec.param; -import static org.junit.Assert.fail; - import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; - -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; +import java.util.Set; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.BodyProcessor; import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.RawJsonBodyProcessor; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.parameters.RequestBody; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; +import io.vertx.core.buffer.impl.BufferImpl; import io.vertx.core.http.impl.headers.HeadersMultiMap; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.MediaType; + public class TestBodyProcessor { - @Mocked - HttpServletRequest request; + Environment environment = Mockito.mock(Environment.class); + + final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); MultiMap headers; - RestClientRequest clientRequest; + final RestClientRequest clientRequest = Mockito.mock(RestClientRequest.class); ParamValueProcessor processor; - ByteBuf inputBodyByteBuf = Unpooled.buffer(); + final Buffer inputBodyByteBuf = Buffer.buffer(); - BufferInputStream inputStream = new BufferInputStream(inputBodyByteBuf); + final BufferInputStream inputStream = new BufferInputStream(inputBodyByteBuf); Buffer outputBodyBuffer; + String value; + private void createProcessor(Class type) { - processor = new BodyProcessor(TypeFactory.defaultInstance().constructType(type), type.equals(String.class), true); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); + OpenAPI openAPI = Mockito.mock(OpenAPI.class); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getSwagger()).thenReturn(openAPI); + RequestBody requestBody = Mockito.mock(RequestBody.class); + Content content = Mockito.mock(Content.class); + Mockito.when(requestBody.getContent()).thenReturn(content); + Mockito.when(requestBody.getRequired()).thenReturn(true); + Set supported = new HashSet<>(); + supported.add(MediaType.APPLICATION_JSON); + supported.add(MediaType.TEXT_PLAIN); + Mockito.when(content.keySet()).thenReturn(supported); + processor = new BodyProcessor(operationMeta, TypeFactory.defaultInstance().constructType(type), requestBody); } private void createRawJsonProcessor() { - processor = new RawJsonBodyProcessor(TypeFactory.defaultInstance().constructType(String.class), true, true); + processor = new RawJsonBodyProcessor(TypeFactory.defaultInstance().constructType(String.class), true); } private void createClientRequest() { - clientRequest = new MockUp() { - @Mock - void putHeader(String name, String value) { - headers.add(name, value); - } - - @Mock - void write(Buffer bodyBuffer) { - outputBodyBuffer = bodyBuffer; - } - - @Mock - MultiMap getHeaders() { - return headers; - } - }.getMockInstance(); + Mockito.doAnswer(invocation -> { + headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); + return null; + }).when(clientRequest).putHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); + + Mockito.when(clientRequest.getHeaders()).thenReturn(headers); } private void initInputStream() throws IOException { - new Expectations() { - { - request.getInputStream(); - result = inputStream; - } - }; + Mockito.when(request.getInputStream()).thenReturn(inputStream); } private void setupGetValue(Class type) throws IOException { @@ -107,76 +111,58 @@ private void setupGetValue(Class type) throws IOException { initInputStream(); } - @Before + @BeforeEach public void before() { - headers = new HeadersMultiMap(); + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + headers = HeadersMultiMap.httpHeaders(); + value = "value"; } @Test public void testGetValueHaveAttr() throws Exception { int body = 10; createProcessor(String.class); - new Expectations() { - { - request.getAttribute(RestConst.BODY_PARAMETER); - result = body; - } - }; + Mockito.when(request.getAttribute(RestConst.BODY_PARAMETER)).thenReturn(body); Object result = processor.getValue(request); - Assert.assertEquals("10", result); + Assertions.assertEquals("10", result); } @Test public void testGetValueNoAttrNoStream() throws Exception { createProcessor(String.class); - new Expectations() { - { - request.getInputStream(); - result = null; - } - }; - - Object result = processor.getValue(request); - Assert.assertNull(result); + Mockito.when(request.getInputStream()).thenReturn(null); + Assertions.assertThrows(InvocationException.class, () -> processor.getValue(request)); } @Test public void testGetValueTextPlain() throws Exception { setupGetValue(String.class); - inputBodyByteBuf.writeCharSequence("abc", StandardCharsets.UTF_8); + inputBodyByteBuf.appendString("abc", StandardCharsets.UTF_8.toString()); - new Expectations() { - { - request.getContentType(); - result = MediaType.TEXT_PLAIN; - } - }; + Mockito.when(request.getContentType()).thenReturn(MediaType.TEXT_PLAIN); - Assert.assertEquals("abc", processor.getValue(request)); + Assertions.assertEquals("abc", processor.getValue(request)); } @Test public void testGetValueContextTypeJson() throws Exception { setupGetValue(Integer.class); - inputBodyByteBuf.writeCharSequence("\"1\"", StandardCharsets.UTF_8); + inputBodyByteBuf.appendString("\"1\"", StandardCharsets.UTF_8.toString()); - new Expectations() { - { - request.getContentType(); - result = MediaType.APPLICATION_JSON; - } - }; + Mockito.when(request.getContentType()).thenReturn(MediaType.APPLICATION_JSON); - Assert.assertEquals(1, processor.getValue(request)); + Assertions.assertEquals(1, processor.getValue(request)); } @Test public void testGetValueDefaultJson() throws Exception { setupGetValue(Integer.class); - inputBodyByteBuf.writeCharSequence("\"1\"", StandardCharsets.UTF_8); + inputBodyByteBuf.appendString("\"1\"", StandardCharsets.UTF_8.toString()); - Assert.assertEquals(1, processor.getValue(request)); + Assertions.assertEquals(1, processor.getValue(request)); } @Test @@ -184,9 +170,17 @@ public void testSetValue() throws Exception { createClientRequest(); createProcessor(String.class); - processor.setValue(clientRequest, "value"); - Assert.assertEquals(MediaType.APPLICATION_JSON, headers.get(HttpHeaders.CONTENT_TYPE)); - Assert.assertEquals("\"value\"", outputBodyBuffer.toString()); + Mockito.when(clientRequest.getHeaders()).thenReturn(headers); + ParamValueProcessor spy = Mockito.spy(processor); + Mockito.doAnswer(invocation -> { + outputBodyBuffer = new BufferImpl().appendBytes((value).getBytes(StandardCharsets.UTF_8)); + return null; + }).when(spy).setValue(clientRequest, value); + + spy.setValue(clientRequest, value); + processor.setValue(clientRequest, value); + Assertions.assertEquals(MediaType.APPLICATION_JSON, headers.get(HttpHeaders.CONTENT_TYPE)); + Assertions.assertEquals(value, outputBodyBuffer.toString()); } @Test @@ -195,74 +189,57 @@ public void testSetValueTextPlain() throws Exception { createProcessor(String.class); headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN); - processor.setValue(clientRequest, "value"); - Assert.assertEquals(MediaType.TEXT_PLAIN, headers.get(HttpHeaders.CONTENT_TYPE)); - Assert.assertEquals("value", outputBodyBuffer.toString()); - } + ParamValueProcessor spy = Mockito.spy(processor); + Mockito.doAnswer(invocation -> { + outputBodyBuffer = new BufferImpl().appendBytes((value).getBytes(StandardCharsets.UTF_8)); + return null; + }).when(spy).setValue(clientRequest, value); - @Test - public void testSetValueTextPlainTypeMismatch() { - createClientRequest(); - createProcessor(String.class); - headers.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN); - - try { - processor.setValue(clientRequest, new Date()); - fail("an exception is expected!"); - } catch (Exception e) { - Assert.assertEquals(IllegalArgumentException.class, e.getClass()); - Assert.assertEquals("Content-Type is text/plain while arg type is not String", e.getMessage()); - } + spy.setValue(clientRequest, value); + processor.setValue(clientRequest, value); + Assertions.assertEquals(MediaType.TEXT_PLAIN, headers.get(HttpHeaders.CONTENT_TYPE)); + Assertions.assertEquals(value, outputBodyBuffer.toString()); } + @Test public void testGetParameterPath() { createProcessor(String.class); - Assert.assertEquals("", processor.getParameterPath()); + Assertions.assertEquals("", processor.getParameterPath()); } @Test public void testGetProcessorType() { createProcessor(String.class); - Assert.assertEquals("body", processor.getProcessorType()); + Assertions.assertEquals("body", processor.getProcessorType()); } @Test public void testGetValueRawJson() throws Exception { createRawJsonProcessor(); initInputStream(); - inputBodyByteBuf.writeCharSequence("\"1\"", StandardCharsets.UTF_8); + inputBodyByteBuf.appendString("\"1\"", StandardCharsets.UTF_8.toString()); - Assert.assertEquals("\"1\"", processor.getValue(request)); + Assertions.assertEquals("\"1\"", processor.getValue(request)); } @Test public void testGetValueRawJsonHaveAttr() throws Exception { int body = 10; createRawJsonProcessor(); - new Expectations() { - { - request.getAttribute(RestConst.BODY_PARAMETER); - result = body; - } - }; + Mockito.when(request.getAttribute(RestConst.BODY_PARAMETER)).thenReturn(body); Object result = processor.getValue(request); - Assert.assertEquals("10", result); + Assertions.assertEquals("10", result); } @Test public void testGetValueRawJsonNoAttrNoStream() throws Exception { createRawJsonProcessor(); - new Expectations() { - { - request.getInputStream(); - result = null; - } - }; + Mockito.when(request.getInputStream()).thenReturn(null); Object result = processor.getValue(request); - Assert.assertNull(result); + Assertions.assertNull(result); } @Test @@ -270,9 +247,15 @@ public void testSetValueRawJson() throws Exception { createClientRequest(); createRawJsonProcessor(); - processor.setValue(clientRequest, "value"); - Assert.assertEquals(MediaType.APPLICATION_JSON, headers.get(HttpHeaders.CONTENT_TYPE)); - Assert.assertEquals("value", outputBodyBuffer.toString()); + ParamValueProcessor spy = Mockito.spy(processor); + Mockito.doAnswer(invocation -> { + outputBodyBuffer = new BufferImpl().appendBytes((value).getBytes(StandardCharsets.UTF_8)); + return null; + }).when(spy).setValue(clientRequest, value); + spy.setValue(clientRequest, value); + processor.setValue(clientRequest, value); + Assertions.assertEquals(MediaType.APPLICATION_JSON, headers.get(HttpHeaders.CONTENT_TYPE)); + Assertions.assertEquals("value", outputBodyBuffer.toString()); } static class BodyModel { @@ -287,18 +270,12 @@ public void convertFromFormData() throws Exception { Map parameterMap = new HashMap<>(); parameterMap.put("name", new String[] {"n"}); parameterMap.put("age", new String[] {"10"}); - new Expectations() { - { - request.getParameterMap(); - result = parameterMap; - request.getContentType(); - result = MediaType.MULTIPART_FORM_DATA + ";utf-8"; - } - }; + Mockito.when(request.getParameterMap()).thenReturn(parameterMap); + Mockito.when(request.getContentType()).thenReturn(MediaType.MULTIPART_FORM_DATA + ";utf-8"); BodyModel bm = (BodyModel) processor.getValue(request); - Assert.assertEquals("n", bm.name); - Assert.assertEquals(10, bm.age); + Assertions.assertEquals("n", bm.name); + Assertions.assertEquals(10, bm.age); } @Test @@ -307,17 +284,11 @@ public void convertFromUrlencoded() throws Exception { Map parameterMap = new HashMap<>(); parameterMap.put("name", new String[] {"n"}); parameterMap.put("age", new String[] {"10"}); - new Expectations() { - { - request.getParameterMap(); - result = parameterMap; - request.getContentType(); - result = MediaType.APPLICATION_FORM_URLENCODED + ";utf-8"; - } - }; + Mockito.when(request.getParameterMap()).thenReturn(parameterMap); + Mockito.when(request.getContentType()).thenReturn(MediaType.APPLICATION_FORM_URLENCODED + ";utf-8"); BodyModel bm = (BodyModel) processor.getValue(request); - Assert.assertEquals("n", bm.name); - Assert.assertEquals(10, bm.age); + Assertions.assertEquals("n", bm.name); + Assertions.assertEquals(10, bm.age); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java index db9d5ded396..22d7e8d39db 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestBodyProcessorCreator.java @@ -17,35 +17,61 @@ package org.apache.servicecomb.common.rest.codec.param; +import java.util.HashMap; + import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.BodyProcessor; import org.apache.servicecomb.common.rest.codec.param.BodyProcessorCreator.RawJsonBodyProcessor; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.swagger.generator.SwaggerConst; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import io.swagger.models.parameters.BodyParameter; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.RequestBody; +@SuppressWarnings({"rawtypes", "unchecked"}) public class TestBodyProcessorCreator { + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach + public void before() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + } + @Test public void testCreateNormal() { ParamValueProcessorCreator creator = - ParamValueProcessorCreatorManager.INSTANCE.findValue(BodyProcessorCreator.PARAMTYPE); - BodyParameter param = new BodyParameter(); + ParamValueProcessorCreatorManager.INSTANCE.findValue(BodyProcessorCreator.PARAM_TYPE); + RequestBody param = new RequestBody(); + param.setContent(new Content()); + param.getContent().addMediaType(SwaggerConst.DEFAULT_MEDIA_TYPE, new MediaType()); + param.getContent().get(SwaggerConst.DEFAULT_MEDIA_TYPE).setSchema(new Schema()); + param.setExtensions(new HashMap<>()); - ParamValueProcessor processor = creator.create(param, String.class); + ParamValueProcessor processor = creator.create(null, null, param, String.class); - Assert.assertEquals(BodyProcessor.class, processor.getClass()); + Assertions.assertEquals(BodyProcessor.class, processor.getClass()); } @Test public void testCreateRawJson() { ParamValueProcessorCreator creator = - ParamValueProcessorCreatorManager.INSTANCE.findValue(BodyProcessorCreator.PARAMTYPE); - BodyParameter param = new BodyParameter(); - param.setVendorExtension(SwaggerConst.EXT_RAW_JSON_TYPE, true); + ParamValueProcessorCreatorManager.INSTANCE.findValue(BodyProcessorCreator.PARAM_TYPE); + RequestBody param = new RequestBody(); + param.setContent(new Content()); + param.getContent().addMediaType(SwaggerConst.DEFAULT_MEDIA_TYPE, new MediaType()); + param.getContent().get(SwaggerConst.DEFAULT_MEDIA_TYPE).setSchema(new Schema()); + param.addExtension(SwaggerConst.EXT_RAW_JSON_TYPE, true); - ParamValueProcessor processor = creator.create(param, String.class); + ParamValueProcessor processor = creator.create(null, null, param, String.class); - Assert.assertEquals(RawJsonBodyProcessor.class, processor.getClass()); + Assertions.assertEquals(RawJsonBodyProcessor.class, processor.getClass()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessor.java index 0fab41c3356..10cad81b4f4 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessor.java @@ -21,29 +21,29 @@ import java.util.HashMap; import java.util.Map; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.common.rest.codec.param.CookieProcessorCreator.CookieProcessor; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.StdDateFormat; - -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestCookieProcessor { - @Mocked - HttpServletRequest request; + final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + + final Map cookies = new HashMap<>(); - Map cookies = new HashMap<>(); + final RestClientRequest clientRequest = Mockito.mock(RestClientRequest.class); - RestClientRequest clientRequest; + final String cookieName = "v1"; + + final String cookieValue = "c1v"; private CookieProcessor createProcessor(String name, Class type) { return new CookieProcessor(name, TypeFactory.defaultInstance().constructType(type), null, true); @@ -54,108 +54,76 @@ private CookieProcessor createProcessor(String name, Class type, String defau } private void createClientRequest() { - clientRequest = new MockUp() { - @Mock - void addCookie(String name, String value) { - cookies.put(name, value); - } - }.getMockInstance(); + Mockito.doAnswer(invocation -> { + cookies.put(cookieName, cookieValue); + return null; + }).when(clientRequest).addCookie(cookieName, cookieValue); } @Test public void testGetValueNoCookies() throws Exception { - new Expectations() { - { - request.getCookies(); - result = null; - } - }; - - CookieProcessor processor = createProcessor("c1", String.class, null, false); + Mockito.when(request.getCookies()).thenReturn(null); + + CookieProcessor processor = createProcessor(cookieName, String.class, null, false); Object value = processor.getValue(request); - Assert.assertNull(value); + Assertions.assertNull(value); } @Test public void testNoCookieAndRequired() throws Exception { - new Expectations() { - { - request.getCookies(); - result = null; - } - }; - - CookieProcessor processor = createProcessor("c1", String.class, null, true); + Mockito.when(request.getCookies()).thenReturn(null); + + CookieProcessor processor = createProcessor(cookieName, String.class, null, true); try { processor.getValue(request); - Assert.assertEquals("required is true, throw exception", "not throw exception"); + Assertions.assertEquals("required is true, throw exception", "not throw exception"); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Parameter is required.")); + Assertions.assertTrue(e.getMessage().contains("Parameter is required.")); } } @Test public void testGetValueCookiesNotFound() throws Exception { - Cookie[] cookies = new Cookie[] {new Cookie("c1", "c1v")}; - new Expectations() { - { - request.getCookies(); - result = cookies; - } - }; + Cookie[] cookies = new Cookie[] {new Cookie(cookieName, cookieValue)}; + Mockito.when(request.getCookies()).thenReturn(cookies); CookieProcessor processor = createProcessor("c2", String.class, null, false); Object value = processor.getValue(request); - Assert.assertNull(value); + Assertions.assertNull(value); } @Test public void testGetValueCookiesFound() throws Exception { - Cookie[] cookies = new Cookie[] {new Cookie("c1", "c1v")}; - new Expectations() { - { - request.getCookies(); - result = cookies; - } - }; - - CookieProcessor processor = createProcessor("c1", String.class); + Cookie[] cookies = new Cookie[] {new Cookie(cookieName, cookieValue)}; + Mockito.when(request.getCookies()).thenReturn(cookies); + + CookieProcessor processor = createProcessor(cookieName, String.class); Object value = processor.getValue(request); - Assert.assertEquals("c1v", value); + Assertions.assertEquals(cookieValue, value); } @Test public void testGetValueRequiredTrue() throws Exception { - Cookie[] cookies = new Cookie[] {new Cookie("c1", null)}; - new Expectations() { - { - request.getCookies(); - result = cookies; - } - }; - - CookieProcessor processor = createProcessor("c1", String.class, null, true); + Cookie[] cookies = new Cookie[] {new Cookie(cookieName, null)}; + Mockito.when(request.getCookies()).thenReturn(cookies); + + CookieProcessor processor = createProcessor(cookieName, String.class, null, true); try { processor.getValue(request); - Assert.assertEquals("required is true, throw exception", "not throw exception"); + Assertions.assertEquals("required is true, throw exception", "not throw exception"); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Parameter is required.")); + Assertions.assertTrue(e.getMessage().contains("Parameter is required.")); } } @Test public void testGetValueRequiredFalse() throws Exception { - Cookie[] cookies = new Cookie[] {new Cookie("c1", null)}; - new Expectations() { - { - request.getCookies(); - result = cookies; - } - }; - - CookieProcessor processor = createProcessor("c1", String.class, "test", false); + Cookie[] cookies = new Cookie[] {new Cookie(cookieName, null)}; + Mockito.when(request.getCookies()).thenReturn(cookies); + + CookieProcessor processor = createProcessor(cookieName, String.class, "test", false); Object result = processor.getValue(request); - Assert.assertEquals("test", result); + Assertions.assertEquals("test", result); } @SuppressWarnings("deprecation") @@ -163,26 +131,21 @@ public void testGetValueRequiredFalse() throws Exception { public void testGetValueCookiesDate() throws Exception { Date date = new Date(); String strDate = com.fasterxml.jackson.databind.util.ISO8601Utils.format(date); - Cookie[] cookies = new Cookie[] {new Cookie("c1", strDate)}; - new Expectations() { - { - request.getCookies(); - result = cookies; - } - }; - - CookieProcessor processor = createProcessor("c1", Date.class); + Cookie[] cookies = new Cookie[] {new Cookie(cookieName, strDate)}; + Mockito.when(request.getCookies()).thenReturn(cookies); + + CookieProcessor processor = createProcessor(cookieName, Date.class); Object value = processor.getValue(request); - Assert.assertEquals(strDate, com.fasterxml.jackson.databind.util.ISO8601Utils.format((Date) value)); + Assertions.assertEquals(strDate, com.fasterxml.jackson.databind.util.ISO8601Utils.format((Date) value)); } @Test public void testSetValue() throws Exception { createClientRequest(); - CookieProcessor processor = createProcessor("c1", String.class); - processor.setValue(clientRequest, "c1v"); - Assert.assertEquals("c1v", cookies.get("c1")); + CookieProcessor processor = createProcessor(cookieName, String.class); + processor.setValue(clientRequest, cookieValue); + Assertions.assertEquals(cookieValue, cookies.get(cookieName)); } @Test @@ -190,11 +153,14 @@ public void testSetValueDateFixed() throws Exception { Date date = new Date(1586957400199L); String strDate = "2020-04-15T13:30:00.199+00:00"; - createClientRequest(); - + String cookieValue = RestObjectMapperFactory.getConsumerWriterMapper().convertToString(date); + Mockito.doAnswer(invocation -> { + cookies.put("h1", cookieValue); + return null; + }).when(clientRequest).addCookie("h1", cookieValue); CookieProcessor processor = createProcessor("h1", Date.class); processor.setValue(clientRequest, date); - Assert.assertEquals(strDate, cookies.get("h1")); + Assertions.assertEquals(strDate, cookies.get("h1")); } @Test @@ -203,16 +169,19 @@ public void testSetValueDate() throws Exception { String strDate = new StdDateFormat().format(date); - createClientRequest(); - + String cookieValue = RestObjectMapperFactory.getConsumerWriterMapper().convertToString(date); + Mockito.doAnswer(invocation -> { + cookies.put("h1", cookieValue); + return null; + }).when(clientRequest).addCookie("h1", cookieValue); CookieProcessor processor = createProcessor("h1", Date.class); processor.setValue(clientRequest, date); - Assert.assertEquals(strDate, cookies.get("h1")); + Assertions.assertEquals(strDate, cookies.get("h1")); } @Test public void testGetProcessorType() { - CookieProcessor processor = createProcessor("c1", String.class); - Assert.assertEquals("cookie", processor.getProcessorType()); + CookieProcessor processor = createProcessor(cookieName, String.class); + Assertions.assertEquals("cookie", processor.getProcessorType()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java index 1d23d900999..d3769dcb2c5 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestCookieProcessorCreator.java @@ -18,21 +18,33 @@ package org.apache.servicecomb.common.rest.codec.param; import org.apache.servicecomb.common.rest.codec.param.CookieProcessorCreator.CookieProcessor; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import io.swagger.models.parameters.CookieParameter; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.CookieParameter; public class TestCookieProcessorCreator { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + } + @Test public void testCreate() { ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.findValue(CookieProcessorCreator.PARAMTYPE); CookieParameter p = new CookieParameter(); p.setName("p1"); + p.setSchema(new Schema()); + ParamValueProcessor processor = creator.create(null, p.getName(), p, String.class); - ParamValueProcessor processor = creator.create(p, String.class); - - Assert.assertEquals(CookieProcessor.class, processor.getClass()); + Assertions.assertEquals(CookieProcessor.class, processor.getClass()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessor.java index 6711e3fd209..42aa5343bef 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessor.java @@ -24,32 +24,32 @@ import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.RestClientRequest; import org.apache.servicecomb.common.rest.codec.param.FormProcessorCreator.FormProcessor; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.FormParameter; -import io.swagger.models.properties.ArrayProperty; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MapSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.RequestBody; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.core.MediaType; public class TestFormProcessor { - @Mocked - HttpServletRequest request; + final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Map forms = new HashMap<>(); + final Map forms = new HashMap<>(); - RestClientRequest clientRequest; + final RestClientRequest clientRequest = Mockito.mock(RestClientRequest.class); private FormProcessor createProcessor(String name, Type type) { return createProcessor(name, type, null, true); @@ -58,54 +58,48 @@ private FormProcessor createProcessor(String name, Type type) { private FormProcessor createProcessor(String name, Type type, String defaultValue, boolean required) { JavaType javaType = TypeFactory.defaultInstance().constructType(type); - FormParameter formParameter = new FormParameter(); - formParameter.name(name) - .required(required) - .setDefaultValue(defaultValue); + RequestBody formParameter = new RequestBody(); + Content content = new Content(); + MapSchema schema = new MapSchema(); + io.swagger.v3.oas.models.media.MediaType mediaType = new io.swagger.v3.oas.models.media.MediaType(); if (javaType.isContainerType()) { - formParameter.type(ArrayProperty.TYPE); + Schema propertySchema = new ArraySchema(); + schema.addProperty(name, propertySchema); + mediaType.schema(schema); + } else { + Schema propertySchema = new Schema(); + propertySchema.setDefault(defaultValue); + schema.addProperty(name, propertySchema); + mediaType.schema(schema); } - return new FormProcessor(formParameter, javaType); - } - private void createClientRequest() { - clientRequest = new MockUp() { - @Mock - void addForm(String name, Object value) { - forms.put(name, value); - } - }.getMockInstance(); + content.addMediaType(MediaType.APPLICATION_FORM_URLENCODED, + mediaType); + formParameter.content(content) + .required(required); + + return new FormProcessor(name, formParameter, MediaType.APPLICATION_FORM_URLENCODED, javaType); } @Test public void testGetValueWithAttr() throws Exception { Map forms = new HashMap<>(); forms.put("name", "value"); - new Expectations() { - { - request.getAttribute(RestConst.FORM_PARAMETERS); - result = forms; - } - }; + Mockito.when(request.getAttribute(RestConst.BODY_PARAMETER)).thenReturn(forms); ParamValueProcessor processor = createProcessor("name", String.class); Object value = processor.getValue(request); - Assert.assertEquals("value", value); + Assertions.assertEquals("value", value); } @Test public void testGetValueNormal() throws Exception { - new Expectations() { - { - request.getParameter("name"); - result = "value"; - } - }; + Mockito.when(request.getParameter("name")).thenReturn("value"); ParamValueProcessor processor = createProcessor("name", String.class); Object value = processor.getValue(request); - Assert.assertEquals("value", value); + Assertions.assertEquals("value", value); } @SuppressWarnings("deprecation") @@ -113,121 +107,96 @@ public void testGetValueNormal() throws Exception { public void testGetValueNormalDate() throws Exception { Date date = new Date(); String strDate = com.fasterxml.jackson.databind.util.ISO8601Utils.format(date); - new Expectations() { - { - request.getParameter("name"); - result = strDate; - } - }; + Mockito.when(request.getParameter("name")).thenReturn(strDate); ParamValueProcessor processor = createProcessor("name", Date.class); Object value = processor.getValue(request); - Assert.assertEquals(strDate, com.fasterxml.jackson.databind.util.ISO8601Utils.format((Date) value)); + Assertions.assertEquals(strDate, com.fasterxml.jackson.databind.util.ISO8601Utils.format((Date) value)); } @Test public void testGetValueContainerTypeNull() throws Exception { - new Expectations() { - { - request.getParameterValues("name"); - result = null; - } - }; + Mockito.when(request.getParameterValues("name")).thenReturn(null); ParamValueProcessor processor = createProcessor("name", String[].class, null, false); String[] value = (String[]) processor.getValue(request); - Assert.assertNull(value); + Assertions.assertNull(value); } @Test public void testGetValueNull() throws Exception { - new Expectations() { - { - request.getParameter("name"); - result = null; - } - }; + Mockito.when(request.getParameter("name")).thenReturn(null); ParamValueProcessor processor = createProcessor("name", String.class, null, true); try { processor.getValue(request); - Assert.assertEquals("required is true, throw exception", "not throw exception"); + Assertions.assertEquals("required is true, throw exception", "not throw exception"); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Parameter is required.")); + Assertions.assertTrue(e.getMessage().contains("Parameter is required.")); } } @Test public void testGetValueArray() throws Exception { - new Expectations() { - { - request.getParameterValues("name"); - result = new String[] {"value"}; - } - }; + Mockito.when(request.getParameterValues("name")).thenReturn(new String[] {"value"}); ParamValueProcessor processor = createProcessor("name", String[].class); String[] value = (String[]) processor.getValue(request); - Assert.assertThat(value, Matchers.arrayContaining("value")); + MatcherAssert.assertThat(value, Matchers.arrayContaining("value")); } @SuppressWarnings("unchecked") @Test public void testGetValueList() throws Exception { - new Expectations() { - { - request.getParameterValues("name"); - result = new String[] {"value"}; - } - }; + Mockito.when(request.getParameterValues("name")).thenReturn(new String[] {"value"}); ParamValueProcessor processor = createProcessor("name", TypeFactory.defaultInstance().constructCollectionType(List.class, String.class), null, true); Object value = processor.getValue(request); - Assert.assertThat((List) value, Matchers.contains("value")); + MatcherAssert.assertThat((List) value, Matchers.contains("value")); } @SuppressWarnings("unchecked") @Test public void testGetValueSet() throws Exception { - new Expectations() { - { - request.getParameterValues("name"); - result = new String[] {"value"}; - } - }; + Mockito.when(request.getParameterValues("name")).thenReturn(new String[] {"value"}); ParamValueProcessor processor = createProcessor("name", TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class), null, true); Object value = processor.getValue(request); - Assert.assertThat((Set) value, Matchers.contains("value")); + MatcherAssert.assertThat((Set) value, Matchers.contains("value")); } @Test public void testSetValue() throws Exception { - createClientRequest(); + Mockito.doAnswer(invocation -> { + forms.put("name", "value"); + return null; + }).when(clientRequest).addForm("name", "value"); ParamValueProcessor processor = createProcessor("name", String.class); processor.setValue(clientRequest, "value"); - Assert.assertEquals("value", forms.get("name")); + Assertions.assertEquals("value", forms.get("name")); } @Test public void testSetValueDate() throws Exception { Date date = new Date(); - createClientRequest(); - + Mockito.doAnswer(invocation -> { + forms.put("name", date); + return null; + }).when(clientRequest).addForm("name", date); ParamValueProcessor processor = createProcessor("name", Date.class); processor.setValue(clientRequest, date); - Assert.assertSame(date, forms.get("name")); + Assertions.assertSame(date, forms.get("name")); } @Test public void testGetProcessorType() { ParamValueProcessor processor = createProcessor("name", String.class); - Assert.assertEquals("formData", processor.getProcessorType()); + Assertions.assertEquals("formData", processor.getProcessorType()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java index 4551f6a1366..f2b7b9c393e 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestFormProcessorCreator.java @@ -17,22 +17,32 @@ package org.apache.servicecomb.common.rest.codec.param; +import java.util.HashMap; + import org.apache.servicecomb.common.rest.codec.param.FormProcessorCreator.FormProcessor; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.swagger.generator.SwaggerConst; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -import io.swagger.models.parameters.FormParameter; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.MediaType; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.RequestBody; +@SuppressWarnings({"rawtypes", "unchecked"}) public class TestFormProcessorCreator { @Test public void testCreate() { ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.findValue(FormProcessorCreator.PARAMTYPE); - FormParameter p = new FormParameter(); - p.setName("p1"); + RequestBody p = new RequestBody(); + p.setContent(new Content()); + p.getContent().addMediaType(SwaggerConst.FORM_MEDIA_TYPE, new MediaType()); + p.getContent().get(SwaggerConst.FORM_MEDIA_TYPE).setSchema(new Schema()); + p.getContent().get(SwaggerConst.FORM_MEDIA_TYPE).getSchema().setProperties(new HashMap<>()); - ParamValueProcessor processor = creator.create(p, String.class); + ParamValueProcessor processor = creator.create(null, "p1", p, String.class); - Assert.assertEquals(FormProcessor.class, processor.getClass()); + Assertions.assertEquals(FormProcessor.class, processor.getClass()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessor.java index 866bb9ad683..39bed2e809b 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessor.java @@ -26,32 +26,33 @@ import java.util.Map; import java.util.Set; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.codec.RestClientRequest; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.common.rest.codec.param.HeaderProcessorCreator.HeaderProcessor; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; import com.fasterxml.jackson.databind.util.StdDateFormat; -import io.swagger.models.parameters.HeaderParameter; -import io.swagger.models.properties.ArrayProperty; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.HeaderParameter; +import jakarta.servlet.http.HttpServletRequest; public class TestHeaderProcessor { - @Mocked - HttpServletRequest request; + final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Map headers = new HashMap<>(); + final Map headers = new HashMap<>(); - RestClientRequest clientRequest; + final RestClientRequest clientRequest = Mockito.mock(RestClientRequest.class); private HeaderProcessor createProcessor(String name, Type type) { return createProcessor(name, type, null, true); @@ -61,37 +62,33 @@ private HeaderProcessor createProcessor(String name, Type type, String defaultVa JavaType javaType = TypeFactory.defaultInstance().constructType(type); HeaderParameter headerParameter = new HeaderParameter(); + headerParameter.setSchema(new Schema()); headerParameter.name(name) - .required(required) - .setDefaultValue(defaultValue); + .required(required); + headerParameter.getSchema().setDefault(defaultValue); if (javaType.isContainerType()) { - headerParameter.type(ArrayProperty.TYPE); + headerParameter.schema(new ArraySchema()); } return new HeaderProcessor(headerParameter, javaType); } - private void createClientRequest() { - clientRequest = new MockUp() { - @Mock - void putHeader(String name, String value) { - headers.put(name, value); - } - }.getMockInstance(); + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach + void setUp() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.header.ignoreRequiredCheck" + , boolean.class, false)).thenReturn(false); } @Test public void testGetValueNormal() throws Exception { - new Expectations() { - { - request.getHeader("h1"); - result = "h1v"; - } - }; + Mockito.when(request.getHeader("h1")).thenReturn("h1v"); HeaderProcessor processor = createProcessor("h1", String.class); Object value = processor.getValue(request); - Assert.assertEquals("h1v", value); + Assertions.assertEquals("h1v", value); } @SuppressWarnings("deprecation") @@ -99,155 +96,132 @@ public void testGetValueNormal() throws Exception { public void testGetValueNormalDate() throws Exception { Date date = new Date(); String strDate = com.fasterxml.jackson.databind.util.ISO8601Utils.format(date); - new Expectations() { - { - request.getHeader("h1"); - result = strDate; - } - }; + Mockito.when(request.getHeader("h1")).thenReturn(strDate); HeaderProcessor processor = createProcessor("h1", Date.class); Object value = processor.getValue(request); - Assert.assertEquals(strDate, com.fasterxml.jackson.databind.util.ISO8601Utils.format((Date) value)); + Assertions.assertEquals(strDate, com.fasterxml.jackson.databind.util.ISO8601Utils.format((Date) value)); } @Test public void testGetValueContainerTypeNull() throws Exception { - new Expectations() { - { - request.getHeaders("h1"); - result = null; - } - }; + Mockito.when(request.getHeader("h1")).thenReturn(null); HeaderProcessor processor = createProcessor("h1", String[].class, null, false); String[] value = (String[]) processor.getValue(request); - Assert.assertNull(value); + Assertions.assertNull(value); } @Test public void testGetValueRequiredTrue() throws Exception { - new Expectations() { - { - request.getHeader("h1"); - result = null; - } - }; + Mockito.when(request.getHeader("h1")).thenReturn(null); HeaderProcessor processor = createProcessor("h1", String.class); try { processor.getValue(request); - Assert.assertEquals("required is true, throw exception", "not throw exception"); + Assertions.assertEquals("required is true, throw exception", "not throw exception"); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Parameter is required.")); + Assertions.assertTrue(e.getMessage().contains("Parameter is required.")); } } @Test public void testGetValueRequiredFalse() throws Exception { - new Expectations() { - { - request.getHeader("h1"); - result = null; - } - }; + Mockito.when(request.getHeader("h1")).thenReturn(null); HeaderProcessor processor = createProcessor("h1", String.class, "test", false); Object value = processor.getValue(request); - Assert.assertEquals("test", value); + Assertions.assertEquals("test", value); } @Test public void testGetValueArray() throws Exception { - new Expectations() { - { - request.getHeaders("h1"); - result = Collections.enumeration(Arrays.asList("h1v")); - } - }; + Mockito.when(request.getHeaders("h1")).thenReturn(Collections.enumeration(Arrays.asList("h1v"))); HeaderProcessor processor = createProcessor("h1", String[].class); String[] value = (String[]) processor.getValue(request); - Assert.assertThat(value, Matchers.arrayContaining("h1v")); + MatcherAssert.assertThat(value, Matchers.arrayContaining("h1v")); } @SuppressWarnings("unchecked") @Test public void testGetValueList() throws Exception { - new Expectations() { - { - request.getHeaders("h1"); - result = Collections.enumeration(Arrays.asList("h1v")); - } - }; + Mockito.when(request.getHeaders("h1")).thenReturn(Collections.enumeration(Arrays.asList("h1v"))); HeaderProcessor processor = createProcessor("h1", TypeFactory.defaultInstance().constructCollectionType(List.class, String.class), null, true); Object value = processor.getValue(request); - Assert.assertThat((List) value, Matchers.contains("h1v")); + MatcherAssert.assertThat((List) value, Matchers.contains("h1v")); } @SuppressWarnings("unchecked") @Test public void testGetValueSet() throws Exception { - new Expectations() { - { - request.getHeaders("h1"); - result = Collections.enumeration(Arrays.asList("h1v")); - } - }; + Mockito.when(request.getHeaders("h1")).thenReturn(Collections.enumeration(Arrays.asList("h1v"))); HeaderProcessor processor = createProcessor("h1", TypeFactory.defaultInstance().constructCollectionType(Set.class, String.class), null, true); Object value = processor.getValue(request); - Assert.assertThat((Set) value, Matchers.contains("h1v")); + MatcherAssert.assertThat((Set) value, Matchers.contains("h1v")); } @Test public void testSetValue() throws Exception { - createClientRequest(); + Mockito.doAnswer(invocation -> { + headers.put("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString("h1v")); + return null; + }).when(clientRequest).putHeader("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString("h1v")); HeaderProcessor processor = createProcessor("h1", String.class); processor.setValue(clientRequest, "h1v"); - Assert.assertEquals("h1v", headers.get("h1")); + Assertions.assertEquals("h1v", headers.get("h1")); } @Test public void testSetValueNull() throws Exception { - createClientRequest(); + Mockito.doAnswer(invocation -> { + headers.put("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString(null)); + return null; + }).when(clientRequest).putHeader("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString(null)); HeaderProcessor processor = createProcessor("h1", String.class); processor.setValue(clientRequest, null); - Assert.assertEquals(0, headers.size()); + Assertions.assertEquals(0, headers.size()); } @Test public void testSetValueDateFixed() throws Exception { Date date = new Date(1586957400199L); - String strDate = "2020-04-15T13:30:00.199+00:00"; + String strDate = "2020-04-15T13:30:00.199+00:00"; - createClientRequest(); + Mockito.doAnswer(invocation -> { + headers.put("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString(date)); + return null; + }).when(clientRequest).putHeader("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString(date)); HeaderProcessor processor = createProcessor("h1", Date.class); processor.setValue(clientRequest, date); - Assert.assertEquals(strDate, headers.get("h1")); + Assertions.assertEquals(strDate, headers.get("h1")); } @Test public void testSetValueDate() throws Exception { Date date = new Date(); - String strDate = new StdDateFormat().format(date); - createClientRequest(); + String strDate = new StdDateFormat().format(date); + Mockito.doAnswer(invocation -> { + headers.put("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString(date)); + return null; + }).when(clientRequest).putHeader("h1", RestObjectMapperFactory.getConsumerWriterMapper().convertToString(date)); HeaderProcessor processor = createProcessor("h1", Date.class); processor.setValue(clientRequest, date); - Assert.assertEquals(strDate, headers.get("h1")); + Assertions.assertEquals(strDate, headers.get("h1")); } @Test public void testGetProcessorType() { HeaderProcessor processor = createProcessor("h1", String.class); - Assert.assertEquals("header", processor.getProcessorType()); + Assertions.assertEquals("header", processor.getProcessorType()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java index 8e8e9f4ef68..d275b16b62e 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestHeaderProcessorCreator.java @@ -18,21 +18,36 @@ package org.apache.servicecomb.common.rest.codec.param; import org.apache.servicecomb.common.rest.codec.param.HeaderProcessorCreator.HeaderProcessor; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import io.swagger.models.parameters.HeaderParameter; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.HeaderParameter; public class TestHeaderProcessorCreator { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.header.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } + @Test public void testCreate() { ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.findValue(HeaderProcessorCreator.PARAMTYPE); HeaderParameter hp = new HeaderParameter(); hp.setName("h1"); + hp.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(hp, String.class); + ParamValueProcessor processor = creator.create(null, hp.getName(), hp, String.class); - Assert.assertEquals(HeaderProcessor.class, processor.getClass()); + Assertions.assertEquals(HeaderProcessor.class, processor.getClass()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessor.java index 443a04adf50..ff8218768cf 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessor.java @@ -20,23 +20,20 @@ import java.util.HashMap; import java.util.Map; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.codec.param.PathProcessorCreator.PathProcessor; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.databind.type.TypeFactory; - -import mockit.Expectations; -import mockit.Mocked; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestPathProcessor { - @Mocked - HttpServletRequest request; + final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - Map pathVars = new HashMap<>(); + final Map pathVars = new HashMap<>(); ParamValueProcessor processor; @@ -46,26 +43,21 @@ private void createProcessor(String name, Class type) { private void prepareGetValue(String name, Class type) { createProcessor(name, type); - new Expectations() { - { - request.getAttribute(RestConst.PATH_PARAMETERS); - result = pathVars; - } - }; + Mockito.when(request.getAttribute(RestConst.PATH_PARAMETERS)).thenReturn(pathVars); } @Test public void testGetValueNoPathVars() throws Exception { createProcessor("name", String.class); - Assert.assertEquals(null, processor.getValue(request)); + Assertions.assertNull(processor.getValue(request)); } @Test public void testGetValuePathNotFound() throws Exception { prepareGetValue("name", String.class); - Assert.assertEquals(null, processor.getValue(request)); + Assertions.assertNull(processor.getValue(request)); } @Test @@ -73,7 +65,7 @@ public void testGetValuePathNormal() throws Exception { prepareGetValue("name", String.class); pathVars.put("name", "value"); - Assert.assertEquals("value", processor.getValue(request)); + Assertions.assertEquals("value", processor.getValue(request)); } @Test @@ -81,7 +73,7 @@ public void testGetSpaceEncoded() throws Exception { prepareGetValue("name", String.class); pathVars.put("name", "a%20b"); - Assert.assertEquals("a b", processor.getValue(request)); + Assertions.assertEquals("a b", processor.getValue(request)); } @Test @@ -89,7 +81,7 @@ public void testGetPlus() throws Exception { prepareGetValue("name", String.class); pathVars.put("name", "a+b"); - Assert.assertEquals("a+b", processor.getValue(request)); + Assertions.assertEquals("a+b", processor.getValue(request)); } @Test @@ -97,19 +89,19 @@ public void testGetPercentage() throws Exception { prepareGetValue("name", String.class); pathVars.put("name", "%25%25"); - Assert.assertEquals("%%", processor.getValue(request)); + Assertions.assertEquals("%%", processor.getValue(request)); } @Test public void testGetColon() throws Exception { prepareGetValue("name", String.class); pathVars.put("name", "aa:bb"); - Assert.assertEquals("aa:bb", processor.getValue(request)); + Assertions.assertEquals("aa:bb", processor.getValue(request)); } @Test public void testGetProcessorType() { createProcessor("name", String.class); - Assert.assertEquals("path", processor.getProcessorType()); + Assertions.assertEquals("path", processor.getProcessorType()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java index b6a99327851..0f40291c82b 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestPathProcessorCreator.java @@ -18,11 +18,12 @@ package org.apache.servicecomb.common.rest.codec.param; import org.apache.servicecomb.common.rest.codec.param.PathProcessorCreator.PathProcessor; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.PathParameter; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.PathParameter; public class TestPathProcessorCreator { @Test @@ -31,9 +32,10 @@ public void testCreate() { ParamValueProcessorCreatorManager.INSTANCE.findValue(PathProcessorCreator.PARAMTYPE); Parameter parameter = new PathParameter(); parameter.setName("path"); + parameter.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(parameter, String.class); + ParamValueProcessor processor = creator.create(null, parameter.getName(), parameter, String.class); - Assert.assertEquals(PathProcessor.class, processor.getClass()); + Assertions.assertEquals(PathProcessor.class, processor.getClass()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessor.java index e70a9172fc1..be18fb8378b 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessor.java @@ -17,122 +17,117 @@ package org.apache.servicecomb.common.rest.codec.param; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.QueryParameter; -import io.swagger.models.properties.ArrayProperty; -import mockit.Expectations; -import mockit.Mocked; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; +import io.swagger.v3.oas.models.parameters.QueryParameter; +import jakarta.servlet.http.HttpServletRequest; public class TestQueryProcessor { - @Mocked - HttpServletRequest request; + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } - private ParamValueProcessor createProcessor(String name, Class type, String collectionFormat) { - return createProcessor(name, type, null, true, collectionFormat); + final HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + + private ParamValueProcessor createProcessor(String name, Class type, + Parameter.StyleEnum style, boolean explode) { + return createProcessor(name, type, null, true, style, explode); } private ParamValueProcessor createProcessor(String name, Class type, String defaultValue, boolean required, - String collectionFormat) { + Parameter.StyleEnum style, boolean explode) { JavaType javaType = TypeFactory.defaultInstance().constructType(type); QueryParameter queryParameter = new QueryParameter(); queryParameter.name(name) .required(required) - .collectionFormat(collectionFormat) - .setDefaultValue(defaultValue); + .setSchema(new StringSchema()); + queryParameter.getSchema().setDefault(defaultValue); if (javaType.isContainerType()) { - queryParameter.type(ArrayProperty.TYPE); + queryParameter.setSchema(new ArraySchema()); + queryParameter.setExplode(explode); + queryParameter.setStyle(style); } return new QueryProcessor(queryParameter, javaType); } @Test public void testGetValueNormal() throws Exception { - new Expectations() { - { - request.getParameter("name"); - result = "value"; - } - }; - - ParamValueProcessor processor = createProcessor("name", String.class, "multi"); + Mockito.when(request.getParameter("name")).thenReturn("value"); + + ParamValueProcessor processor = createProcessor("name", String.class, StyleEnum.FORM, true); Object value = processor.getValue(request); - Assert.assertEquals("value", value); + Assertions.assertEquals("value", value); } @Test public void testGetValueContainerType() throws Exception { - new Expectations() { - { - request.getParameterValues("name"); - result = new String[] {"value", "value2"}; - } - }; - - ParamValueProcessor processor = createProcessor("name", String[].class, "multi"); + Mockito.when(request.getParameterValues("name")).thenReturn(new String[] {"value", "value2"}); + + ParamValueProcessor processor = createProcessor("name", String[].class, StyleEnum.FORM, true); String[] value = (String[]) processor.getValue(request); - Assert.assertThat(value, Matchers.arrayContaining("value", "value2")); + MatcherAssert.assertThat(value, Matchers.arrayContaining("value", "value2")); } @Test public void testGetValueOnCollectionFormatIsCsv() throws Exception { - new Expectations() { - { - request.getParameter("name"); - result = "value2,value3"; - } - }; - - ParamValueProcessor processor = createProcessor("name", String[].class, "csv"); + Mockito.when(request.getParameter("name")).thenReturn("value2,value3"); + + ParamValueProcessor processor = createProcessor("name", String[].class, StyleEnum.FORM, false); String[] value = (String[]) processor.getValue(request); - Assert.assertThat(value, Matchers.arrayContaining("value2", "value3")); + MatcherAssert.assertThat(value, Matchers.arrayContaining("value2", "value3")); } @Test public void testGetProcessorType() { - ParamValueProcessor processor = createProcessor("name", String.class, "multi"); - Assert.assertEquals("query", processor.getProcessorType()); + ParamValueProcessor processor = createProcessor("name", String.class, StyleEnum.FORM, true); + Assertions.assertEquals("query", processor.getProcessorType()); } @Test public void testGetValueRequiredTrue() throws Exception { - new Expectations() { - { - request.getParameter("name"); - result = null; - } - }; - - ParamValueProcessor processor = createProcessor("name", String.class, "multi"); + Mockito.when(request.getParameter("name")).thenReturn(null); + + ParamValueProcessor processor = createProcessor("name", String.class, StyleEnum.FORM, true); try { processor.getValue(request); - Assert.assertEquals("required is true, throw exception", "not throw exception"); + Assertions.assertEquals("required is true, throw exception", "not throw exception"); } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("Parameter is required.")); + Assertions.assertTrue(e.getMessage().contains("Parameter name is required.")); } } @Test public void testGetValueRequiredFalse() throws Exception { - new Expectations() { - { - request.getParameter("name"); - result = null; - } - }; - - ParamValueProcessor processor = createProcessor("name", String.class, "test", false, "multi"); + Mockito.when(request.getParameter("name")).thenReturn(null); + + ParamValueProcessor processor = createProcessor("name", String.class, "test", false, StyleEnum.FORM, true); Object result = processor.getValue(request); - Assert.assertEquals("test", result); + Assertions.assertEquals("test", result); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java index f5b0e77e7e6..a75e1df2b2f 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestQueryProcessorCreator.java @@ -17,66 +17,83 @@ package org.apache.servicecomb.common.rest.codec.param; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.core.env.Environment; import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.QueryParameter; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.QueryParameter; +import jakarta.servlet.http.HttpServletRequest; public class TestQueryProcessorCreator { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } + @Test public void testCreate() { ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.findValue(QueryProcessorCreator.PARAMTYPE); Parameter parameter = new QueryParameter(); parameter.setName("query"); + parameter.setSchema(new Schema()); + ParamValueProcessor processor = creator.create(null, parameter.getName(), parameter, String.class); - ParamValueProcessor processor = creator.create(parameter, String.class); - - Assert.assertEquals(QueryProcessor.class, processor.getClass()); + Assertions.assertEquals(QueryProcessor.class, processor.getClass()); String result = (String) processor.convertValue("Hello", TypeFactory.defaultInstance().constructType(String.class)); - Assert.assertEquals("Hello", result); + Assertions.assertEquals("Hello", result); result = (String) processor.convertValue("", TypeFactory.defaultInstance().constructType(String.class)); - Assert.assertEquals("", result); + Assertions.assertEquals("", result); result = (String) processor.convertValue(null, TypeFactory.defaultInstance().constructType(String.class)); - Assert.assertEquals(null, result); + Assertions.assertNull(result); } @SuppressWarnings("UnusedAssignment") @Test public void testCreateNullAsEmpty() throws Exception { HttpServletRequest request = Mockito.mock(HttpServletRequest.class); - ArchaiusUtils.setProperty("servicecomb.rest.parameter.query.emptyAsNull", "true"); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(true); ParamValueProcessorCreator creator = ParamValueProcessorCreatorManager.INSTANCE.findValue(QueryProcessorCreator.PARAMTYPE); Parameter parameter = new QueryParameter(); parameter.setName("query"); + parameter.setSchema(new Schema()); - ParamValueProcessor processor = creator.create(parameter, String.class); + ParamValueProcessor processor = creator.create(null, parameter.getName(), parameter, String.class); - Assert.assertEquals(QueryProcessor.class, processor.getClass()); + Assertions.assertEquals(QueryProcessor.class, processor.getClass()); Mockito.when(request.getParameter("query")).thenReturn("Hello"); String result = (String) processor.getValue(request); - Assert.assertEquals("Hello", result); + Assertions.assertEquals("Hello", result); Mockito.when(request.getParameter("query")).thenReturn(""); result = (String) processor.getValue(request); - Assert.assertEquals(null, result); + Assertions.assertNull(result); Mockito.when(request.getParameter("query")).thenReturn(null); result = (String) processor.convertValue(null, TypeFactory.defaultInstance().constructType(String.class)); result = (String) processor.getValue(request); - Assert.assertEquals(null, result); + Assertions.assertNull(result); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java deleted file mode 100644 index f0baacb6042..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/param/TestRestClientRequestImpl.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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.common.rest.codec.param; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; - -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.google.common.collect.Multimap; - -import io.vertx.core.Context; -import io.vertx.core.MultiMap; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpClientRequest; -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestRestClientRequestImpl { - @Mocked - private HttpClientRequest request; - - @Mocked - private Context context; - - @Test - public void testForm() throws Exception { - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null); - restClientRequest.addForm("abc", "Hello"); - restClientRequest.addForm("def", "world"); - restClientRequest.addForm("ghi", null); - Buffer buffer = restClientRequest.getBodyBuffer(); - Assert.assertEquals("abc=Hello&def=world&", buffer.toString()); - } - - @Test - public void testCookie() throws Exception { - HttpClientRequest request = new MockUp() { - - MultiMap map = MultiMap.caseInsensitiveMultiMap(); - - @Mock - public HttpClientRequest putHeader(CharSequence key, CharSequence val) { - map.add(key, val); - return null; - } - - @Mock - public MultiMap headers() { - return map; - } - }.getMockInstance(); - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null); - restClientRequest.addCookie("sessionid", "abcdefghijklmnopqrstuvwxyz"); - restClientRequest.addCookie("region", "china-north"); - restClientRequest.write(Buffer.buffer("I love servicecomb")); - restClientRequest.end(); - Buffer buffer = restClientRequest.getBodyBuffer(); - Assert.assertEquals("I love servicecomb", buffer.toString()); - Assert.assertEquals("sessionid=abcdefghijklmnopqrstuvwxyz; region=china-north; ", - restClientRequest.request.headers().get(HttpHeaders.COOKIE)); - } - - @Test - public void fileBoundaryInfo_nullSubmittedFileName(@Mocked Part part) { - new Expectations() { - { - part.getSubmittedFileName(); - result = null; - part.getContentType(); - result = "abc"; - } - }; - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null); - Buffer buffer = restClientRequest.fileBoundaryInfo("boundary", "name", part); - Assert.assertEquals("\r\n" + - "--boundary\r\n" + - "Content-Disposition: form-data; name=\"name\"; filename=\"null\"\r\n" + - "Content-Type: abc\r\n" + - "Content-Transfer-Encoding: binary\r\n" + - "\r\n", buffer.toString()); - } - - @Test - public void fileBoundaryInfo_validSubmittedFileName(@Mocked Part part) { - new Expectations() { - { - part.getSubmittedFileName(); - result = "a.txt"; - part.getContentType(); - result = MediaType.TEXT_PLAIN; - } - }; - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null); - Buffer buffer = restClientRequest.fileBoundaryInfo("boundary", "name", part); - Assert.assertEquals("\r\n" + - "--boundary\r\n" + - "Content-Disposition: form-data; name=\"name\"; filename=\"a.txt\"\r\n" + - "Content-Type: text/plain\r\n" + - "Content-Transfer-Encoding: binary\r\n" + - "\r\n", buffer.toString()); - } - - @Test - public void testAttach() { - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null); - Part part = Mockito.mock(Part.class); - String fileName = "fileName"; - - restClientRequest.attach(fileName, part); - - Multimap uploads = Deencapsulation.getField(restClientRequest, "uploads"); - Assert.assertEquals(1, uploads.size()); - Assert.assertThat(uploads.asMap(), Matchers.hasEntry(fileName, Arrays.asList(part))); - } - - @Test - public void testAttachOnPartIsNull() { - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, null, null); - - restClientRequest.attach("fileName", null); - - Multimap uploads = Deencapsulation.getField(restClientRequest, "uploads"); - Assert.assertTrue(uploads.isEmpty()); - } - - @Test - public void doEndWithUpload() { - Map headers = new HashMap<>(); - new MockUp(request) { - @Mock - HttpClientRequest putHeader(String name, String value) { - headers.put(name, value); - return request; - } - }; - - UUID uuid = new UUID(0, 0); - new Expectations(UUID.class) { - { - UUID.randomUUID(); - result = uuid; - } - }; - RestClientRequestImpl restClientRequest = new RestClientRequestImpl(request, context, null); - restClientRequest.doEndWithUpload(); - - Assert.assertEquals("multipart/form-data; charset=UTF-8; boundary=boundary00000000-0000-0000-0000-000000000000", - headers.get(HttpHeaders.CONTENT_TYPE)); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceJsonProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceJsonProcessor.java index dcd5ea4e52f..db8e71cd5a9 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceJsonProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceJsonProcessor.java @@ -23,42 +23,42 @@ import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.type.TypeFactory; import io.vertx.core.buffer.Buffer; +import org.junit.jupiter.api.Test; public class TestProduceJsonProcessor { - ProduceProcessor pp = ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(); + final ProduceProcessor pp = ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(); - JavaType stringType = TypeFactory.defaultInstance().constructType(String.class); + final JavaType stringType = TypeFactory.defaultInstance().constructType(String.class); @Test public void testEncodeResponseNull() throws Exception { Buffer buffer = pp.encodeResponse(null); - Assert.assertNull(buffer); + Assertions.assertNull(buffer); ByteArrayOutputStream os = new ByteArrayOutputStream(); pp.encodeResponse(os, null); - Assert.assertEquals(0, os.size()); + Assertions.assertEquals(0, os.size()); } @Test - public void testdecodeResponseNull() throws Exception { + public void testDecodeResponseNull() throws Exception { JavaType resultType = TypeFactory.unknownType(); Object result = pp.decodeResponse(Buffer.buffer(), resultType); - Assert.assertNull(result); + Assertions.assertNull(result); ByteArrayInputStream is = new ByteArrayInputStream(new byte[] {}); try { pp.decodeResponse(is, resultType); - Assert.fail(); + Assertions.fail(); } catch (Exception e) { - Assert.assertTrue(e instanceof MismatchedInputException); + Assertions.assertTrue(e instanceof MismatchedInputException); } } @@ -66,10 +66,10 @@ public void testdecodeResponseNull() throws Exception { public void testBufferNormal() throws Exception { String value = "abc"; Buffer buffer = pp.encodeResponse(value); - Assert.assertEquals("\"abc\"", buffer.toString(StandardCharsets.UTF_8)); + Assertions.assertEquals("\"abc\"", buffer.toString(StandardCharsets.UTF_8)); Object result = pp.decodeResponse(buffer, stringType); - Assert.assertEquals(value, result); + Assertions.assertEquals(value, result); } @Test @@ -78,11 +78,11 @@ public void testStreamNormal() throws Exception { ByteArrayOutputStream os = new ByteArrayOutputStream(); pp.encodeResponse(os, value); - Assert.assertEquals("\"abc\"", os.toString(StandardCharsets.UTF_8.name())); + Assertions.assertEquals("\"abc\"", os.toString(StandardCharsets.UTF_8.name())); ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); Object result = pp.decodeResponse(is, stringType); - Assert.assertEquals(value, result); + Assertions.assertEquals(value, result); os.close(); is.close(); @@ -90,12 +90,12 @@ public void testStreamNormal() throws Exception { @Test public void testSetSerializationView() { - Assert.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); + Assertions.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); pp.setSerializationView(null); - Assert.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); + Assertions.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); pp.setSerializationView(Object.class); - Assert.assertEquals(Object.class.getCanonicalName(), pp.getSerializationView()); + Assertions.assertEquals(Object.class.getCanonicalName(), pp.getSerializationView()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceProcessorManager.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceProcessorManager.java index 1c08656b995..58dd3e6d856 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceProcessorManager.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceProcessorManager.java @@ -17,13 +17,13 @@ package org.apache.servicecomb.common.rest.codec.produce; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestProduceProcessorManager { @Test public void testDefault() { - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(), + Assertions.assertSame(ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(), ProduceProcessorManager.INSTANCE.findDefaultProcessor()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceTextPlainProcessor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceTextPlainProcessor.java index aa6eca9abc4..d717072a27c 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceTextPlainProcessor.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/produce/TestProduceTextPlainProcessor.java @@ -23,48 +23,48 @@ import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; import io.vertx.core.buffer.Buffer; +import org.junit.jupiter.api.Test; public class TestProduceTextPlainProcessor { - ProduceProcessor pp = ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(); + final ProduceProcessor pp = ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(); - JavaType stringType = TypeFactory.defaultInstance().constructType(String.class); + final JavaType stringType = TypeFactory.defaultInstance().constructType(String.class); @Test public void testEncodeResponseNull() throws Exception { Buffer buffer = pp.encodeResponse(null); - Assert.assertNull(buffer); + Assertions.assertNull(buffer); ByteArrayOutputStream os = new ByteArrayOutputStream(); pp.encodeResponse(os, null); - Assert.assertEquals(0, os.size()); + Assertions.assertEquals(0, os.size()); } @Test public void testdecodeResponseNull() throws Exception { JavaType resultType = TypeFactory.unknownType(); Object result = pp.decodeResponse(Buffer.buffer(), resultType); - Assert.assertNull(result); + Assertions.assertNull(result); - ByteArrayInputStream is = new ByteArrayInputStream(new byte[] {}); + ByteArrayInputStream is = new ByteArrayInputStream("\"\"".getBytes(StandardCharsets.UTF_8)); result = pp.decodeResponse(is, resultType); - Assert.assertEquals(result, ""); + Assertions.assertEquals(result, ""); } @Test public void testBufferNormal() throws Exception { String value = "abc"; Buffer buffer = pp.encodeResponse(value); - Assert.assertEquals(value, buffer.toString(StandardCharsets.UTF_8)); + Assertions.assertEquals(value, buffer.toString(StandardCharsets.UTF_8)); Object result = pp.decodeResponse(buffer, stringType); - Assert.assertEquals(value, result); + Assertions.assertEquals(value, result); } @Test @@ -73,11 +73,11 @@ public void testStreamNormal() throws Exception { ByteArrayOutputStream os = new ByteArrayOutputStream(); pp.encodeResponse(os, value); - Assert.assertEquals(value, os.toString(StandardCharsets.UTF_8.name())); + Assertions.assertEquals(value, os.toString(StandardCharsets.UTF_8.name())); ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray()); Object result = pp.decodeResponse(is, stringType); - Assert.assertEquals(value, result); + Assertions.assertEquals(value, result); os.close(); is.close(); @@ -85,12 +85,12 @@ public void testStreamNormal() throws Exception { @Test public void testSetSerializationView() { - Assert.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); + Assertions.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); pp.setSerializationView(null); - Assert.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); + Assertions.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); pp.setSerializationView(Object.class); - Assert.assertEquals(DEFAULT_SERIAL_CLASS, pp.getSerializationView()); + Assertions.assertEquals("java.lang.Object", pp.getSerializationView()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsvTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsvTest.java index 18e9ba48c15..890075cbe7a 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsvTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecCsvTest.java @@ -19,11 +19,28 @@ import java.util.Date; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; class QueryCodecCsvTest extends QueryCodecTestBase { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } + @BeforeEach void setUp() { codec = new QueryCodecCsv(); @@ -114,4 +131,4 @@ void should_decode_values_start_with_delimiter() { should_decode(",,1", new int[] {0, 0, 1}); } } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMultiTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMultiTest.java index 948b831294b..3c56d1b1ce6 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMultiTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecMultiTest.java @@ -19,13 +19,27 @@ import java.util.Date; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; class QueryCodecMultiTest extends QueryCodecTestBase { + Environment environment = Mockito.mock(Environment.class); + @BeforeEach void setUp() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); codec = new QueryCodecMulti(); } @@ -104,4 +118,4 @@ void should_decode_null_to_single() { should_decode((String) null, null); } } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipesTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipesTest.java index aaa07123123..83f2b80062c 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipesTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecPipesTest.java @@ -19,11 +19,28 @@ import java.util.Date; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; class QueryCodecPipesTest extends QueryCodecTestBase { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } + @BeforeEach void setUp() { codec = new QueryCodecPipes(); @@ -114,4 +131,4 @@ void should_decode_values_start_with_delimiter() { should_decode("||1", new int[] {0, 0, 1}); } } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsvTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsvTest.java index bbbfb550cd8..c6e521f6718 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsvTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecSsvTest.java @@ -19,11 +19,28 @@ import java.util.Date; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +public class QueryCodecSsvTest extends QueryCodecTestBase { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } -class QueryCodecSsvTest extends QueryCodecTestBase { @BeforeEach void setUp() { codec = new QueryCodecSsv(); @@ -114,4 +131,4 @@ void should_decode_values_start_with_delimiter() { should_decode(" 1", new int[] {0, 0, 1}); } } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTestBase.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTestBase.java index c39e729b09b..03347607b36 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTestBase.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTestBase.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; import org.apache.servicecomb.common.rest.codec.param.QueryProcessorCreator.QueryProcessor; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; @@ -26,13 +26,14 @@ import com.fasterxml.jackson.databind.type.TypeFactory; -import io.swagger.models.parameters.QueryParameter; -import io.swagger.models.properties.ArrayProperty; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.QueryParameter; public class QueryCodecTestBase { QueryCodec codec; - String queryName = "q"; + final String queryName = "q"; void should_encode(String encodedValue, Object... values) throws Exception { URLPathStringBuilder builder = new URLPathStringBuilder(); @@ -42,34 +43,35 @@ void should_encode(String encodedValue, Object... values) throws Exception { } void should_decode(String value, Object decodedValue) { - HttpServletRequest Request = new AbstractHttpServletRequest() { + HttpServletRequest request = new AbstractHttpServletRequest() { @Override public String getParameter(String name) { return value; } }; - should_decode(Request, decodedValue); + should_decode(request, decodedValue); } void should_decode(String[] value, Object decodedValue) { - HttpServletRequest Request = new AbstractHttpServletRequest() { + HttpServletRequest request = new AbstractHttpServletRequest() { @Override public String[] getParameterValues(String name) { return value; } }; - should_decode(Request, decodedValue); + should_decode(request, decodedValue); } private void should_decode(HttpServletRequest request, Object decodedValue) { Class targetType = decodedValue == null ? Object.class : decodedValue.getClass(); QueryParameter queryParameter = new QueryParameter(); - queryParameter.setCollectionFormat(codec.getCodecName()); + queryParameter.setSchema(new Schema()); + queryParameter.getSchema().setFormat(codec.getCodecName()); if (targetType.isArray()) { - queryParameter.setType(ArrayProperty.TYPE); + queryParameter.setSchema(new ArraySchema()); } QueryProcessor queryProcessor = new QueryProcessor(queryParameter, diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTsvTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTsvTest.java deleted file mode 100644 index 2a835991512..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecTsvTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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.common.rest.codec.query; - -import java.util.Date; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -class QueryCodecTsvTest extends QueryCodecTestBase { - @BeforeEach - void setUp() { - codec = new QueryCodecTsv(); - } - - @Nested - class Encode { - @Test - void should_encode_date() throws Exception { - should_encode("?q=1970-01-01T00%3A00%3A00.000%2B00%3A00", new Date(0)); - } - - @Test - void should_encode_single_value() throws Exception { - should_encode("?q=v1", "v1"); - } - - @Test - void should_encode_empty_string() throws Exception { - should_encode("?q=", ""); - } - - @Test - void should_encode_common_string() throws Exception { - should_encode("?q=v1%09v2", "v1", "v2"); - } - - @Test - void should_encode_common_numbers() throws Exception { - should_encode("?q=1%092", 1, 2); - } - - @Test - void should_encode_chinese_values() throws Exception { - should_encode("?q=%E4%B8%AD%E6%96%87%09v2", "中文", "v2"); - } - - @Test - void should_encode_ignore_null() throws Exception { - should_encode("?q=v1%09v2", "v1", null, "v2"); - } - - @Test - void should_encode_when_values_is_empty_after_ignore_null() throws Exception { - should_encode("", new Object[] {null}); - } - } - - @Nested - class Decode { - @Test - void should_decode_single_value_to_array() { - should_decode("1", new int[] {1}); - } - - @Test - void should_decode_common_values_to_array() { - should_decode("1\t2", new int[] {1, 2}); - } - - @Test - void should_decode_null_to_array() { - should_decode((String) null, new int[] {}); - } - - @Test - void should_decode_empty_string_to_number() { - should_decode("", new int[] {0}); - } - - @Test - void should_decode_empty_string_to_string() { - should_decode("", new String[] {""}); - } - - @Test - void should_decode_common_values_with_empty_string_to_array() { - should_decode("1\t\t2", new int[] {1, 0, 2}); - } - - @Test - void should_decode_values_end_with_delimiter() { - should_decode("1\t\t", new int[] {1, 0, 0}); - } - - @Test - void should_decode_values_start_with_delimiter() { - should_decode("\t\t1", new int[] {0, 0, 1}); - } - } -} \ No newline at end of file diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsTest.java index c2c5fed1f41..7ccdbb2b38b 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/codec/query/QueryCodecsTest.java @@ -40,4 +40,4 @@ void can_override_by_customize_implement() { assertThat(queryCodecs.find(QueryCodecCsv.CODEC_NAME).getClass()) .isEqualTo(MyQueryCodecCsv.class); } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java index 242ae89dba6..db0b09f83fe 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestPath.java @@ -17,8 +17,6 @@ package org.apache.servicecomb.common.rest.definition; -import static org.junit.Assert.fail; - import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -27,72 +25,87 @@ import org.apache.servicecomb.common.rest.definition.path.QueryVarParamWriter; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.PathParameter; -import io.swagger.models.parameters.QueryParameter; -import mockit.Mock; -import mockit.MockUp; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.PathParameter; +import io.swagger.v3.oas.models.parameters.QueryParameter; public class TestPath { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } - @Before + @BeforeEach public void setUp() { } - @After + @AfterEach public void tearDown() { } @Test public void testPathRegExp() throws Exception { PathRegExp oPathRegExp = new PathRegExp("//{test}//"); - Assert.assertEquals(1, oPathRegExp.getGroupCount()); - Assert.assertEquals(0, oPathRegExp.getGroupWithRegExpCount()); + Assertions.assertEquals(1, oPathRegExp.getGroupCount()); + Assertions.assertEquals(0, oPathRegExp.getGroupWithRegExpCount()); PathRegExp oSecondPathRegExp = new PathRegExp("{[^/:]+?}"); - Assert.assertEquals(1, oSecondPathRegExp.getGroupCount()); - Assert.assertEquals(1, oSecondPathRegExp.getGroupWithRegExpCount()); - Assert.assertEquals("test/", PathRegExp.ensureEndWithSlash("test/")); - Assert.assertEquals("test/", PathRegExp.ensureEndWithSlash("test")); - Assert.assertEquals(null, oSecondPathRegExp.match("{test/test}", null)); - Assert.assertEquals("(]+?)/(.*)", (oSecondPathRegExp.toString())); - Assert.assertEquals(false, oSecondPathRegExp.isStaticPath()); - Assert.assertEquals(0, oSecondPathRegExp.getStaticCharCount()); - Assert.assertNotEquals(null, (oPathRegExp.match("//{test}//", new HashMap<>()))); + Assertions.assertEquals(1, oSecondPathRegExp.getGroupCount()); + Assertions.assertEquals(1, oSecondPathRegExp.getGroupWithRegExpCount()); + Assertions.assertEquals("test/", PathRegExp.ensureEndWithSlash("test/")); + Assertions.assertEquals("test/", PathRegExp.ensureEndWithSlash("test")); + Assertions.assertNull(oSecondPathRegExp.match("{test/test}", null)); + Assertions.assertEquals("(]+?)/(.*)", (oSecondPathRegExp.toString())); + Assertions.assertFalse(oSecondPathRegExp.isStaticPath()); + Assertions.assertEquals(0, oSecondPathRegExp.getStaticCharCount()); + Assertions.assertNotEquals(null, (oPathRegExp.match("//{test}//", new HashMap<>()))); // Error Scenarios new PathRegExp("//{test \t}//"); // Error Scenarios for double {{ try { new PathRegExp("//{test{"); - fail("an exception is expected!"); + Assertions.fail("an exception is expected!"); } catch (Exception e) { - Assert.assertEquals(true, e.getMessage().contains("A variable must not contain an extra")); + Assertions.assertTrue(e.getMessage().contains("A variable must not contain an extra")); } // Error Scenarios for illegal }} try { new PathRegExp("//}"); - fail("an exception is expected!"); + Assertions.fail("an exception is expected!"); } catch (Exception e) { - Assert.assertEquals(true, e.getMessage().contains("is only allowed as")); + Assertions.assertTrue(e.getMessage().contains("is only allowed as")); } // Error Scenarios for illegal ; try { new PathRegExp("//;"); - fail("an exception is expected!"); + Assertions.fail("an exception is expected!"); } catch (Exception e) { - Assert.assertEquals(true, e.getMessage().contains("matrix parameters are not allowed in")); + Assertions.assertTrue(e.getMessage().contains("matrix parameters are not allowed in")); } // Error Scenarios for NO } ; try { new PathRegExp("//{test"); - fail("an exception is expected!"); + Assertions.fail("an exception is expected!"); } catch (Exception e) { - Assert.assertEquals(true, e.getMessage().contains("No '}' found after")); + Assertions.assertTrue(e.getMessage().contains("No '}' found after")); } } @@ -102,40 +115,34 @@ public void testUrlPathBuilder() throws Exception { Parameter pathParameter = new PathParameter(); pathParameter.setName("id"); - RestParam oRestParam = new RestParam(pathParameter, int.class); + pathParameter.setSchema(new Schema<>()); + RestParam oRestParam = new RestParam(null, pathParameter, int.class); paramMap.put(oRestParam.getParamName(), oRestParam); Parameter queryParameter = new QueryParameter(); queryParameter.setName("q"); - oRestParam = new RestParam(queryParameter, String.class); + queryParameter.setSchema(new Schema<>()); + oRestParam = new RestParam(null, queryParameter, String.class); paramMap.put(oRestParam.getParamName(), oRestParam); URLPathBuilder oURLPathBuilder = new URLPathBuilder("/root/{id}", paramMap); Map parameters = new HashMap<>(); parameters.put("id", 100); parameters.put("q", "query"); - Assert.assertEquals("/root/100?q=query", oURLPathBuilder.createRequestPath(parameters)); - Assert.assertEquals("/root/100", oURLPathBuilder.createPathString(parameters)); + Assertions.assertEquals("/root/100?q=query", oURLPathBuilder.createRequestPath(parameters)); + Assertions.assertEquals("/root/100", oURLPathBuilder.createPathString(parameters)); } @Test public void testQueryVarParamWriter() { boolean status = true; - new MockUp() { - @Mock - public String getParamName() { - return "queryVar"; - } - }; - new MockUp() { - @Mock - protected Object getParamValue(Object[] args) { - return args[0]; - } - }; Parameter parameter = new QueryParameter(); - QueryVarParamWriter writer = new QueryVarParamWriter(new RestParam(parameter, String.class)); + parameter.setSchema(new Schema<>()); + RestParam restParam = new RestParam(null, parameter, String.class); + RestParam spy = Mockito.spy(restParam); + Mockito.when(spy.getParamName()).thenReturn("queryVar"); + QueryVarParamWriter writer = new QueryVarParamWriter(spy); try { Map parameters = new HashMap<>(); parameters.put("queryVar", "T"); @@ -157,12 +164,12 @@ protected Object getParamValue(Object[] args) { } catch (Exception e) { status = false; } - Assert.assertTrue(status); + Assertions.assertTrue(status); } private void verify(QueryVarParamWriter writer, Map args, String expect) throws Exception { URLPathStringBuilder sb = new URLPathStringBuilder(); writer.write(sb, args); - Assert.assertEquals(expect, sb.build()); + Assertions.assertEquals(expect, sb.build()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationComparator.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationComparator.java index cc4970eadee..66a4a5bad54 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationComparator.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationComparator.java @@ -18,8 +18,8 @@ package org.apache.servicecomb.common.rest.definition; import org.apache.servicecomb.common.rest.locator.MicroservicePaths; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestRestOperationComparator { @Test @@ -35,8 +35,8 @@ public void testStaticCharCount() { paths.addResource(more); paths.sortPath(); - Assert.assertSame(more, paths.getDynamicPathOperationList().get(0)); - Assert.assertSame(less, paths.getDynamicPathOperationList().get(1)); + Assertions.assertSame(more, paths.getDynamicPathOperationList().get(0)); + Assertions.assertSame(less, paths.getDynamicPathOperationList().get(1)); } @Test @@ -52,8 +52,8 @@ public void testVarGroupCount() { paths.addResource(more); paths.sortPath(); - Assert.assertSame(more, paths.getDynamicPathOperationList().get(0)); - Assert.assertSame(less, paths.getDynamicPathOperationList().get(1)); + Assertions.assertSame(more, paths.getDynamicPathOperationList().get(0)); + Assertions.assertSame(less, paths.getDynamicPathOperationList().get(1)); } @Test @@ -69,7 +69,7 @@ public void testGroupWithRegExpCount() { paths.addResource(more); paths.sortPath(); - Assert.assertSame(more, paths.getDynamicPathOperationList().get(0)); - Assert.assertSame(less, paths.getDynamicPathOperationList().get(1)); + Assertions.assertSame(more, paths.getDynamicPathOperationList().get(0)); + Assertions.assertSame(less, paths.getDynamicPathOperationList().get(1)); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java index 036bd60f96a..df8ebe47a75 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/TestRestOperationMeta.java @@ -17,49 +17,55 @@ package org.apache.servicecomb.common.rest.definition; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; import java.io.File; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; -import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.common.rest.RestEngineSchemaListener; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.bootstrap.SCBBootstrap; import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.core.executor.ExecutorManager; +import org.apache.servicecomb.core.transport.TransportManager; +import org.hamcrest.MatcherAssert; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import com.fasterxml.jackson.annotation.JsonView; -import io.swagger.models.Swagger; -import mockit.Expectations; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.servers.Server; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; public class TestRestOperationMeta { @Path("/") static class RestOperationMetaSchema { @Path("/emptyProduces") @GET - @Produces("") + @Produces(value = MediaType.APPLICATION_JSON) public String emptyProduces() { return null; } @Path("/emptyProducesWithView") @GET - @Produces("") + @Produces(value = MediaType.APPLICATION_JSON) @JsonView(Object.class) public String emptyProducesWithView() { return null; @@ -67,14 +73,14 @@ public String emptyProducesWithView() { @Path("/notSupport") @GET - @Produces("notSupport") + @Produces(value = MediaType.APPLICATION_JSON) public void notSupport() { } @Path("/notSupportWithView") @GET - @Produces("notSupport") + @Produces(value = MediaType.APPLICATION_JSON) @JsonView(Object.class) public void notSupportWithView() { @@ -112,14 +118,14 @@ public String jsonWithView() { @Path("/textCharJsonChar") @GET - @Produces({MediaType.APPLICATION_JSON + ";charset=UTF-8", MediaType.TEXT_PLAIN + ";charset=UTF-8"}) + @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}) public void textCharJsonChar() { } @Path("/textCharJsonCharWithView") @GET - @Produces({MediaType.APPLICATION_JSON + ";charset=UTF-8", MediaType.TEXT_PLAIN + ";charset=UTF-8"}) + @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN}) @JsonView(Object.class) public void textCharJsonCharWithView() { @@ -151,322 +157,125 @@ public void formWithView(@FormParam("form") String form) { } } - static SCBEngine scbEngine; + SCBEngine scbEngine; - static Swagger swagger; + OpenAPI swagger; OperationMeta meta; RestOperationMeta operationMeta; - @BeforeClass - public static void classSetup() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest() + @BeforeEach + public void setUp() { + Environment environment = Mockito.mock(Environment.class); + scbEngine = SCBBootstrap.createSCBEngineForTest(environment); + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + TransportManager transportManager = Mockito.mock(TransportManager.class); + scbEngine.setTransportManager(transportManager); + scbEngine.setExecutorManager(executorManager); + + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)) + .thenReturn(BootStrapProperties.DEFAULT_APPLICATION); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)) + .thenReturn("test"); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_ENVIRONMENT)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_ENVIRONMENT); + + List listeners = new ArrayList<>(); + listeners.add(new RestEngineSchemaListener()); + scbEngine.setBootListeners(listeners); + scbEngine .addProducerMeta("sid1", new RestOperationMetaSchema()) .run(); - swagger = scbEngine.getProducerMicroserviceMeta().ensureFindSchemaMeta("sid1").getSwagger(); + swagger = Mockito.spy(scbEngine.getProducerMicroserviceMeta().ensureFindSchemaMeta("sid1").getSwagger()); } - @AfterClass - public static void classTeardown() { + @AfterEach + public void teardown() { scbEngine.destroy(); - ArchaiusUtils.resetConfig(); } private void findOperation(String operationId) { - meta = scbEngine.getProducerMicroserviceMeta().operationMetas().get("test.sid1." + operationId); - operationMeta = RestMetaUtils.getRestOperationMeta(meta); - } - - @Test - public void testCreateProduceProcessorsNull() { - findOperation("emptyProduces"); - operationMeta.produces = null; - operationMeta.createProduceProcessors(); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - for (String produce : ProduceProcessorManager.INSTANCE.keys()) { - ProduceProcessor expected = ProduceProcessorManager.INSTANCE.findProcessor(produce, null); - Assert.assertSame(expected, operationMeta.findProduceProcessor(produce)); - } - } - - @Test - public void testCreateProduceProcessorsNullWithView() { - findOperation("emptyProducesWithView"); - operationMeta.produces = null; - operationMeta.createProduceProcessors(); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - for (String produce : ProduceProcessorManager.INSTANCE.keys()) { - ProduceProcessor expected = ProduceProcessorManager.INSTANCE.findProcessor(produce, Object.class); - Assert.assertSame(expected, operationMeta.findProduceProcessor(produce)); - } - } - - @Test - public void testCreateProduceProcessorsEmpty() { - findOperation("emptyProduces"); - operationMeta.produces = Arrays.asList(); - operationMeta.createProduceProcessors(); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - for (String produce : ProduceProcessorManager.INSTANCE.keys()) { - ProduceProcessor expected = ProduceProcessorManager.INSTANCE.findProcessor(produce, null); - Assert.assertSame(expected, operationMeta.findProduceProcessor(produce)); - } - } - - @Test - public void testCreateProduceProcessorsEmptyWithView() { - findOperation("emptyProducesWithView"); - operationMeta.produces = Arrays.asList(); - operationMeta.createProduceProcessors(); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - for (String produce : ProduceProcessorManager.INSTANCE.keys()) { - ProduceProcessor expected = ProduceProcessorManager.INSTANCE.findProcessor(produce, Object.class); - Assert.assertSame(expected, operationMeta.findProduceProcessor(produce)); - } - } - - @Test - public void testCreateProduceProcessorsNormal() { - findOperation("json"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(), - operationMeta.findProduceProcessor(MediaType.APPLICATION_JSON)); - Assert.assertNull(operationMeta.findProduceProcessor(MediaType.TEXT_PLAIN)); - } - - @Test - public void testCreateProduceProcessorsNormalWithView() { - findOperation("jsonWithView"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findJsonProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findJsonProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findJsonProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findJsonProcessorByViewClass(Object.class), - operationMeta.findProduceProcessor(MediaType.APPLICATION_JSON)); - Assert.assertNull(operationMeta.findProduceProcessor(MediaType.TEXT_PLAIN)); - } - - @Test - public void testCreateProduceProcessorsNotSupported() { - findOperation("notSupport"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessor(), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(), - operationMeta.findProduceProcessor(MediaType.APPLICATION_JSON)); - Assert.assertNull(operationMeta.findProduceProcessor(MediaType.TEXT_PLAIN)); - } - - @Test - public void testCreateProduceProcessorsNotSupportedWithView() { - findOperation("notSupportWithView"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor((String) null)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor("*/*")); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(ProduceProcessorManager.DEFAULT_TYPE)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultProcessorByViewClass(Object.class), - operationMeta.findProduceProcessor(MediaType.APPLICATION_JSON)); - Assert.assertNull(operationMeta.findProduceProcessor(MediaType.TEXT_PLAIN)); - } - - @Test - public void testCreateProduceProcessorsTextAndWildcard() { - findOperation("textPlain"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(), - operationMeta.ensureFindProduceProcessor(MediaType.WILDCARD)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(), - operationMeta.ensureFindProduceProcessor(MediaType.TEXT_PLAIN)); - Assert.assertNull(operationMeta.ensureFindProduceProcessor(MediaType.APPLICATION_JSON)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(), - operationMeta.ensureFindProduceProcessor( - MediaType.APPLICATION_JSON + "," + MediaType.APPLICATION_XML + "," + MediaType.WILDCARD)); - } - - @Test - public void testCreateProduceProcessorsTextAndWildcardWithView() { - findOperation("textPlainWithView"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findPlainProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(MediaType.WILDCARD)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findPlainProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(MediaType.TEXT_PLAIN)); - Assert.assertNull(operationMeta.ensureFindProduceProcessor(MediaType.APPLICATION_JSON)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findPlainProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor( - MediaType.APPLICATION_JSON + "," + MediaType.APPLICATION_XML + "," + MediaType.WILDCARD)); - } - - @Test - public void testCreateProduceProcessorsWithSemicolon() { - findOperation("textCharJsonChar"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultPlainProcessor(), - operationMeta.ensureFindProduceProcessor(MediaType.TEXT_PLAIN)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findDefaultJsonProcessor(), - operationMeta.ensureFindProduceProcessor(MediaType.APPLICATION_JSON)); - } - - @Test - public void testCreateProduceProcessorsWithSemicolonWithView() { - findOperation("textCharJsonCharWithView"); - - Assert.assertSame(ProduceProcessorManager.INSTANCE.findPlainProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(MediaType.TEXT_PLAIN)); - Assert.assertSame(ProduceProcessorManager.INSTANCE.findJsonProcessorByViewClass(Object.class), - operationMeta.ensureFindProduceProcessor(MediaType.APPLICATION_JSON)); - } - - @Test - public void testEnsureFindProduceProcessorAcceptNotFound() { - findOperation("textCharJsonChar"); - Assert.assertNull(operationMeta.ensureFindProduceProcessor("notSupport")); - } - - @Test - public void testEnsureFindProduceProcessorAcceptNotFoundWithView() { - findOperation("textCharJsonCharWithView"); - Assert.assertNull(operationMeta.ensureFindProduceProcessor("notSupport")); + meta = Mockito.spy(scbEngine.getProducerMicroserviceMeta().operationMetas().get("test.sid1." + operationId)); + operationMeta = Mockito.spy(RestMetaUtils.getRestOperationMeta(meta)); + SchemaMeta schemaMeta = Mockito.spy(meta.getSchemaMeta()); + Mockito.when(meta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getSwagger()).thenReturn(swagger); } @Test public void generatesAbsolutePathWithRootBasePath() { findOperation("textCharJsonChar"); - assertThat(operationMeta.getAbsolutePath(), is("/textCharJsonChar/")); + MatcherAssert.assertThat(operationMeta.getAbsolutePath(), is("/textCharJsonChar")); } @Test public void generatesAbsolutePathWithNonRootBasePath() { findOperation("textCharJsonChar"); - new Expectations(swagger) { - { - swagger.getBasePath(); - result = "/rest"; - } - }; + Server server = Mockito.mock(Server.class); + Mockito.when(server.getUrl()).thenReturn("/rest"); + Mockito.when(swagger.getServers()).thenReturn(Arrays.asList(server)); RestOperationMeta restOperationMeta = new RestOperationMeta(); - restOperationMeta.init(operationMeta.getOperationMeta()); + restOperationMeta.init(meta); - assertThat(restOperationMeta.getAbsolutePath(), is("/rest/textCharJsonChar/")); + MatcherAssert.assertThat(restOperationMeta.getAbsolutePath(), is("/rest/textCharJsonChar")); } @Test public void generatesAbsolutePathWithNullPath() { findOperation("textCharJsonChar"); - new Expectations(swagger) { - { - swagger.getBasePath(); - result = null; - } - }; - new Expectations(meta) { - { - meta.getOperationPath(); - result = null; - } - }; + Server server = Mockito.mock(Server.class); + Mockito.when(server.getUrl()).thenReturn(null); + Mockito.when(swagger.getServers()).thenReturn(Arrays.asList(server)); + Mockito.when(meta.getOperationPath()).thenReturn(null); RestOperationMeta restOperationMeta = new RestOperationMeta(); - restOperationMeta.init(operationMeta.getOperationMeta()); + restOperationMeta.init(meta); - assertThat(restOperationMeta.getAbsolutePath(), is("/")); + MatcherAssert.assertThat(restOperationMeta.getAbsolutePath(), is("/")); } @Test public void generatesAbsolutePathWithEmptyPath() { findOperation("textCharJsonChar"); - new Expectations(swagger) { - { - swagger.getBasePath(); - result = ""; - } - }; - new Expectations(meta) { - { - meta.getOperationPath(); - result = ""; - } - }; + Server server = Mockito.mock(Server.class); + Mockito.when(server.getUrl()).thenReturn(""); + Mockito.when(swagger.getServers()).thenReturn(Arrays.asList(server)); + Mockito.when(meta.getOperationPath()).thenReturn(""); RestOperationMeta restOperationMeta = new RestOperationMeta(); - restOperationMeta.init(operationMeta.getOperationMeta()); + restOperationMeta.init(meta); - assertThat(restOperationMeta.getAbsolutePath(), is("/")); + MatcherAssert.assertThat(restOperationMeta.getAbsolutePath(), is("/")); } @Test public void consecutiveSlashesAreRemoved() { findOperation("textCharJsonChar"); - new Expectations(swagger) { - { - swagger.getBasePath(); - result = "//rest//"; - } - }; - new Expectations(meta) { - { - meta.getOperationPath(); - result = "//sayHi//"; - } - }; + Server server = Mockito.mock(Server.class); + Mockito.when(server.getUrl()).thenReturn("//rest//"); + Mockito.when(swagger.getServers()).thenReturn(Arrays.asList(server)); + Mockito.when(meta.getOperationPath()).thenReturn("//sayHi//"); RestOperationMeta restOperationMeta = new RestOperationMeta(); - restOperationMeta.init(operationMeta.getOperationMeta()); + restOperationMeta.init(meta); - assertThat(restOperationMeta.getAbsolutePath(), is("/rest/sayHi/")); + MatcherAssert.assertThat(restOperationMeta.getAbsolutePath(), is("/rest/sayHi/")); } @Test public void testFormDataFlagTrue() { findOperation("form"); - assertThat(operationMeta.isFormData(), is(true)); + MatcherAssert.assertThat(operationMeta.isFormData(), is(true)); } @Test public void testFormDataFlagFalse() { findOperation("json"); - assertThat(operationMeta.isFormData(), is(false)); + MatcherAssert.assertThat(operationMeta.isFormData(), is(false)); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/PathVarParamWriterTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/PathVarParamWriterTest.java index 01978e8382b..99ef928b48d 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/PathVarParamWriterTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/PathVarParamWriterTest.java @@ -22,11 +22,9 @@ import org.apache.servicecomb.common.rest.definition.RestParam; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Mock; -import mockit.MockUp; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class PathVarParamWriterTest { @@ -38,7 +36,7 @@ public void writePlainPath() throws Exception { Map parameters = new HashMap<>(); parameters.put("test", "abc"); pathVarParamWriter.write(pathBuilder, parameters); - Assert.assertEquals("abc", pathBuilder.build()); + Assertions.assertEquals("abc", pathBuilder.build()); } @Test @@ -49,7 +47,7 @@ public void writePathWithSpace() throws Exception { Map parameters = new HashMap<>(); parameters.put("test", "a 20bc"); pathVarParamWriter.write(pathBuilder, parameters); - Assert.assertEquals("a%2020bc", pathBuilder.build()); + Assertions.assertEquals("a%2020bc", pathBuilder.build()); } @Test @@ -60,7 +58,7 @@ public void writePathWithPercentage() throws Exception { Map parameters = new HashMap<>(); parameters.put("test", "a%%bc"); pathVarParamWriter.write(pathBuilder, parameters); - Assert.assertEquals("/api/a%25%25bc", pathBuilder.build()); + Assertions.assertEquals("/api/a%25%25bc", pathBuilder.build()); } @Test @@ -71,7 +69,7 @@ public void writePathParamWithSlash() throws Exception { Map parameters = new HashMap<>(); parameters.put("test", "a/bc"); pathVarParamWriter.write(pathBuilder, parameters); - Assert.assertEquals("/api/a%2Fbc", pathBuilder.build()); + Assertions.assertEquals("/api/a%2Fbc", pathBuilder.build()); } @Test @@ -81,16 +79,12 @@ public void writeIntegerParam() throws Exception { Map parameters = new HashMap<>(); parameters.put("test", 12); pathVarParamWriter.write(pathBuilder, parameters); - Assert.assertEquals("12", pathBuilder.build()); + Assertions.assertEquals("12", pathBuilder.build()); } private PathVarParamWriter createPathVarParamWriter() { - RestParam restParam = new MockUp() { - @Mock - public String getParamName(){ - return "test"; - } - }.getMockInstance(); + RestParam restParam = Mockito.mock(RestParam.class); + Mockito.when(restParam.getParamName()).thenReturn("test"); return new PathVarParamWriter(restParam); } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java index 60c2561baae..1aafc89fbb3 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/QueryVarParamWriterTest.java @@ -26,11 +26,16 @@ import org.apache.servicecomb.common.rest.definition.RestParam; import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import io.swagger.models.parameters.QueryParameter; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter.StyleEnum; +import io.swagger.v3.oas.models.parameters.QueryParameter; public class QueryVarParamWriterTest { private static QueryVarParamWriter queryVarParamWriterCsv; @@ -39,24 +44,39 @@ public class QueryVarParamWriterTest { private static QueryVarParamWriter queryVarParamWriterDefault; - @BeforeClass + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + QueryParameter parameter = new QueryParameter(); parameter.setName("q"); - parameter.setCollectionFormat("csv"); + parameter.setSchema(new Schema()); + parameter.setStyle(StyleEnum.FORM); + parameter.setExplode(false); queryVarParamWriterCsv = new QueryVarParamWriter( - new RestParam(parameter, String[].class)); + new RestParam(null, parameter, String[].class)); parameter = new QueryParameter(); parameter.setName("q"); - parameter.setCollectionFormat("multi"); + parameter.setSchema(new Schema()); + parameter.setStyle(StyleEnum.FORM); + parameter.setExplode(true); queryVarParamWriterMulti = new QueryVarParamWriter( - new RestParam(parameter, String[].class)); + new RestParam(null, parameter, String[].class)); parameter = new QueryParameter(); parameter.setName("q"); + parameter.setSchema(new Schema()); queryVarParamWriterDefault = new QueryVarParamWriter( - new RestParam(parameter, String[].class)); + new RestParam(null, parameter, String[].class)); } @Test @@ -65,13 +85,13 @@ public void write() throws Exception { Map parameters = new HashMap<>(); parameters.put("q", "a"); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=a", stringBuilder.build()); + Assertions.assertEquals("?q=a", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=a", stringBuilder.build()); + Assertions.assertEquals("?q=a", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=a", stringBuilder.build()); + Assertions.assertEquals("?q=a", stringBuilder.build()); } @Test @@ -80,13 +100,13 @@ public void writeNull() throws Exception { Map parameters = new HashMap<>(); parameters.put("test", null); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); } @Test @@ -95,71 +115,71 @@ public void writeArray() throws Exception { Map parameters = new HashMap<>(); parameters.put("q", new String[] {"ab", "cd", "ef"}); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab%2Ccd%2Cef", stringBuilder.build()); + Assertions.assertEquals("?q=ab%2Ccd%2Cef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); // encode space char stringBuilder = new URLPathStringBuilder(); parameters.put("q", new String[] {"a b", " ", "", "ef"}); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=a+b%2C+%2C%2Cef", stringBuilder.build()); + Assertions.assertEquals("?q=a+b%2C+%2C%2Cef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); // pass blank string stringBuilder = new URLPathStringBuilder(); parameters.put("q", new String[] {""}); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=", stringBuilder.build()); + Assertions.assertEquals("?q=", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=", stringBuilder.build()); + Assertions.assertEquals("?q=", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=", stringBuilder.build()); + Assertions.assertEquals("?q=", stringBuilder.build()); // pass empty stringBuilder = new URLPathStringBuilder(); parameters.put("q", new String[] {}); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); // pass null parameters.put("q", new String[] {null}); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); parameters.put("q", new String[] {null, "ab", null, "cd", null, null, "", null, "ef", null}); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab%2Ccd%2C%2Cef", stringBuilder.build()); + Assertions.assertEquals("?q=ab%2Ccd%2C%2Cef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); } @Test @@ -169,70 +189,70 @@ public void writeList() throws Exception { parameters.put("q", queryList); URLPathStringBuilder stringBuilder = new URLPathStringBuilder(); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab%2Ccd%2Cef", stringBuilder.build()); + Assertions.assertEquals("?q=ab%2Ccd%2Cef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=ef", stringBuilder.build()); // encode space char parameters.put("q", Arrays.asList("a b", " ", "", "ef")); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=a+b%2C+%2C%2Cef", stringBuilder.build()); + Assertions.assertEquals("?q=a+b%2C+%2C%2Cef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=a+b&q=+&q=&q=ef", stringBuilder.build()); // pass blank string stringBuilder = new URLPathStringBuilder(); parameters.put("q", Collections.singletonList("")); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=", stringBuilder.build()); + Assertions.assertEquals("?q=", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=", stringBuilder.build()); + Assertions.assertEquals("?q=", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=", stringBuilder.build()); + Assertions.assertEquals("?q=", stringBuilder.build()); // pass empty stringBuilder = new URLPathStringBuilder(); parameters.put("q", new ArrayList<>()); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); // pass null parameters.put("q", Collections.singletonList(null)); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("", stringBuilder.build()); + Assertions.assertEquals("", stringBuilder.build()); parameters.put("q", Arrays.asList(null, "ab", null, "cd", null, null, "", null, "ef", null)); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterCsv.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab%2Ccd%2C%2Cef", stringBuilder.build()); + Assertions.assertEquals("?q=ab%2Ccd%2C%2Cef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterMulti.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); stringBuilder = new URLPathStringBuilder(); queryVarParamWriterDefault.write(stringBuilder, parameters); - Assert.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); + Assertions.assertEquals("?q=ab&q=cd&q=&q=ef", stringBuilder.build()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java index 90882c4ac2b..bcff2ff1523 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathBuilderTest.java @@ -23,14 +23,32 @@ import java.util.Map; import org.apache.servicecomb.common.rest.definition.RestParam; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import io.swagger.models.parameters.Parameter; -import io.swagger.models.parameters.PathParameter; -import io.swagger.models.parameters.QueryParameter; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.PathParameter; +import io.swagger.v3.oas.models.parameters.QueryParameter; public class URLPathBuilderTest { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void beforeClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.emptyAsNull", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreDefaultValue", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.query.ignoreRequiredCheck", boolean.class, false)) + .thenReturn(false); + } + @Test public void testNormal() throws Exception { Map paramMap = new LinkedHashMap<>(); @@ -45,9 +63,9 @@ public void testNormal() throws Exception { parameters.put("p1", "abcPath"); parameters.put("q0", 11); parameters.put("q1", "queryABC"); - Assert.assertEquals("/path/10/and/abcPath?q0=11&q1=queryABC", + Assertions.assertEquals("/path/10/and/abcPath?q0=11&q1=queryABC", urlPathBuilder.createRequestPath(parameters)); - Assert.assertEquals("/path/10/and/abcPath", + Assertions.assertEquals("/path/10/and/abcPath", urlPathBuilder.createPathString(parameters)); } @@ -61,9 +79,9 @@ public void testEncode() throws Exception { Map parameters = new HashMap<>(); parameters.put("p", "ab%% %cd%"); parameters.put("q", "ab%% %cd%"); - Assert.assertEquals("/path/ab%25%25%20%25cd%25?q=ab%25%25+%25cd%25", + Assertions.assertEquals("/path/ab%25%25%20%25cd%25?q=ab%25%25+%25cd%25", urlPathBuilder.createRequestPath(parameters)); - Assert.assertEquals("/path/ab%25%25%20%25cd%25", + Assertions.assertEquals("/path/ab%25%25%20%25cd%25", urlPathBuilder.createPathString(parameters)); } @@ -77,19 +95,19 @@ public void testMultiQuery() throws Exception { Map parameters = new HashMap<>(); parameters.put("strArr", new Object[] {"a", "b", "c"}); parameters.put("intArr", new Object[] {1, 2, 3}); - Assert.assertEquals("/path?strArr=a&strArr=b&strArr=c&intArr=1&intArr=2&intArr=3", + Assertions.assertEquals("/path?strArr=a&strArr=b&strArr=c&intArr=1&intArr=2&intArr=3", urlPathBuilder.createRequestPath(parameters)); parameters.put("strArr", new Object[] {}); parameters.put("intArr", new Object[] {1, 2, 3}); - Assert.assertEquals("/path?intArr=1&intArr=2&intArr=3", + Assertions.assertEquals("/path?intArr=1&intArr=2&intArr=3", urlPathBuilder.createRequestPath(parameters)); parameters.put("strArr", new Object[] {"a", "b", "c"}); parameters.put("intArr", new Object[] {}); - Assert.assertEquals("/path?strArr=a&strArr=b&strArr=c", + Assertions.assertEquals("/path?strArr=a&strArr=b&strArr=c", urlPathBuilder.createRequestPath(parameters)); parameters.put("strArr", new Object[] {}); parameters.put("intArr", new Object[] {}); - Assert.assertEquals("/path", + Assertions.assertEquals("/path", urlPathBuilder.createRequestPath(parameters)); } @@ -107,9 +125,9 @@ public void testRegexPathParam() throws Exception { parameters.put("p1", "abcPath"); parameters.put("q0", 11); parameters.put("q1", "queryABC"); - Assert.assertEquals("/path/10/and/abcPath?q0=11&q1=queryABC", + Assertions.assertEquals("/path/10/and/abcPath?q0=11&q1=queryABC", urlPathBuilder.createRequestPath(parameters)); - Assert.assertEquals("/path/10/and/abcPath", + Assertions.assertEquals("/path/10/and/abcPath", urlPathBuilder.createPathString(parameters)); } @@ -117,7 +135,8 @@ private void addParam(String paramName, Type paramType, ParameterConstructor constructor, Map paramMap) { Parameter parameter = constructor.construct(); parameter.setName(paramName); - paramMap.put(paramName, new RestParam(parameter, paramType)); + parameter.setSchema(new Schema()); + paramMap.put(paramName, new RestParam(null, parameter, paramType)); } interface ParameterConstructor { diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathStringBuilderTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathStringBuilderTest.java index 2fc9a55aad5..5ccb4a7eff2 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathStringBuilderTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/definition/path/URLPathStringBuilderTest.java @@ -17,10 +17,9 @@ package org.apache.servicecomb.common.rest.definition.path; -import static org.junit.Assert.assertEquals; - import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder.URLPathStringBuilder; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class URLPathStringBuilderTest { @Test @@ -28,27 +27,27 @@ public void testNormal() { URLPathStringBuilder builder = new URLPathStringBuilder(); builder.appendPath("/path"); builder.appendQuery("q", "abc"); - assertEquals("/path?q=abc", builder.build()); + Assertions.assertEquals("/path?q=abc", builder.build()); } @Test public void appendPath() { URLPathStringBuilder builder = new URLPathStringBuilder(); builder.appendPath("/abc"); - assertEquals("/abc", builder.build()); + Assertions.assertEquals("/abc", builder.build()); builder.appendPath("/de fg"); - assertEquals("/abc/de fg", builder.build()); + Assertions.assertEquals("/abc/de fg", builder.build()); } @Test public void appendQuery() { URLPathStringBuilder builder = new URLPathStringBuilder(); - assertEquals("", builder.build()); + Assertions.assertEquals("", builder.build()); builder.appendQuery("ab", "cd"); - assertEquals("?ab=cd", builder.build()); + Assertions.assertEquals("?ab=cd", builder.build()); builder.appendQuery("ef", ""); - assertEquals("?ab=cd&ef=", builder.build()); + Assertions.assertEquals("?ab=cd&ef=", builder.build()); builder.appendQuery("gh", "jk"); - assertEquals("?ab=cd&ef=&gh=jk", builder.build()); + Assertions.assertEquals("?ab=cd&ef=&gh=jk", builder.build()); } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/HttpServerFilterBaseForTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/HttpServerFilterBaseForTest.java deleted file mode 100644 index 24ccd95a81d..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/HttpServerFilterBaseForTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.common.rest.filter; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.swagger.invocation.Response; - -public class HttpServerFilterBaseForTest implements HttpServerFilter { - @Override - public int getOrder() { - return 0; - } - - @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { - return null; - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java deleted file mode 100644 index 1ea467d4c24..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilter.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.common.rest.filter; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestHttpServerFilter { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void asyncSucc() throws InterruptedException, ExecutionException { - HttpServerFilter filter = new HttpServerFilterBaseForTest(); - - CompletableFuture future = filter.beforeSendResponseAsync(null, null); - Assert.assertNull(future.get()); - } - - @Test - public void asyncFailed() throws InterruptedException, ExecutionException { - HttpServerFilter filter = new HttpServerFilterBaseForTest() { - @Override - public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) { - throw new RuntimeExceptionWithoutStackTrace(); - } - }; - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.instanceOf(RuntimeExceptionWithoutStackTrace.class)); - - CompletableFuture future = filter.beforeSendResponseAsync(null, null); - future.get(); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilterBeforeSendResponseExecutor.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilterBeforeSendResponseExecutor.java deleted file mode 100644 index c8754ac1ae5..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/TestHttpServerFilterBeforeSendResponseExecutor.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.common.rest.filter; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import mockit.Mocked; - -public class TestHttpServerFilterBeforeSendResponseExecutor { - @Mocked - Invocation invocation; - - @Mocked - HttpServletResponseEx responseEx; - - List httpServerFilters = new ArrayList<>(); - - HttpServerFilterBeforeSendResponseExecutor executor = - new HttpServerFilterBeforeSendResponseExecutor(httpServerFilters, invocation, responseEx); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setup() { - httpServerFilters.add(new HttpServerFilterBaseForTest()); - } - - @Test - public void runSucc() throws InterruptedException, ExecutionException { - CompletableFuture result = executor.run(); - - Assert.assertNull(result.get()); - } - - @Test - public void runFail() throws InterruptedException, ExecutionException { - httpServerFilters.add(new HttpServerFilterBaseForTest() { - @Override - public CompletableFuture beforeSendResponseAsync(Invocation invocation, HttpServletResponseEx responseEx) { - throw new RuntimeExceptionWithoutStackTrace(); - } - }); - - CompletableFuture result = executor.run(); - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.instanceOf(RuntimeExceptionWithoutStackTrace.class)); - - result.get(); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java index 24942a076cb..0decec28bd9 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilterTest.java @@ -19,150 +19,170 @@ import static com.google.common.net.HttpHeaders.CONTENT_LENGTH; import static com.google.common.net.HttpHeaders.TRANSFER_ENCODING; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static org.assertj.core.api.Assertions.assertThat; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; -import java.util.ArrayList; -import java.util.List; +import java.io.ByteArrayInputStream; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import org.apache.servicecomb.common.rest.HttpTransportContext; import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.config.ConfigUtil; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.SCBStatus; import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.apache.servicecomb.core.definition.InvocationRuntimeType; +import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.core.filter.AbstractFilter; import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.core.invocation.InvocationFactory; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.foundation.common.part.InputStreamPart; import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; +import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.Content; +import io.swagger.v3.oas.models.media.StringSchema; +import io.swagger.v3.oas.models.responses.ApiResponse; +import io.swagger.v3.oas.models.responses.ApiResponses; import io.vertx.core.MultiMap; -import io.vertx.core.json.Json; -import mockit.Expectations; -import mockit.Mocked; -import mockit.Verifications; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.MediaType; public class RestServerCodecFilterTest { - RestServerCodecFilter codecFilter = new RestServerCodecFilter(); + final RestServerCodecFilter codecFilter = new RestServerCodecFilter(); Invocation invocation; - @Mocked - Endpoint endpoint; + final Endpoint endpoint = Mockito.mock(Endpoint.class); + + final OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + + final SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); + + final MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); + + final InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); - @Mocked - OperationMeta operationMeta; + final RestOperationMeta restOperationMeta = Mockito.mock(RestOperationMeta.class); - @Mocked - RestOperationMeta restOperationMeta; + final HttpTransportContext transportContext = Mockito.mock(HttpTransportContext.class); - @Mocked - HttpTransportContext transportContext; + final HttpServletResponseEx responseEx = Mockito.mock(HttpServletResponseEx.class); - @Mocked - HttpServletResponseEx responseEx; + final MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - MultiMap headers = MultiMap.caseInsensitiveMultiMap(); + final Part part = new InputStreamPart("ok", new ByteArrayInputStream(new byte[] {1, 2})); - FilterNode nextNode = new FilterNode((invocation, next) -> { - Response response = Response.ok("ok"); - response.setHeaders(headers); - return CompletableFuture.completedFuture(response); + final FilterNode nextNode = new FilterNode(new AbstractFilter() { + @Override + public String getName() { + return "f2"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + Response response = Response.ok(part); + response.setHeaders(headers); + return CompletableFuture.completedFuture(response); + } }); static SCBEngine engine; - @BeforeClass + @BeforeAll public static void beforeClass() { - ArchaiusUtils.resetConfig(); - ConfigUtil.installDynamicConfig(); - - engine = SCBBootstrap.createSCBEngineForTest(); + Environment environment = Mockito.mock(Environment.class); + engine = SCBBootstrap.createSCBEngineForTest(environment); + engine.setEnvironment(environment); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); engine.setStatus(SCBStatus.UP); } - @AfterClass + @AfterAll public static void afterClass() { engine.destroy(); - ArchaiusUtils.resetConfig(); } - @Before + @BeforeEach public void setUp() { - invocation = InvocationFactory.forProvider(endpoint, operationMeta, null); + Mockito.when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Mockito.when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + Mockito.when(operationMeta.buildBaseProviderRuntimeType()).thenReturn(invocationRuntimeType); + invocation = Mockito.spy(InvocationFactory.forProvider(endpoint, operationMeta, null)); + Mockito.when(responseEx.sendPart(part)).thenReturn(CompletableFuture.completedFuture(null)); } private void mockDecodeRequestFail() { - new Expectations(invocation) { - { - invocation.getTransportContext(); - result = transportContext; - - invocation.getRequestEx(); - result = new RuntimeExceptionWithoutStackTrace("mock encode request failed"); - } - }; + Mockito.when(invocation.getTransportContext()).thenReturn(transportContext); + Mockito.when(transportContext.getResponseEx()).thenReturn(responseEx); + Mockito.when(invocation.getRequestEx()) + .thenThrow(new RuntimeExceptionWithoutStackTrace("mock encode request failed")); } @Test - public void should_not_invoke_filter_when_decode_request_failed(@Mocked FilterNode nextNode) { + public void should_not_invoke_filter_when_decode_request_failed() { + FilterNode nextNode = Mockito.mock(FilterNode.class); mockDecodeRequestFail(); codecFilter.onFilter(invocation, nextNode); - new Verifications() { - { - nextNode.onFilter(invocation); - times = 0; - } - }; + Mockito.verify(nextNode, Mockito.times(0)).onFilter(invocation); } @Test public void should_convert_exception_to_response_when_decode_request_failed() throws ExecutionException, InterruptedException { mockDecodeRequestFail(); - new Expectations(invocation) { - { - invocation.findResponseType(anyInt); - result = TypeFactory.defaultInstance().constructType(String.class); - } - }; - - Response response = codecFilter.onFilter(invocation, nextNode).get(); - - assertThat(response.getStatus()).isEqualTo(INTERNAL_SERVER_ERROR); - assertThat(Json.encode(response.getResult())) - .isEqualTo("{\"code\":\"SCB.50000000\",\"message\":\"mock encode request failed\"}"); + Mockito.when(invocation.findResponseType(INTERNAL_SERVER_ERROR.getStatusCode())) + .thenReturn(TypeFactory.defaultInstance().constructType(String.class)); + + Assertions.assertThrows(ExecutionException.class, + () -> codecFilter.onFilter(invocation, nextNode).get()); } private void success_invocation() throws InterruptedException, ExecutionException { - new Expectations(invocation) { - { - invocation.getTransportContext(); - result = transportContext; - - operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - result = restOperationMeta; - - invocation.findResponseType(anyInt); - result = TypeFactory.defaultInstance().constructType(String.class); - } - }; + Mockito.when(invocation.getTransportContext()).thenReturn(transportContext); + HttpServletRequestEx requestExt = Mockito.mock(HttpServletRequestEx.class); + Mockito.when(invocation.getRequestEx()).thenReturn(requestExt); + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Operation swaggerOperation = Mockito.mock(Operation.class); + Mockito.when(operationMeta.getSwaggerOperation()).thenReturn(swaggerOperation); + ApiResponses apiResponses = Mockito.mock(ApiResponses.class); + Mockito.when(swaggerOperation.getResponses()).thenReturn(apiResponses); + ApiResponse apiResponse = Mockito.mock(ApiResponse.class); + Mockito.when(apiResponses.get("200")).thenReturn(apiResponse); + Content content = new Content(); + content.addMediaType(MediaType.APPLICATION_JSON, new io.swagger.v3.oas.models.media.MediaType()); + content.get(MediaType.APPLICATION_JSON).setSchema(new StringSchema()); + Mockito.when(apiResponse.getContent()).thenReturn(content); + Mockito.when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(restOperationMeta); + Mockito.when(invocation.findResponseType(INTERNAL_SERVER_ERROR.getStatusCode())) + .thenReturn(TypeFactory.defaultInstance().constructType(String.class)); + JavaType javaType = Mockito.mock(JavaType.class); + Mockito.when(invocationRuntimeType.findResponseType(200)).thenReturn(javaType); + Mockito.when(javaType.getRawClass()).thenAnswer(invocationOnMock -> Part.class); + Mockito.when(invocation.getTransportContext()).thenReturn(transportContext); + Mockito.when(transportContext.getResponseEx()).thenReturn(responseEx); codecFilter.onFilter(invocation, nextNode).get(); } @@ -172,15 +192,7 @@ public void should_encode_response_header() throws ExecutionException, Interrupt headers.add("h1", "v1"); success_invocation(); - new Verifications() { - { - String name; - String value; - responseEx.addHeader(name = withCapture(), value = withCapture()); - assertThat(name).isEqualTo("h1"); - assertThat(value).isEqualTo("v1"); - } - }; + Mockito.verify(responseEx).addHeader("h1", "v1"); } @Test @@ -190,15 +202,8 @@ public void should_not_encode_content_length_header() throws ExecutionException, .add(CONTENT_LENGTH, "10"); success_invocation(); - new Verifications() { - { - List names = new ArrayList<>(); - List values = new ArrayList<>(); - responseEx.addHeader(withCapture(names), withCapture(values)); - assertThat(names).containsExactly("h1", "h2"); - assertThat(values).containsExactly("v1", "v2"); - } - }; + Mockito.verify(responseEx, Mockito.times(1)).addHeader("h1", "v1"); + Mockito.verify(responseEx, Mockito.times(1)).addHeader("h2", "v2"); } @Test @@ -208,14 +213,7 @@ public void should_not_encode_transfer_encoding_header() throws ExecutionExcepti .add(TRANSFER_ENCODING, "test"); success_invocation(); - new Verifications() { - { - List names = new ArrayList<>(); - List values = new ArrayList<>(); - responseEx.addHeader(withCapture(names), withCapture(values)); - assertThat(names).containsExactly("h1", "h2"); - assertThat(values).containsExactly("v1", "v2"); - } - }; + Mockito.verify(responseEx, Mockito.times(1)).addHeader("h1", "v1"); + Mockito.verify(responseEx, Mockito.times(1)).addHeader("h2", "v2"); } -} \ No newline at end of file +} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/TestServerRestArgsFilter.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/TestServerRestArgsFilter.java deleted file mode 100644 index 47a7f87f607..00000000000 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/filter/inner/TestServerRestArgsFilter.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.common.rest.filter.inner; - -import java.util.concurrent.CompletableFuture; - -import javax.servlet.http.Part; - -import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.common.rest.definition.RestMetaUtils; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.response.ResponsesMeta; -import org.junit.Assert; -import org.junit.Test; - -import com.fasterxml.jackson.databind.type.TypeFactory; - -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestServerRestArgsFilter { - @Mocked - Invocation invocation; - - @Mocked - HttpServletResponseEx responseEx; - - @Mocked - Response response; - - @Mocked - Part part; - - @Mocked - OperationMeta operationMeta; - - boolean invokedSendPart; - - ServerRestArgsFilter filter = new ServerRestArgsFilter(); - - @Test - public void asyncBeforeSendResponse_part(@Mocked RestOperationMeta restOperationMeta) { - ResponsesMeta responsesMeta = new ResponsesMeta(); - responsesMeta.getResponseMap().put(202, RestObjectMapperFactory.getRestObjectMapper().constructType(Part.class)); - new Expectations(RestMetaUtils.class) { - { - responseEx.getAttribute(RestConst.INVOCATION_HANDLER_RESPONSE); - result = response; - response.getResult(); - result = part; - response.getStatusCode(); - result = 202; - invocation.findResponseType(202); - result = TypeFactory.defaultInstance().constructType(Part.class); - } - }; - new MockUp(responseEx) { - @Mock - CompletableFuture sendPart(Part body) { - invokedSendPart = true; - return null; - } - }; - - Assert.assertNull(filter.beforeSendResponseAsync(invocation, responseEx)); - Assert.assertTrue(invokedSendPart); - } -} diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestMicroservicePaths.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestMicroservicePaths.java index f8921a664e2..d99fb3b04f1 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestMicroservicePaths.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestMicroservicePaths.java @@ -17,98 +17,93 @@ package org.apache.servicecomb.common.rest.locator; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.servicecomb.common.rest.RestEngineSchemaListener; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.apache.servicecomb.core.executor.ExecutorManager; +import org.apache.servicecomb.core.transport.TransportManager; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mocked; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestMicroservicePaths { - static SCBEngine scbEngine; - - static MicroservicePaths paths; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @BeforeClass - public static void setup() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest() - .addProducerMeta("sid1", new TestPathSchema()) + SCBEngine scbEngine; + + MicroservicePaths paths; + + @BeforeEach + public void setup() { + Environment environment = Mockito.mock(Environment.class); + scbEngine = SCBBootstrap.createSCBEngineForTest(environment); + + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)) + .thenReturn(BootStrapProperties.DEFAULT_APPLICATION); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_NAME); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_ENVIRONMENT)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_ENVIRONMENT); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + List listeners = new ArrayList<>(); + listeners.add(new RestEngineSchemaListener()); + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + TransportManager transportManager = Mockito.mock(TransportManager.class); + scbEngine.setTransportManager(transportManager); + scbEngine.setExecutorManager(executorManager); + scbEngine.setBootListeners(listeners); + scbEngine.addProducerMeta("sid1", new TestPathSchema()) .run(); ServicePathManager spm = ServicePathManager.getServicePathManager(scbEngine.getProducerMicroserviceMeta()); - paths = Deencapsulation.getField(spm, "producerPaths"); + paths = spm.producerPaths; } - @AfterClass - public static void teardown() { + @AfterEach + public void teardown() { scbEngine.destroy(); - ArchaiusUtils.resetConfig(); } @Test public void staticGroup() { RestOperationMeta meta = paths.getStaticPathOperationMap().get("/static/").findValue("POST"); - Assert.assertSame("postStatic", meta.getOperationMeta().getOperationId()); + Assertions.assertSame("postStatic", meta.getOperationMeta().getOperationId()); meta = paths.getStaticPathOperationMap().get("/static/").findValue("GET"); - Assert.assertSame("getStatic", meta.getOperationMeta().getOperationId()); + Assertions.assertSame("getStatic", meta.getOperationMeta().getOperationId()); } @Test - public void testAddResourceStaticDuplicatedHttpMethod(@Mocked RestOperationMeta staticResPost) { - new Expectations() { - { - staticResPost.getHttpMethod(); - result = "POST"; - staticResPost.getAbsolutePath(); - result = "/static/"; - staticResPost.isAbsoluteStaticPath(); - result = true; - } - }; - - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage("operation with url /static/, method POST is duplicated."); - - paths.addResource(staticResPost); + public void testAddResourceStaticDuplicatedHttpMethod() { + RestOperationMeta staticResPost = Mockito.mock(RestOperationMeta.class); + Mockito.when(staticResPost.getHttpMethod()).thenReturn("POST"); + Mockito.when(staticResPost.getAbsolutePath()).thenReturn("/static/"); + Mockito.when(staticResPost.isAbsoluteStaticPath()).thenReturn(true); + + ServiceCombException exception = Assertions.assertThrows(ServiceCombException.class, + () -> paths.addResource(staticResPost)); + Assertions.assertEquals("operation with url /static/, method POST is duplicated.", exception.getMessage()); } @Test public void dynamicPath() { - Assert.assertEquals("dynamicExId", paths.getDynamicPathOperationList().get(0).getOperationMeta().getOperationId()); - Assert.assertEquals("dynamicId", paths.getDynamicPathOperationList().get(1).getOperationMeta().getOperationId()); - } - - @Test - public void testPrintPaths() { - try (LogCollector collector = new LogCollector()) { - paths.printPaths(); - - StringBuilder sb = new StringBuilder(); - collector.getEvents().stream() - .forEach(e -> sb.append(e.getMessage()).append("\n")); - Assert.assertEquals( - "Swagger mapped \"{[/static/], method=[POST], produces=[application/json]}\" onto public void org.apache.servicecomb.common.rest.locator.TestPathSchema.postStatic()\n" - + "Swagger mapped \"{[/static/], method=[GET], produces=[application/json]}\" onto public void org.apache.servicecomb.common.rest.locator.TestPathSchema.getStatic()\n" - + "Swagger mapped \"{[/staticEx/], method=[GET], produces=[application/json]}\" onto public void org.apache.servicecomb.common.rest.locator.TestPathSchema.getStaticEx()\n" - + "Swagger mapped \"{[/dynamicEx/{id}/], method=[GET], produces=[application/json]}\" onto public void org.apache.servicecomb.common.rest.locator.TestPathSchema.dynamicExId(java.lang.String)\n" - + "Swagger mapped \"{[/dynamic/{id}/], method=[GET], produces=[application/json]}\" onto public void org.apache.servicecomb.common.rest.locator.TestPathSchema.dynamicId(java.lang.String)\n", - sb.toString()); - } + Assertions.assertEquals("dynamicExId", + paths.getDynamicPathOperationList().get(0).getOperationMeta().getOperationId()); + Assertions.assertEquals("dynamicId", + paths.getDynamicPathOperationList().get(1).getOperationMeta().getOperationId()); } } diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestPathSchema.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestPathSchema.java index 66e7f4a8a66..b0de6caf78b 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestPathSchema.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestPathSchema.java @@ -16,10 +16,10 @@ */ package org.apache.servicecomb.common.rest.locator; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; @Path("/") public class TestPathSchema { diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestServicePathManager.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestServicePathManager.java index 99ec24a191d..84ae22015ae 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestServicePathManager.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/locator/TestServicePathManager.java @@ -17,37 +17,73 @@ package org.apache.servicecomb.common.rest.locator; -import org.apache.servicecomb.config.ConfigUtil; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.servicecomb.common.rest.RestEngineSchemaListener; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.apache.servicecomb.core.executor.ExecutorManager; +import org.apache.servicecomb.core.transport.TransportManager; import org.apache.servicecomb.foundation.common.utils.ClassLoaderScopeContext; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestServicePathManager { - @Before + SCBEngine scbEngine; + + Environment environment; + + @BeforeEach public void setUp() { - ConfigUtil.installDynamicConfig(); + environment = Mockito.mock(Environment.class); + scbEngine = SCBBootstrap.createSCBEngineForTest(environment); + + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty("servicecomb.rest.parameter.decodeAsObject", boolean.class, false)) + .thenReturn(false); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)) + .thenReturn(BootStrapProperties.DEFAULT_APPLICATION); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_NAME); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_ENVIRONMENT)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_ENVIRONMENT); } - @After + @AfterEach public void tearDown() { - ArchaiusUtils.resetConfig(); + scbEngine.destroy(); ClassLoaderScopeContext.clearClassLoaderScopeProperty(); } @Test public void testBuildProducerPathsNoPrefix() { - SCBEngine scbEngine = SCBBootstrap.createSCBEngineForTest() - .addProducerMeta("sid1", new TestPathSchema()) + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + TransportManager transportManager = Mockito.mock(TransportManager.class); + scbEngine.setTransportManager(transportManager); + scbEngine.setExecutorManager(executorManager); + List listeners = new ArrayList<>(); + listeners.add(new RestEngineSchemaListener()); + scbEngine.setBootListeners(listeners); + scbEngine.addProducerMeta("sid1", new TestPathSchema()) .run(); + ServicePathManager spm = ServicePathManager.getServicePathManager(scbEngine.getProducerMicroserviceMeta()); - Assert.assertSame(spm.producerPaths, spm.swaggerPaths); + Assertions.assertSame(spm.producerPaths, spm.swaggerPaths); scbEngine.destroy(); } @@ -56,9 +92,20 @@ public void testBuildProducerPathsNoPrefix() { public void testBuildProducerPathsHasPrefix() { ClassLoaderScopeContext.setClassLoaderScopeProperty(DefinitionConst.URL_PREFIX, "/root/rest"); - SCBEngine scbEngine = SCBBootstrap.createSCBEngineForTest() - .addProducerMeta("sid1", new TestPathSchema()) + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty(DefinitionConst.REGISTER_URL_PREFIX, boolean.class, false)).thenReturn(false); + + ExecutorManager executorManager = Mockito.mock(ExecutorManager.class); + TransportManager transportManager = Mockito.mock(TransportManager.class); + scbEngine.setTransportManager(transportManager); + scbEngine.setExecutorManager(executorManager); + List listeners = new ArrayList<>(); + listeners.add(new RestEngineSchemaListener()); + scbEngine.setBootListeners(listeners); + scbEngine.addProducerMeta("sid1", new TestPathSchema()) .run(); + ServicePathManager spm = ServicePathManager.getServicePathManager(scbEngine.getProducerMicroserviceMeta()); // all locate should be success diff --git a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/resource/TestClassPathStaticResourceHandler.java b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/resource/TestClassPathStaticResourceHandler.java index 7005eaabac1..f95468f4f38 100644 --- a/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/resource/TestClassPathStaticResourceHandler.java +++ b/common/common-rest/src/test/java/org/apache/servicecomb/common/rest/resource/TestClassPathStaticResourceHandler.java @@ -20,26 +20,25 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.Status; - import org.apache.commons.io.IOUtils; import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; -import mockit.Expectations; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response.Status; public class TestClassPathStaticResourceHandler { static ClassPathStaticResourceHandler handler = new ClassPathStaticResourceHandler(); - @BeforeClass + @BeforeAll public static void setup() { handler.setWebRoot("web-root/"); } @@ -50,11 +49,11 @@ public void normal() throws IOException { Part part = response.getResult(); try (InputStream is = part.getInputStream()) { - Assert.assertTrue(IOUtils.toString(is, StandardCharsets.UTF_8).endsWith("")); + Assertions.assertTrue(IOUtils.toString(is, StandardCharsets.UTF_8).trim().endsWith("")); } - Assert.assertEquals("text/html", part.getContentType()); - Assert.assertEquals("text/html", response.getHeader(HttpHeaders.CONTENT_TYPE)); - Assert.assertEquals("inline", response.getHeader(HttpHeaders.CONTENT_DISPOSITION)); + Assertions.assertEquals("text/html", part.getContentType()); + Assertions.assertEquals("text/html", response.getHeader(HttpHeaders.CONTENT_TYPE)); + Assertions.assertEquals("inline", response.getHeader(HttpHeaders.CONTENT_DISPOSITION)); } @Test @@ -62,11 +61,11 @@ public void notExist() { Response response = handler.handle("notExist.html"); InvocationException invocationException = response.getResult(); - Assert.assertEquals(Status.NOT_FOUND, invocationException.getStatus()); - Assert.assertEquals(Status.NOT_FOUND.getReasonPhrase(), + Assertions.assertEquals(Status.NOT_FOUND, invocationException.getStatus()); + Assertions.assertEquals(Status.NOT_FOUND.getReasonPhrase(), ((CommonExceptionData) invocationException.getErrorData()).getMessage()); - Assert.assertEquals(404, response.getStatusCode()); - Assert.assertEquals("Not Found", response.getReasonPhrase()); + Assertions.assertEquals(404, response.getStatusCode()); + Assertions.assertEquals("Not Found", response.getReasonPhrase()); } @Test @@ -74,34 +73,31 @@ public void attack() { Response response = handler.handle("../microservice.yaml"); InvocationException invocationException = response.getResult(); - Assert.assertEquals(Status.NOT_FOUND, invocationException.getStatus()); - Assert.assertEquals(Status.NOT_FOUND.getReasonPhrase(), + Assertions.assertEquals(Status.NOT_FOUND, invocationException.getStatus()); + Assertions.assertEquals(Status.NOT_FOUND.getReasonPhrase(), ((CommonExceptionData) invocationException.getErrorData()).getMessage()); - Assert.assertEquals(404, response.getStatusCode()); - Assert.assertEquals("Not Found", response.getReasonPhrase()); + Assertions.assertEquals(404, response.getStatusCode()); + Assertions.assertEquals("Not Found", response.getReasonPhrase()); } @Test public void readContentFailed() throws IOException { - new Expectations(handler) { - { - handler.findResource(anyString); - result = new RuntimeExceptionWithoutStackTrace("read content failed."); - } - }; + handler = Mockito.spy(TestClassPathStaticResourceHandler.handler); + Mockito.when(handler.findResource("web-root/index.html")) + .thenThrow(new RuntimeExceptionWithoutStackTrace("read content failed.")); try (LogCollector logCollector = new LogCollector()) { Response response = handler.handle("index.html"); - Assert.assertEquals("failed to process static resource, path=web-root/index.html", - logCollector.getLastEvents().getMessage()); + Assertions.assertEquals("failed to process static resource, path=web-root/index.html", + logCollector.getLastEvents().getMessage().getFormattedMessage()); InvocationException invocationException = response.getResult(); - Assert.assertEquals(Status.INTERNAL_SERVER_ERROR, invocationException.getStatus()); - Assert.assertEquals("failed to process static resource.", + Assertions.assertEquals(Status.INTERNAL_SERVER_ERROR, invocationException.getStatus()); + Assertions.assertEquals("failed to process static resource.", ((CommonExceptionData) invocationException.getErrorData()).getMessage()); - Assert.assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode()); - Assert.assertEquals(Status.INTERNAL_SERVER_ERROR.getReasonPhrase(), response.getReasonPhrase()); + Assertions.assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode()); + Assertions.assertEquals(Status.INTERNAL_SERVER_ERROR.getReasonPhrase(), response.getReasonPhrase()); } } } diff --git a/common/common-rest/src/test/resources/log4j.properties b/common/common-rest/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/common/common-rest/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/common/common-rest/src/test/resources/log4j2.xml b/common/common-rest/src/test/resources/log4j2.xml new file mode 100644 index 00000000000..8cee07220ec --- /dev/null +++ b/common/common-rest/src/test/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/common/common-rest/src/test/resources/microservice.yaml b/common/common-rest/src/test/resources/microservice.yaml index 5f3131b943d..90fd8d97c8e 100644 --- a/common/common-rest/src/test/resources/microservice.yaml +++ b/common/common-rest/src/test/resources/microservice.yaml @@ -27,14 +27,3 @@ servicecomb: address: 0.0.0.0:8080 highway: address: 0.0.0.0:7070 - #executors: - #default: test - #Provider: - #server: test - #server.wrapParam: test - filter-chains: - consumer: - default: empty - producer: - default: empty - diff --git a/common/common-rest/src/test/resources/web-root/index.html b/common/common-rest/src/test/resources/web-root/index.html index 6aed06f6ed3..8fe33dc3cfa 100644 --- a/common/common-rest/src/test/resources/web-root/index.html +++ b/common/common-rest/src/test/resources/web-root/index.html @@ -14,4 +14,4 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - \ No newline at end of file + diff --git a/common/pom.xml b/common/pom.xml index 92b08df166a..c39c89ff4ce 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -21,14 +21,13 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default common Java Chassis::Common pom - common-protobuf common-rest common-access-log diff --git a/core/pom.xml b/core/pom.xml index dd7e768f3ba..af73c36dff9 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -21,17 +21,13 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default java-chassis-core Java Chassis::Core - - org.apache.servicecomb - deployment - org.apache.servicecomb foundation-vertx @@ -44,6 +40,10 @@ org.apache.servicecomb swagger-invocation-core + + org.apache.servicecomb + swagger-generator-core + io.zipkin.brave brave @@ -52,40 +52,39 @@ org.hibernate.validator hibernate-validator - - org.jmockit - jmockit - provided + org.apache.servicecomb + servicecomb-governance - org.mockito - mockito-core - provided + org.springframework.boot + spring-boot-autoconfigure - junit - junit + io.vertx + vertx-codegen provided + - org.slf4j - slf4j-log4j12 + org.apache.servicecomb + foundation-test-scaffolding test - log4j - log4j + org.apache.logging.log4j + log4j-slf4j-impl test - org.apache.servicecomb - foundation-test-scaffolding + org.apache.logging.log4j + log4j-core + test - io.vertx - vertx-codegen - provided + org.jmockit + jmockit + test diff --git a/core/src/main/java/org/apache/servicecomb/core/BootListener.java b/core/src/main/java/org/apache/servicecomb/core/BootListener.java index 174f24f1c1b..ea8314e2e1d 100644 --- a/core/src/main/java/org/apache/servicecomb/core/BootListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/BootListener.java @@ -17,10 +17,10 @@ package org.apache.servicecomb.core; -public interface BootListener { +import org.springframework.core.Ordered; + +public interface BootListener extends Ordered { enum EventType { - BEFORE_HANDLER, - AFTER_HANDLER, BEFORE_FILTER, AFTER_FILTER, BEFORE_PRODUCER_PROVIDER, @@ -67,18 +67,13 @@ public BootEvent setEventType(EventType eventType) { } } + @Override default int getOrder() { return 0; } default void onBootEvent(BootEvent event) { switch (event.eventType) { - case BEFORE_HANDLER: - onBeforeHandler(event); - return; - case AFTER_HANDLER: - onAfterHandler(event); - return; case BEFORE_FILTER: onBeforeFilter(event); return; @@ -120,14 +115,6 @@ default void onBootEvent(BootEvent event) { } } - default void onBeforeHandler(BootEvent event) { - - } - - default void onAfterHandler(BootEvent event) { - - } - default void onBeforeFilter(BootEvent event) { } diff --git a/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java b/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java deleted file mode 100644 index 4f495a215ac..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/ConfigurationSpringInitializer.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * 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.core; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.servicecomb.config.ConfigMapping; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.config.YAMLUtil; -import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader; -import org.apache.servicecomb.config.event.DynamicConfigurationChangedEvent; -import org.apache.servicecomb.config.event.RefreshGovernanceConfigurationEvent; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.apache.servicecomb.foundation.bootstrap.BootStrapService; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.EnvironmentAware; -import org.springframework.context.annotation.Conditional; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.Ordered; -import org.springframework.core.env.CompositePropertySource; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.EnumerablePropertySource; -import org.springframework.core.env.Environment; -import org.springframework.core.env.MapPropertySource; -import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.util.StringUtils; - -import com.google.common.eventbus.Subscribe; -import com.netflix.config.ConfigurationManager; -import com.netflix.config.WatchedUpdateResult; - -/** - * Adapt spring PropertySource and Archaius Configuration - * spring vs archaius - * (add) | dynamic(configcenter) - * system property | system property - * environment | environment - * *properties/*.yml | (add) - * (add) | microservice.yaml - * - * add dynamic configuration, microserive.yaml to spring, add *properties/*.yml to archaius - * - * NOTICE: we are not duplicate spring system property and environment property source, this will cause some problem - * related to precedence of a KEY-VAlUE. That is cse.test in dynamic config may not override servicecomb.test in yml. - * Users need to use the same key as what is in config file to override. - */ -public class ConfigurationSpringInitializer extends PropertySourcesPlaceholderConfigurer implements EnvironmentAware { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationSpringInitializer.class); - - public static final String EXTRA_CONFIG_SOURCE_PREFIX = "extraConfig-"; - - public static final String MICROSERVICE_PROPERTY_SOURCE_NAME = "microservice.yaml"; - - public static final String MAPPING_PROPERTY_SOURCE_NAME = "mapping.yaml"; - - public static final String EXTERNAL_INIT = "scb-config-external-init"; - - public static void setExternalInit(boolean value) { - System.setProperty(EXTERNAL_INIT, String.valueOf(value)); - } - - public static boolean isExternalInit() { - return Boolean.getBoolean(EXTERNAL_INIT); - } - - private final List bootStrapServices = SPIServiceUtils.getSortedService(BootStrapService.class); - - private final Map dynamicData = new ConcurrentHashMap<>(); - - private ConfigCenterConfigurationSource configCenterConfigurationSource; - - public ConfigurationSpringInitializer() { - setOrder(Ordered.LOWEST_PRECEDENCE / 2); - setIgnoreUnresolvablePlaceholders(true); - } - - /** - * Get configurations from Spring, merge them into the configurations of ServiceComb. - * @param environment From which to get the extra config. - */ - @Override - public void setEnvironment(Environment environment) { - super.setEnvironment(environment); - if (isExternalInit()) { - return; - } - - syncFromSpring(environment); - syncToSpring(environment); - - startupBootStrapService(environment); - - // watch configuration changes - EventManager.register(this); - configCenterConfigurationSource = ConfigUtil.installDynamicConfig(); - addDynamicConfigurationToSpring(environment, configCenterConfigurationSource); - } - - @Subscribe - public void onConfigurationDataChanged(DynamicConfigurationChangedEvent event) { - try { - WatchedUpdateResult data = event.getEvent(); - if (data.getDeleted() != null) { - data.getDeleted().forEach((k, v) -> dynamicData.remove(k)); - } - if (data.getAdded() != null) { - dynamicData.putAll(data.getAdded()); - } - if (data.getChanged() != null) { - dynamicData.putAll(data.getChanged()); - } - } catch (Exception e) { - LOGGER.error("", e); - } - EventManager.post(new RefreshGovernanceConfigurationEvent(event.getEvent())); - } - - private void syncFromSpring(Environment environment) { - String environmentName = generateNameForEnvironment(environment); - LOGGER.info("Environment received, will get configurations from [{}].", environmentName); - - Map extraConfig = getAllProperties(environment); - ConfigUtil.addExtraConfig(EXTRA_CONFIG_SOURCE_PREFIX + environmentName, extraConfig); - } - - public static void syncToSpring(Environment environment) { - if (isExternalInit()) { - return; - } - - addMicroserviceYAMLToSpring(environment); - addMappingToSpring(environment); - } - - private void startupBootStrapService(Environment environment) { - bootStrapServices.forEach(bootStrapService -> bootStrapService.startup(environment)); - } - - /** - * make springboot have a change to add microservice.yaml source earlier
- * to affect {@link Conditional} - * @param environment environment - */ - private static void addMicroserviceYAMLToSpring(Environment environment) { - if (!(environment instanceof ConfigurableEnvironment)) { - return; - } - - MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources(); - if (propertySources.contains(MICROSERVICE_PROPERTY_SOURCE_NAME)) { - return; - } - - propertySources.addLast(new EnumerablePropertySource(MICROSERVICE_PROPERTY_SOURCE_NAME) { - private final Map values = new HashMap<>(); - - private final String[] propertyNames; - - { - MicroserviceConfigLoader loader = new MicroserviceConfigLoader(); - loader.loadAndSort(); - - loader.getConfigModels() - .forEach(configModel -> values.putAll(YAMLUtil.retrieveItems("", configModel.getConfig()))); - - propertyNames = values.keySet().toArray(new String[values.size()]); - } - - @Override - public String[] getPropertyNames() { - return propertyNames; - } - - @SuppressWarnings("unchecked") - @Override - public Object getProperty(String name) { - Object value = this.values.get(name); - - // spring will not resolve nested placeholder of list, so try to fix the problem - if (value instanceof List) { - value = ((List) value).stream() - .filter(item -> item instanceof String) - .map(item -> environment.resolvePlaceholders((String) item)) - .collect(Collectors.toList()); - } - return value; - } - }); - } - - private static void addMappingToSpring(Environment environment) { - if (!(environment instanceof ConfigurableEnvironment)) { - return; - } - - MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources(); - if (propertySources.contains(MAPPING_PROPERTY_SOURCE_NAME)) { - return; - } - - Map mappings = ConfigMapping.getConvertedMap(environment); - propertySources.addFirst(new MapPropertySource(MAPPING_PROPERTY_SOURCE_NAME, mappings)); - } - - private void addDynamicConfigurationToSpring(Environment environment, - ConfigCenterConfigurationSource configCenterConfigurationSource) { - if (environment instanceof ConfigurableEnvironment) { - ConfigurableEnvironment ce = (ConfigurableEnvironment) environment; - if (configCenterConfigurationSource != null) { - try { - ce.getPropertySources() - .addFirst(new MapPropertySource("dynamic-source", dynamicData)); - } catch (Exception e) { - LOGGER.warn("set up spring property source failed. msg: {}", e.getMessage()); - } - } - } - } - - @Override - protected Properties mergeProperties() throws IOException { - Properties properties = super.mergeProperties(); - if (isExternalInit()) { - return properties; - } - - AbstractConfiguration config = ConfigurationManager.getConfigInstance(); - Iterator iterator = config.getKeys(); - while (iterator.hasNext()) { - String key = iterator.next(); - Object value = config.getProperty(key); - properties.put(key, value); - } - return properties; - } - - /** - * Try to get a name for identifying the environment. - * @param environment the target that the name is generated for. - * @return The generated name for the environment. - */ - private String generateNameForEnvironment(Environment environment) { - String environmentName = environment.getProperty("spring.config.name"); - if (!StringUtils.isEmpty(environmentName)) { - return environmentName; - } - - environmentName = environment.getProperty("spring.application.name"); - if (!StringUtils.isEmpty(environmentName)) { - return environmentName; - } - - return environment.getClass().getName() + "@" + environment.hashCode(); - } - - /** - * Traversal all {@link PropertySource} of {@link ConfigurableEnvironment}, and try to get all properties. - */ - private Map getAllProperties(Environment environment) { - Map configFromSpringBoot = new HashMap<>(); - - if (!(environment instanceof ConfigurableEnvironment)) { - return configFromSpringBoot; - } - - ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment; - - if (ignoreResolveFailure()) { - configurableEnvironment.setIgnoreUnresolvableNestedPlaceholders(true); - } - - for (PropertySource propertySource : configurableEnvironment.getPropertySources()) { - if (MICROSERVICE_PROPERTY_SOURCE_NAME.equals(propertySource.getName()) - || MAPPING_PROPERTY_SOURCE_NAME.equals(propertySource.getName())) { - continue; - } - getProperties(configurableEnvironment, propertySource, configFromSpringBoot); - } - return configFromSpringBoot; - } - - /** - * Get property names from {@link EnumerablePropertySource}, and get property value from {@link ConfigurableEnvironment#getProperty(String)} - */ - private void getProperties(ConfigurableEnvironment environment, PropertySource propertySource, - Map configFromSpringBoot) { - if (propertySource instanceof CompositePropertySource) { - // recursively get EnumerablePropertySource - CompositePropertySource compositePropertySource = (CompositePropertySource) propertySource; - compositePropertySource.getPropertySources().forEach(ps -> getProperties(environment, ps, configFromSpringBoot)); - return; - } - if (propertySource instanceof EnumerablePropertySource) { - EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource) propertySource; - for (String propertyName : enumerablePropertySource.getPropertyNames()) { - try { - configFromSpringBoot.put(propertyName, environment.getProperty(propertyName, Object.class)); - } catch (Exception e) { - throw new RuntimeException( - "set up spring property source failed.If you still want to start up the application and ignore errors, you can set servicecomb.config.ignoreResolveFailure to true.", - e); - } - } - return; - } - - LOGGER.debug("a none EnumerablePropertySource is ignored, propertySourceName = [{}]", propertySource.getName()); - } - - private boolean ignoreResolveFailure() { - return ConfigUtil - .createLocalConfig() - .getBoolean("servicecomb.config.ignoreResolveFailure", false); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/Const.java b/core/src/main/java/org/apache/servicecomb/core/Const.java deleted file mode 100644 index cd443339a36..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/Const.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.core; - -import org.apache.servicecomb.registry.definition.DefinitionConst; - -public final class Const { - private Const() { - } - - public static final String CSE_CONTEXT = "x-cse-context"; - - public static final String RESTFUL = "rest"; - - public static final String HIGHWAY = "highway"; - - public static final String ANY_TRANSPORT = ""; - - public static final String VERSION_RULE_LATEST = DefinitionConst.VERSION_RULE_LATEST; - - public static final String DEFAULT_VERSION_RULE = DefinitionConst.VERSION_RULE_ALL; - - public static final String PRODUCER_OPERATION = "producer-operation"; - - public static final String CONSUMER_OPERATION = "consumer-operation"; - - public static final String SRC_MICROSERVICE = "x-cse-src-microservice"; - - public static final String SRC_SERVICE_ID = "x-src-serviceId"; - - public static final String SRC_INSTANCE_ID = "x-src-instanceId"; - - public static final String TARGET_MICROSERVICE = "x-cse-target-microservice"; - - public static final String REMOTE_ADDRESS = "x-cse-remote-address"; - - public static final String AUTH_TOKEN = "x-cse-auth-rsatoken"; - - public static final String TRACE_ID_NAME = "X-B3-TraceId"; -} diff --git a/core/src/main/java/org/apache/servicecomb/core/ConsumerProvider.java b/core/src/main/java/org/apache/servicecomb/core/ConsumerProvider.java deleted file mode 100644 index b4b69a3cc51..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/ConsumerProvider.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.core; - -/** - * consumer端对业务的接口,不同场景是完全不同的 - * 所以这里只定义consumer对core的接口 - */ -public interface ConsumerProvider { - String getName(); - - void init(); -} diff --git a/core/src/main/java/org/apache/servicecomb/core/CoreConst.java b/core/src/main/java/org/apache/servicecomb/core/CoreConst.java new file mode 100644 index 00000000000..37c34b9c96d --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/CoreConst.java @@ -0,0 +1,66 @@ +/* + * 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.core; + +import org.apache.servicecomb.registry.definition.DefinitionConst; + +public final class CoreConst { + private CoreConst() { + } + + public static final String CSE_CONTEXT = "x-cse-context"; + + public static final String TRANSPORT_NAME = "x-transport-name"; + + public static final String RESTFUL = "rest"; + + public static final String HIGHWAY = "highway"; + + public static final String WEBSOCKET = "websocket"; + + public static final String ANY_TRANSPORT = ""; + + public static final String VERSION_RULE_LATEST = DefinitionConst.VERSION_RULE_LATEST; + + public static final String DEFAULT_VERSION_RULE = DefinitionConst.VERSION_RULE_ALL; + + public static final String PRODUCER_OPERATION = "producer-operation"; + + public static final String CONSUMER_OPERATION = "consumer-operation"; + + public static final String SRC_MICROSERVICE = "x-cse-src-microservice"; + + public static final String SRC_SERVICE_ID = "x-src-serviceId"; + + public static final String SRC_INSTANCE_ID = "x-src-instanceId"; + + public static final String TARGET_MICROSERVICE = "x-cse-target-microservice"; + + public static final String REMOTE_ADDRESS = "x-cse-remote-address"; + + public static final String AUTH_TOKEN = "x-cse-auth-rsatoken"; + + public static final String TRACE_ID_NAME = "X-B3-TraceId"; + + // controlling whether to print stack information with sensitive errors + public static final String PRINT_SENSITIVE_ERROR_MESSAGE = "servicecomb.error.printSensitiveErrorMessage"; + + public static final String SWAGGER_EXPORT_ENABLED = "servicecomb.swagger.export.enabled"; + + public static final String SWAGGER_DIRECTORY = "servicecomb.swagger.export.directory"; +} diff --git a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java deleted file mode 100644 index 4e50026fd00..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/CseApplicationListener.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.core; - -import org.apache.servicecomb.config.priority.PriorityPropertyManager; -import org.apache.servicecomb.core.filter.FilterChainsManager; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.RegistrationManager; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextClosedEvent; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.support.AbstractApplicationContext; -import org.springframework.core.Ordered; - -public class CseApplicationListener - implements ApplicationListener, Ordered, ApplicationContextAware { - private Class initEventClass = ContextRefreshedEvent.class; - - private ApplicationContext applicationContext; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if (this.applicationContext == applicationContext) { - // same object. avoid initialize many times. - return; - } - this.applicationContext = applicationContext; - BeanUtils.setContext(applicationContext); - HttpClients.load(); - RegistrationManager.INSTANCE.init(); - DiscoveryManager.INSTANCE.init(); - } - - public void setInitEventClass(Class initEventClass) { - this.initEventClass = initEventClass; - } - - @Override - public int getOrder() { - // should run before default listener, eg: ZuulConfiguration - return -1000; - } - - @Override - public void onApplicationEvent(ApplicationEvent event) { - if (initEventClass.isInstance(event)) { - if (applicationContext instanceof AbstractApplicationContext) { - ((AbstractApplicationContext) applicationContext).registerShutdownHook(); - } - - SCBEngine scbEngine = SCBEngine.getInstance(); - //SCBEngine init first, hence we do not need worry that when other beans need use the - //producer microserviceMeta, the SCBEngine is not inited. -// String serviceName = RegistryUtils.getMicroservice().getServiceName(); -// SCBEngine.getInstance().setProducerMicroserviceMeta(new MicroserviceMeta(serviceName).setConsumer(false)); -// SCBEngine.getInstance().setProducerProviderManager(applicationContext.getBean(ProducerProviderManager.class)); -// SCBEngine.getInstance().setConsumerProviderManager(applicationContext.getBean(ConsumerProviderManager.class)); -// SCBEngine.getInstance().setTransportManager(applicationContext.getBean(TransportManager.class)); - scbEngine.setApplicationContext(applicationContext); - scbEngine.setPriorityPropertyManager(applicationContext.getBean(PriorityPropertyManager.class)); - scbEngine.setFilterChainsManager(applicationContext.getBean(FilterChainsManager.class)); - scbEngine.getConsumerProviderManager().getConsumerProviderList() - .addAll(applicationContext.getBeansOfType(ConsumerProvider.class).values()); - scbEngine.getProducerProviderManager().getProducerProviderList() - .addAll(applicationContext.getBeansOfType(ProducerProvider.class).values()); - scbEngine.addBootListeners(applicationContext.getBeansOfType(BootListener.class).values()); - - scbEngine.run(); - } else if (event instanceof ContextClosedEvent) { - if (SCBEngine.getInstance() != null) { - SCBEngine.getInstance().destroy(); - } - } - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/Endpoint.java b/core/src/main/java/org/apache/servicecomb/core/Endpoint.java index 97ada4521c5..01f6f1129d5 100644 --- a/core/src/main/java/org/apache/servicecomb/core/Endpoint.java +++ b/core/src/main/java/org/apache/servicecomb/core/Endpoint.java @@ -17,35 +17,36 @@ package org.apache.servicecomb.core; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; /** - * Endpoint : 表示一个Endpoint。Transport识别其内部格式. + * Internal representation for microservice instance address. */ public class Endpoint { - // 格式:rest://192.168.1.1:8080 + // Registry address: http://192.168.1.1:8080 // see: http://www.ietf.org/rfc/rfc2396.txt private final String endpoint; private final Transport transport; - private final MicroserviceInstance instance; + private final DiscoveryInstance instance; - // 内部格式, 只有Transport能够认识 + // Internal address format recognized by Transport private final Object address; public Endpoint(Transport transport, String endpoint) { this(transport, endpoint, null); } - public Endpoint(Transport transport, String endpoint, MicroserviceInstance instance) { + public Endpoint(Transport transport, String endpoint, DiscoveryInstance instance) { this.transport = transport; this.endpoint = endpoint; this.instance = instance; this.address = transport.parseAddress(this.endpoint); } - public Endpoint(Transport transport, String endpoint, MicroserviceInstance instance, Object address) { + public Endpoint(Transport transport, String endpoint, StatefulDiscoveryInstance instance, Object address) { this.transport = transport; this.endpoint = endpoint; this.instance = instance; @@ -56,7 +57,7 @@ public String getEndpoint() { return endpoint; } - public MicroserviceInstance getMicroserviceInstance() { + public DiscoveryInstance getMicroserviceInstance() { return instance; } @@ -72,4 +73,17 @@ public Object getAddress() { public String toString() { return endpoint; } + + @Override + public boolean equals(Object o) { + if (o instanceof Endpoint) { + return this.endpoint.equals(((Endpoint) o).getEndpoint()); + } + return false; + } + + @Override + public int hashCode() { + return this.endpoint.hashCode(); + } } diff --git a/core/src/main/java/org/apache/servicecomb/core/Handler.java b/core/src/main/java/org/apache/servicecomb/core/Handler.java deleted file mode 100644 index b966963c25c..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/Handler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.core; - -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.InvocationType; - -// 每个微服务 + invocationType,都对应一个handler实例 -public interface Handler { - default void init(MicroserviceMeta microserviceMeta, InvocationType invocationType) { - } - - void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception; -} diff --git a/core/src/main/java/org/apache/servicecomb/core/Invocation.java b/core/src/main/java/org/apache/servicecomb/core/Invocation.java index 48e77474623..067fe6558f4 100644 --- a/core/src/main/java/org/apache/servicecomb/core/Invocation.java +++ b/core/src/main/java/org/apache/servicecomb/core/Invocation.java @@ -21,7 +21,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -33,13 +32,9 @@ import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.core.event.InvocationBusinessFinishEvent; -import org.apache.servicecomb.core.event.InvocationBusinessMethodFinishEvent; import org.apache.servicecomb.core.event.InvocationBusinessMethodStartEvent; import org.apache.servicecomb.core.event.InvocationEncodeResponseStartEvent; import org.apache.servicecomb.core.event.InvocationFinishEvent; -import org.apache.servicecomb.core.event.InvocationHandlersStartEvent; -import org.apache.servicecomb.core.event.InvocationRunInExecutorFinishEvent; -import org.apache.servicecomb.core.event.InvocationRunInExecutorStartEvent; import org.apache.servicecomb.core.event.InvocationStartEvent; import org.apache.servicecomb.core.event.InvocationStartSendRequestEvent; import org.apache.servicecomb.core.event.InvocationTimeoutCheckEvent; @@ -52,7 +47,6 @@ import org.apache.servicecomb.foundation.common.utils.AsyncUtils; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; import org.apache.servicecomb.swagger.invocation.InvocationType; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; @@ -84,30 +78,21 @@ static Collection loadTraceIdGenerators() { private Endpoint endpoint; // 只用于handler之间传递数据,是本地数据 - private Map handlerContext = localContext; - - // handler链,是arrayList,可以高效地通过index访问 - private List handlerList; - - private int handlerIndex; + private final Map handlerContext = localContext; // 应答的处理器 // 同步模式:避免应答在网络线程中处理解码等等业务级逻辑 private Executor responseExecutor; - private boolean sync = true; + private volatile boolean sync = true; - private InvocationStageTrace invocationStageTrace = new InvocationStageTrace(this); + private final InvocationStageTrace invocationStageTrace = new InvocationStageTrace(this); private HttpServletRequestEx requestEx; - private boolean finished; - - // not extend InvocationType - // because isEdge() only affect to apm/metrics output, no need to change so many logic - private boolean edge; + private volatile boolean finished; - private long invocationId; + private volatile long invocationId; private TraceIdLogger traceIdLogger; @@ -132,7 +117,7 @@ public Invocation(ReferenceConfig referenceConfig, OperationMeta operationMeta, } public Invocation(Endpoint endpoint, OperationMeta operationMeta, Map swaggerArguments) { - this.invocationType = InvocationType.PRODUCER; + this.invocationType = InvocationType.PROVIDER; this.invocationRuntimeType = operationMeta.buildBaseProviderRuntimeType(); this.endpoint = endpoint; init(operationMeta, swaggerArguments); @@ -143,11 +128,16 @@ private void init(OperationMeta operationMeta, Map swaggerArgume this.schemaMeta = operationMeta.getSchemaMeta(); this.operationMeta = operationMeta; this.setSwaggerArguments(swaggerArguments); - this.handlerList = getHandlerChain(); - handlerIndex = 0; traceIdLogger = new TraceIdLogger(this); } + public String getTransportName() { + if (endpoint == null || endpoint.getTransport() == null) { + return null; + } + return endpoint.getTransport().getName(); + } + public Transport getTransport() { if (endpoint == null) { throw new IllegalStateException( @@ -156,10 +146,6 @@ public Transport getTransport() { return endpoint.getTransport(); } - public List getHandlerChain() { - return schemaMeta.getMicroserviceMeta().getHandlerChain(); - } - public Executor getResponseExecutor() { return responseExecutor; } @@ -259,21 +245,6 @@ public Map getHandlerContext() { return handlerContext; } - public int getHandlerIndex() { - return handlerIndex; - } - - public void setHandlerIndex(int handlerIndex) { - this.handlerIndex = handlerIndex; - } - - public void next(AsyncResponse asyncResp) throws Exception { - // 不必判断有效性,因为整个流程都是内部控制的 - int runIndex = handlerIndex; - handlerIndex++; - handlerList.get(runIndex).handle(this, asyncResp); - } - public String getSchemaId() { return schemaMeta.getSchemaId(); } @@ -282,7 +253,22 @@ public String getOperationName() { return operationMeta.getOperationId(); } + public String getProviderTransportName() { + if (operationMeta.getSwaggerOperation().getExtensions() != null && + operationMeta.getSwaggerOperation().getExtensions().get(CoreConst.TRANSPORT_NAME) != null) { + return (String) operationMeta.getSwaggerOperation().getExtensions().get(CoreConst.TRANSPORT_NAME); + } + if (schemaMeta.getSwagger().getExtensions() != null && + schemaMeta.getSwagger().getExtensions().get(CoreConst.TRANSPORT_NAME) != null) { + return (String) schemaMeta.getSwagger().getExtensions().get(CoreConst.TRANSPORT_NAME); + } + return null; + } + public String getConfigTransportName() { + if (getProviderTransportName() != null) { + return getProviderTransportName(); + } return referenceConfig.getTransport(); } @@ -302,10 +288,6 @@ public MicroserviceMeta getMicroserviceMeta() { return schemaMeta.getMicroserviceMeta(); } - public String getMicroserviceVersionRule() { - return referenceConfig.getVersionRule(); - } - public InvocationRuntimeType getInvocationRuntimeType() { return this.invocationRuntimeType; } @@ -357,55 +339,37 @@ protected void initTraceId(TraceIdGenerator traceIdGenerator) { addContext(traceIdGenerator.getTraceIdKeyName(), traceIdGenerator.generate()); } - public void onStart(long start) { - invocationStageTrace.start(start); + public void onStart() { initTraceId(); EventManager.post(new InvocationStartEvent(this)); } - public void onStart(HttpServletRequestEx requestEx, long start) { + public void onStart(HttpServletRequestEx requestEx) { this.requestEx = requestEx; - onStart(start); - } - - public void onExecuteStart() { - invocationStageTrace.startExecution(); - EventManager.post(new InvocationRunInExecutorStartEvent(this)); - } - - public void onExecuteFinish() { - EventManager.post(new InvocationRunInExecutorFinishEvent(this)); - } - - public void onStartHandlersRequest() { - invocationStageTrace.startHandlersRequest(); - EventManager.post(new InvocationHandlersStartEvent(this)); + onStart(); } public void onStartSendRequest() { - invocationStageTrace.startSend(); EventManager.post(new InvocationStartSendRequestEvent(this)); } - @Override public void onBusinessMethodStart() { - invocationStageTrace.startBusinessMethod(); + invocationStageTrace.startBusinessExecute(); EventManager.post(new InvocationBusinessMethodStartEvent(this)); } - @Override - public void onBusinessMethodFinish() { - EventManager.post(new InvocationBusinessMethodFinishEvent(this)); - } - public void onEncodeResponseStart(Response response) { + invocationStageTrace.startProviderEncodeResponse(); EventManager.post(new InvocationEncodeResponseStartEvent(this, response)); } - @Override + public void onEncodeResponseFinish() { + invocationStageTrace.finishProviderEncodeResponse(); + } + public void onBusinessFinish() { - invocationStageTrace.finishBusiness(); + invocationStageTrace.finishBusinessExecute(); EventManager.post(new InvocationBusinessFinishEvent(this)); } @@ -415,9 +379,14 @@ public void onFinish(Response response) { return; } + finished = true; invocationStageTrace.finish(); EventManager.post(new InvocationFinishEvent(this, response)); - finished = true; + } + + // for retry, reset invocation and try it again + public void reset() { + finished = false; } public boolean isFinished() { @@ -437,19 +406,15 @@ public boolean isConsumer() { } public boolean isProducer() { - return InvocationType.PRODUCER.equals(invocationType); + return InvocationType.PROVIDER.equals(invocationType); } public boolean isEdge() { - return edge; + return InvocationType.EDGE.equals(invocationType); } - public void setEdge(boolean edge) { - this.edge = edge; - } - - public boolean isThirdPartyInvocation() { - return referenceConfig.is3rdPartyService(); + public void setEdge() { + this.invocationType = InvocationType.EDGE; } public long getInvocationId() { @@ -469,7 +434,7 @@ public InvocationStageTrace getInvocationStageTrace() { } public String getTraceId() { - return getContext(Const.TRACE_ID_NAME); + return getContext(CoreConst.TRACE_ID_NAME); } public String getTraceId(String traceIdName) { @@ -479,12 +444,25 @@ public String getTraceId(String traceIdName) { // ensure sync consumer invocation response flow not run in eventLoop public CompletableFuture optimizeSyncConsumerThread(CompletableFuture future) { if (sync && !InvokerUtils.isInEventLoop()) { - AsyncUtils.waitQuietly(future); + return AsyncUtils.tryCatchSupplier(() -> InvokerUtils.toSync(future, getWaitTime())); } return future; } + public long getWaitTime() { + if (getOperationMeta().getConfig().getMsInvocationTimeout() > 0) { + // if invocation timeout configured, use it. + return getOperationMeta().getConfig().getMsInvocationTimeout(); + } + + // In invocation handlers, may call other microservices, invocation + // timeout may be much longer than request timeout. + // But this is quite rare, for simplicity, default two times of request timeout. + // If users need longer timeout, can configure invocation timeout. + return getOperationMeta().getConfig().getMsRequestTimeout() * 2; + } + /** * Check if invocation is timeout. * diff --git a/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java b/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java index 785c90c93b3..e7f903e7552 100644 --- a/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java +++ b/core/src/main/java/org/apache/servicecomb/core/NonSwaggerInvocation.java @@ -17,32 +17,24 @@ package org.apache.servicecomb.core; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; - public class NonSwaggerInvocation extends Invocation { - private String appId; - - private String microserviceName; - - private String versionRule; + private final String appId; - private Handler nextHandler; + private final String microserviceName; - public NonSwaggerInvocation(String appId, String microserviceName, String versionRule, Handler nextHandler) { + public NonSwaggerInvocation(String appId, String microserviceName) { this.appId = appId; this.microserviceName = microserviceName; - this.versionRule = versionRule; - this.nextHandler = nextHandler; } @Override public String getSchemaId() { - throw new UnsupportedOperationException(); + return "third-schema"; } @Override public String getOperationName() { - throw new UnsupportedOperationException(); + return "third-operation"; } @Override @@ -52,7 +44,7 @@ public String getInvocationQualifiedName() { @Override public String getConfigTransportName() { - return Const.RESTFUL; + return CoreConst.RESTFUL; } @Override @@ -64,14 +56,4 @@ public String getMicroserviceName() { public String getAppId() { return appId; } - - @Override - public String getMicroserviceVersionRule() { - return versionRule; - } - - @Override - public void next(AsyncResponse asyncResp) throws Exception { - nextHandler.handle(this, asyncResp); - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBApplicationListener.java b/core/src/main/java/org/apache/servicecomb/core/SCBApplicationListener.java new file mode 100644 index 00000000000..3bd5bd5d8f7 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/SCBApplicationListener.java @@ -0,0 +1,93 @@ +/* + * 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.core; + +import org.apache.servicecomb.config.priority.PriorityPropertyManager; +import org.apache.servicecomb.core.filter.FilterChainsManager; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.core.Ordered; +import org.springframework.core.env.Environment; + +public class SCBApplicationListener + implements ApplicationListener, Ordered, ApplicationContextAware, EnvironmentAware { + private Class initEventClass = ContextRefreshedEvent.class; + + private ApplicationContext applicationContext; + + private final SCBEngine scbEngine; + + public SCBApplicationListener(SCBEngine scbEngine) { + this.scbEngine = scbEngine; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (this.applicationContext == applicationContext) { + // same object. avoid initialize many times. + return; + } + this.applicationContext = applicationContext; + BeanUtils.setContext(applicationContext); + HttpClients.load(); + } + + @Override + public void setEnvironment(Environment environment) { + scbEngine.init(); + } + + public void setInitEventClass(Class initEventClass) { + this.initEventClass = initEventClass; + } + + @Override + public int getOrder() { + // should run before default listener, eg: ZuulConfiguration + return -1000; + } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (initEventClass.isInstance(event)) { + if (applicationContext instanceof AbstractApplicationContext) { + ((AbstractApplicationContext) applicationContext).registerShutdownHook(); + } + + scbEngine.setPriorityPropertyManager(applicationContext.getBean(PriorityPropertyManager.class)); + scbEngine.setFilterChainsManager(applicationContext.getBean(FilterChainsManager.class)); + scbEngine.getProducerProviderManager().getProducerProviderList() + .addAll(applicationContext.getBeansOfType(ProducerProvider.class).values()); + + scbEngine.run(); + } else if (event instanceof ContextClosedEvent) { + if (SCBEngine.getInstance() != null) { + SCBEngine.getInstance().destroy(); + } + } + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java index fc9d276af22..c69521698af 100644 --- a/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java +++ b/core/src/main/java/org/apache/servicecomb/core/SCBEngine.java @@ -16,97 +16,73 @@ */ package org.apache.servicecomb.core; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.config.ConfigUtil; +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.config.priority.PriorityPropertyManager; import org.apache.servicecomb.core.BootListener.BootEvent; import org.apache.servicecomb.core.BootListener.EventType; import org.apache.servicecomb.core.bootup.BootUpInformationCollector; -import org.apache.servicecomb.core.definition.ConsumerMicroserviceVersionsMeta; -import org.apache.servicecomb.core.definition.CoreMetaUtils; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.MicroserviceVersionsMeta; -import org.apache.servicecomb.core.definition.ServiceRegistryListener; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.InvocationStartEvent; import org.apache.servicecomb.core.executor.ExecutorManager; import org.apache.servicecomb.core.filter.FilterChainsManager; -import org.apache.servicecomb.core.handler.ConsumerHandlerManager; -import org.apache.servicecomb.core.handler.HandlerConfigUtils; -import org.apache.servicecomb.core.handler.ProducerHandlerManager; +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager; import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; import org.apache.servicecomb.core.provider.consumer.MicroserviceReferenceConfig; +import org.apache.servicecomb.core.provider.consumer.ReferenceConfigManager; import org.apache.servicecomb.core.provider.producer.ProducerProviderManager; import org.apache.servicecomb.core.transport.TransportManager; -import org.apache.servicecomb.foundation.common.VendorExtensions; -import org.apache.servicecomb.foundation.common.event.EnableExceptionPropagation; import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.VertxUtils; import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; import org.apache.servicecomb.registry.DiscoveryManager; import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.event.MicroserviceInstanceRegisteredEvent; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; -import org.apache.servicecomb.registry.definition.MicroserviceNameParser; -import org.apache.servicecomb.registry.swagger.SwaggerLoader; +import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus; import org.apache.servicecomb.swagger.engine.SwaggerEnvironment; import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; -import org.springframework.util.StringUtils; +import org.springframework.core.env.Environment; import com.google.common.eventbus.AllowConcurrentEvents; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -import com.netflix.config.DynamicPropertyFactory; + +import jakarta.ws.rs.core.Response.Status; public class SCBEngine { private static final Logger LOGGER = LoggerFactory.getLogger(SCBEngine.class); - static final String CFG_KEY_WAIT_UP_TIMEOUT = "servicecomb.boot.waitUp.timeoutInMilliseconds"; - - static final long DEFAULT_WAIT_UP_TIMEOUT = 10_000; - - static final String CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC = "servicecomb.boot.turnDown.waitInSeconds"; + public static final String CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC = "servicecomb.boot.turnDown.waitInSeconds"; - static final long DEFAULT_TURN_DOWN_STATUS_WAIT_SEC = 0; + public static final long DEFAULT_TURN_DOWN_STATUS_WAIT_SEC = 0; - private static final Object initializationLock = new Object(); - - private volatile static SCBEngine INSTANCE; + // TODO: will remove in future. Too many codes need refactor. + private static volatile SCBEngine INSTANCE; private ApplicationContext applicationContext; private FilterChainsManager filterChainsManager; - private ConsumerHandlerManager consumerHandlerManager = new ConsumerHandlerManager(); - - private ProducerHandlerManager producerHandlerManager = new ProducerHandlerManager(); - private ProducerProviderManager producerProviderManager; - private ConsumerProviderManager consumerProviderManager = new ConsumerProviderManager(); + private ConsumerProviderManager consumerProviderManager; private MicroserviceMeta producerMicroserviceMeta; - private TransportManager transportManager = new TransportManager(); + private TransportManager transportManager; - private List bootListeners = new ArrayList<>( - SPIServiceUtils.getOrLoadSortedService(BootListener.class)); + private List bootListeners; private final AtomicLong invocationStartedCounter = new AtomicLong(); @@ -114,24 +90,27 @@ public class SCBEngine { private volatile SCBStatus status = SCBStatus.DOWN; - private EventBus eventBus; + private final EventBus eventBus; - private ExecutorManager executorManager = new ExecutorManager(); + private ExecutorManager executorManager; private PriorityPropertyManager priorityPropertyManager; - protected List bootUpInformationCollectors = SPIServiceUtils - .getSortedService(BootUpInformationCollector.class); + private List bootUpInformationCollectors; + + private final SwaggerEnvironment swaggerEnvironment = new SwaggerEnvironment(); - private ServiceRegistryListener serviceRegistryListener; + private OpenAPIRegistryManager openAPIRegistryManager; - private SwaggerEnvironment swaggerEnvironment = new SwaggerEnvironment(); + private RegistrationManager registrationManager; - private VendorExtensions vendorExtensions = new VendorExtensions(); + private DiscoveryManager discoveryManager; - private Thread shutdownHook; + private Environment environment; - protected SCBEngine() { + private ReferenceConfigManager referenceConfigManager; + + public SCBEngine() { eventBus = EventManager.getEventBus(); eventBus.register(this); @@ -139,23 +118,87 @@ protected SCBEngine() { INSTANCE = this; producerProviderManager = new ProducerProviderManager(this); - serviceRegistryListener = new ServiceRegistryListener(this); } - public ApplicationContext getApplicationContext() { - return applicationContext; + public static SCBEngine getInstance() { + if (INSTANCE == null) { + throw new InvocationException(Status.SERVICE_UNAVAILABLE, + new CommonExceptionData("SCBEngine is not initialized yet.")); + } + return INSTANCE; + } + + @Autowired + public void setReferenceConfigManager(ReferenceConfigManager referenceConfigManager) { + this.referenceConfigManager = referenceConfigManager; } + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + public Environment getEnvironment() { + return this.environment; + } + + @Autowired + @SuppressWarnings("unused") + public void setBootUpInformationCollectors(List bootUpInformationCollectors) { + this.bootUpInformationCollectors = bootUpInformationCollectors; + } + + @Autowired + @SuppressWarnings("unused") + public void setBootListeners(List listeners) { + this.bootListeners = listeners; + } + + @Autowired public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } - public VendorExtensions getVendorExtensions() { - return vendorExtensions; + @Autowired + public void setRegistrationManager(RegistrationManager registrationManager) { + this.registrationManager = registrationManager; + } + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } + + @Autowired + public void setOpenAPIRegistryManager(OpenAPIRegistryManager openAPIRegistryManager) { + this.openAPIRegistryManager = openAPIRegistryManager; + } + + @Autowired + public void setConsumerProviderManager(ConsumerProviderManager consumerProviderManager) { + this.consumerProviderManager = consumerProviderManager; + } + + @Autowired + public void setExecutorManager(ExecutorManager executorManager) { + this.executorManager = executorManager; + } + + @Autowired + public void setTransportManager(TransportManager transportManager) { + this.transportManager = transportManager; + } + + public RegistrationManager getRegistrationManager() { + return this.registrationManager; + } + + public ApplicationContext getApplicationContext() { + return applicationContext; } public String getAppId() { - return RegistrationManager.INSTANCE.getAppId(); + return BootStrapProperties.readApplication(environment); } public void setStatus(SCBStatus status) { @@ -166,19 +209,8 @@ public SCBStatus getStatus() { return status; } - public static SCBEngine getInstance() { - if (null == INSTANCE) { - synchronized (initializationLock) { - if (null == INSTANCE) { - new SCBEngine(); - } - } - } - return INSTANCE; - } - - public SwaggerLoader getSwaggerLoader() { - return RegistrationManager.INSTANCE.getSwaggerLoader(); + public OpenAPIRegistryManager getOpenAPIRegistryManager() { + return this.openAPIRegistryManager; } public FilterChainsManager getFilterChainsManager() { @@ -190,18 +222,6 @@ public SCBEngine setFilterChainsManager(FilterChainsManager filterChainsManager) return this; } - public boolean isFilterChainEnabled() { - return filterChainsManager.isEnabled(); - } - - public ConsumerHandlerManager getConsumerHandlerManager() { - return consumerHandlerManager; - } - - public ProducerHandlerManager getProducerHandlerManager() { - return producerHandlerManager; - } - public PriorityPropertyManager getPriorityPropertyManager() { return priorityPropertyManager; } @@ -219,10 +239,6 @@ public ExecutorManager getExecutorManager() { return executorManager; } - public void setExecutorManager(ExecutorManager executorManager) { - this.executorManager = executorManager; - } - public ProducerProviderManager getProducerProviderManager() { return producerProviderManager; } @@ -235,32 +251,14 @@ public ConsumerProviderManager getConsumerProviderManager() { return consumerProviderManager; } - public SCBEngine setConsumerProviderManager(ConsumerProviderManager consumerProviderManager) { - this.consumerProviderManager = consumerProviderManager; - return this; - } - public TransportManager getTransportManager() { return transportManager; } - public SCBEngine setTransportManager(TransportManager transportManager) { - this.transportManager = transportManager; - return this; - } - public SwaggerEnvironment getSwaggerEnvironment() { return swaggerEnvironment; } - public Collection getBootListeners() { - return bootListeners; - } - - public void addBootListeners(Collection bootListeners) { - this.bootListeners.addAll(bootListeners); - } - public SCBEngine addProducerMeta(String schemaId, Object instance) { getProducerProviderManager().addProducerMeta(schemaId, instance); return this; @@ -291,40 +289,31 @@ protected void safeTriggerEvent(EventType eventType) { } } - /** - *

As the process of instance registry is asynchronous, the {@code AFTER_REGISTRY} - * event should not be sent immediately. - * When the instance registry succeeds, {@link MicroserviceInstanceRegisteredEvent} will be posted in {@link EventManager}, - * register a subscriber to watch this event and send {@code AFTER_REGISTRY}.

- * - *

This method should be called before registry initialization to avoid that the registry process is too quick - * that the event is not watched by this subscriber.

- * - *

Check if {@code InstanceId} is null to judge whether the instance registry has succeeded.

- */ - private void triggerAfterRegistryEvent() { - eventBus.register(new AfterRegistryEventHanlder(this)); - } - @AllowConcurrentEvents @Subscribe + @SuppressWarnings("unused") public void onInvocationStart(InvocationStartEvent event) { invocationStartedCounter.incrementAndGet(); } @AllowConcurrentEvents @Subscribe + @SuppressWarnings("unused") public void onInvocationFinish(InvocationFinishEvent event) { invocationFinishedCounter.incrementAndGet(); } + public synchronized SCBEngine init() { + this.discoveryManager.init(); + this.registrationManager.init(); + return this; + } + public synchronized SCBEngine run() { if (SCBStatus.DOWN.equals(status)) { try { doRun(); - waitStatusUp(); - } catch (TimeoutException e) { - LOGGER.warn("{}", e.getMessage()); + printServiceInfo(); } catch (Throwable e) { LOGGER.error("Failed to start ServiceComb due to errors and close", e); try { @@ -334,8 +323,6 @@ public synchronized SCBEngine run() { } status = SCBStatus.FAILED; throw new IllegalStateException("ServiceComb init failed.", e); - } finally { - printServiceInfo(); } } @@ -362,12 +349,6 @@ private void printServiceInfo() { private void doRun() throws Exception { status = SCBStatus.STARTING; - bootListeners.sort(Comparator.comparingInt(BootListener::getOrder)); - - triggerEvent(EventType.BEFORE_HANDLER); - HandlerConfigUtils.init(consumerHandlerManager, producerHandlerManager); - triggerEvent(EventType.AFTER_HANDLER); - triggerEvent(EventType.BEFORE_FILTER); filterChainsManager.init(); triggerEvent(EventType.AFTER_FILTER); @@ -387,28 +368,22 @@ private void doRun() throws Exception { triggerEvent(EventType.AFTER_TRANSPORT); triggerEvent(EventType.BEFORE_REGISTRY); + registrationManager.run(); + discoveryManager.run(); + status = SCBStatus.UP; + triggerEvent(EventType.AFTER_REGISTRY); - triggerAfterRegistryEvent(); - - RegistrationManager.INSTANCE.run(); - DiscoveryManager.INSTANCE.run(); - - shutdownHook = new Thread(this::destroyForShutdownHook); - Runtime.getRuntime().addShutdownHook(shutdownHook); + // Keep this message for tests cases work. + LOGGER.warn("ServiceComb is ready."); } private void createProducerMicroserviceMeta() { - String microserviceName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); - - producerMicroserviceMeta = new MicroserviceMeta(this, microserviceName, false); - producerMicroserviceMeta.setHandlerChain(producerHandlerManager.getOrCreate(microserviceName)); - producerMicroserviceMeta.setFilterChain(filterChainsManager.findProducerChain(microserviceName)); - producerMicroserviceMeta.setMicroserviceVersionsMeta(new MicroserviceVersionsMeta(this, microserviceName)); - } - - public void destroyForShutdownHook() { - shutdownHook = null; - destroy(); + String microserviceName = BootStrapProperties.readServiceName(environment); + producerMicroserviceMeta = new MicroserviceMeta(this, + BootStrapProperties.readApplication(environment), microserviceName, false); + producerMicroserviceMeta.setProviderFilterChain(filterChainsManager.findProducerChain( + BootStrapProperties.readApplication(environment), microserviceName)); + producerMicroserviceMeta.setMicroserviceVersionsMeta(new MicroserviceVersionsMeta(this)); } /** @@ -425,10 +400,6 @@ public synchronized void destroy() { } private void doDestroy() { - if (shutdownHook != null) { - Runtime.getRuntime().removeShutdownHook(shutdownHook); - } - //Step 0: turn down the status of this instance in service center, // so that the consumers can remove this instance record in advance turnDownInstanceStatus(); @@ -442,10 +413,8 @@ private void doDestroy() { //Step 3: Unregister microservice instance from Service Center and close vertx // Forbidden other consumers find me - RegistrationManager.INSTANCE.destroy(); - DiscoveryManager.INSTANCE.destroy(); - - serviceRegistryListener.destroy(); + registrationManager.destroy(); + discoveryManager.destroy(); //Step 4: wait all invocation finished try { @@ -454,8 +423,7 @@ private void doDestroy() { LOGGER.error("wait all invocation finished interrupted", e); } - //Step 5: destroy config center source - ConfigUtil.destroyConfigCenterConfigurationSource(); + //Step 5: destroy config source // only be null for some test cases if (priorityPropertyManager != null) { priorityPropertyManager.close(); @@ -472,14 +440,17 @@ private void doDestroy() { } private void turnDownInstanceStatus() { - RegistrationManager.INSTANCE.updateMicroserviceInstanceStatus(MicroserviceInstanceStatus.DOWN); + try { + registrationManager.updateMicroserviceInstanceStatus(MicroserviceInstanceStatus.DOWN); + } catch (Throwable e) { + LOGGER.warn("turn down instance status fail: {}", e.getMessage()); + } } private void blockShutDownOperationForConsumerRefresh() { try { - long turnDownWaitSeconds = DynamicPropertyFactory.getInstance() - .getLongProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC) - .get(); + long turnDownWaitSeconds = environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); if (turnDownWaitSeconds <= 0) { return; } @@ -493,7 +464,7 @@ private void validAllInvocationFinished() throws InterruptedException { long start = System.currentTimeMillis(); while (true) { long remaining = invocationStartedCounter.get() - invocationFinishedCounter.get(); - if (remaining == 0) { + if (remaining <= 0) { return; } @@ -510,51 +481,19 @@ public void ensureStatusUp() { if (!SCBStatus.UP.equals(currentStatus)) { String message = "The request is rejected. Cannot process the request due to STATUS = " + currentStatus; - LOGGER.warn(message); throw new InvocationException(Status.SERVICE_UNAVAILABLE, new CommonExceptionData(message)); } } - /** - * for normal consumers - * @param microserviceName shortName, or appId:shortName when invoke cross app - * @return - */ - public MicroserviceReferenceConfig createMicroserviceReferenceConfig(String microserviceName) { - return createMicroserviceReferenceConfig(microserviceName, null); - } - - /** - * for edge, versionRule maybe controlled by url rule - * @param microserviceName hortName, or appId:shortName when invoke cross app - * @param versionRule if is empty, then use configuration value - * @return - */ - public CompletableFuture createMicroserviceReferenceConfigAsync(String microserviceName, - String versionRule) { - return DiscoveryManager.INSTANCE - .getOrCreateMicroserviceVersionsAsync(parseAppId(microserviceName), microserviceName) - .thenApply(versions -> { - ConsumerMicroserviceVersionsMeta microserviceVersionsMeta = CoreMetaUtils - .getMicroserviceVersionsMeta(versions); - return new MicroserviceReferenceConfig(microserviceVersionsMeta, versionRule); - }); + public CompletableFuture getOrCreateReferenceConfigAsync( + String microserviceName) { + return referenceConfigManager.getOrCreateReferenceConfigAsync(this, microserviceName); } - /** - * for edge, versionRule maybe controlled by url rule - * @param microserviceName hortName, or appId:shortName when invoke cross app - * @param versionRule if is empty, then use configuration value - * @return - */ - public MicroserviceReferenceConfig createMicroserviceReferenceConfig(String microserviceName, String versionRule) { + public MicroserviceReferenceConfig getOrCreateReferenceConfig( + String microserviceName) { ensureStatusUp(); - MicroserviceVersions microserviceVersions = DiscoveryManager.INSTANCE - .getOrCreateMicroserviceVersions(parseAppId(microserviceName), microserviceName); - ConsumerMicroserviceVersionsMeta microserviceVersionsMeta = CoreMetaUtils - .getMicroserviceVersionsMeta(microserviceVersions); - - return new MicroserviceReferenceConfig(microserviceVersionsMeta, versionRule); + return referenceConfigManager.getOrCreateReferenceConfig(this, microserviceName); } public MicroserviceMeta getProducerMicroserviceMeta() { @@ -565,75 +504,16 @@ public void setProducerMicroserviceMeta(MicroserviceMeta producerMicroserviceMet this.producerMicroserviceMeta = producerMicroserviceMeta; } - /** - * better to subscribe EventType.AFTER_REGISTRY by BootListener
- * but in some simple scenes, just block and wait is enough. - */ - public void waitStatusUp() throws InterruptedException, TimeoutException { - long msWait = DynamicPropertyFactory.getInstance().getLongProperty(CFG_KEY_WAIT_UP_TIMEOUT, DEFAULT_WAIT_UP_TIMEOUT) - .get(); - waitStatusUp(msWait); - } - - /** - * better to subscribe EventType.AFTER_REGISTRY by BootListener
- * but in some simple scenes, just block and wait is enough. - */ - public void waitStatusUp(long msWait) throws InterruptedException, TimeoutException { - if (msWait <= 0) { - LOGGER.info("Give up waiting for status up, wait timeout milliseconds={}.", msWait); - return; - } - LOGGER.info("Waiting for status up. timeout: {}ms", msWait); - long start = System.currentTimeMillis(); - for (; ; ) { - SCBStatus currentStatus = getStatus(); - switch (currentStatus) { - case DOWN: - case FAILED: - throw new IllegalStateException("Failed to wait status up, real status: " + currentStatus); - case UP: - LOGGER.info("Status already changed to up."); - return; - default: - break; - } + public static class CreateMicroserviceMetaEvent { + private final MicroserviceMeta microserviceMeta; - TimeUnit.MILLISECONDS.sleep(100); - if (System.currentTimeMillis() - start > msWait) { - throw new TimeoutException( - String.format("Timeout to wait status up, timeout: %dms, last status: %s", msWait, currentStatus)); - } + public CreateMicroserviceMetaEvent(MicroserviceMeta microserviceMeta) { + this.microserviceMeta = microserviceMeta; } - } - public String parseAppId(String microserviceName) { - return parseMicroserviceName(microserviceName).getAppId(); - } - - public MicroserviceNameParser parseMicroserviceName(String microserviceName) { - return new MicroserviceNameParser(getAppId(), microserviceName); - } - - public static class AfterRegistryEventHanlder { - private SCBEngine engine; - - public AfterRegistryEventHanlder(SCBEngine engine) { - this.engine = engine; - } - - @Subscribe - @EnableExceptionPropagation - public void afterRegistryInstance(MicroserviceInstanceRegisteredEvent event) { - if (event.isRegistrationManager()) { - LOGGER.info("instance registry succeeds for the first time, will send AFTER_REGISTRY event."); - engine.setStatus(SCBStatus.UP); - engine.triggerEvent(EventType.AFTER_REGISTRY); - EventManager.unregister(this); - // keep this message to be WARN, used to detect service ready. - LOGGER.warn("ServiceComb is ready."); - } + public MicroserviceMeta getMicroserviceMeta() { + return this.microserviceMeta; } } } diff --git a/core/src/main/java/org/apache/servicecomb/core/ServiceCombCoreConfiguration.java b/core/src/main/java/org/apache/servicecomb/core/ServiceCombCoreConfiguration.java new file mode 100644 index 00000000000..8abaceef9b5 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/ServiceCombCoreConfiguration.java @@ -0,0 +1,113 @@ +/* + * 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.core; + +import org.apache.servicecomb.core.bootup.ConfigurationProblemsCollector; +import org.apache.servicecomb.core.bootup.FilterChainCollector; +import org.apache.servicecomb.core.bootup.ServiceInformationCollector; +import org.apache.servicecomb.core.executor.ExecutorManager; +import org.apache.servicecomb.core.executor.GroupExecutor; +import org.apache.servicecomb.core.provider.LocalOpenAPIRegistry; +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager; +import org.apache.servicecomb.core.provider.RegistryOpenAPIRegistry; +import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; +import org.apache.servicecomb.core.provider.consumer.ReferenceConfigManager; +import org.apache.servicecomb.core.provider.producer.ProducerBootListener; +import org.apache.servicecomb.core.transport.TransportManager; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +@SuppressWarnings("unused") +public class ServiceCombCoreConfiguration { + @Bean + public SCBApplicationListener scbApplicationListener(SCBEngine scbEngine) { + SCBApplicationListener scbApplicationListener = new SCBApplicationListener(scbEngine); + scbApplicationListener.setInitEventClass(ApplicationReadyEvent.class); + return scbApplicationListener; + } + + @Bean + public SCBEngine scbEngine() { + return new SCBEngine(); + } + + @Bean + public ConsumerProviderManager scbConsumerProviderManager(Environment environment, + OpenAPIRegistryManager openAPIRegistryManager) { + return new ConsumerProviderManager(environment, openAPIRegistryManager); + } + + @Bean + public ReferenceConfigManager scbReferenceConfigManager() { + return new ReferenceConfigManager(); + } + + @Bean + public OpenAPIRegistryManager scbOpenAPIRegistryManager() { + return new OpenAPIRegistryManager(); + } + + @Bean + public LocalOpenAPIRegistry scbLocalOpenAPIRegistry(Environment environment) { + return new LocalOpenAPIRegistry(environment); + } + + @Bean + public RegistryOpenAPIRegistry scbRegistryOpenAPIRegistry() { + return new RegistryOpenAPIRegistry(); + } + + @Bean + public ProducerBootListener scbProducerBootListener() { + return new ProducerBootListener(); + } + + @Bean + public FilterChainCollector scbFilterChainCollector() { + return new FilterChainCollector(); + } + + @Bean + public ConfigurationProblemsCollector scbConfigurationProblemsCollector() { + return new ConfigurationProblemsCollector(); + } + + @Bean + public ServiceInformationCollector scbServiceInformationCollector() { + return new ServiceInformationCollector(); + } + + @Bean + public ExecutorManager scbExecutorManager() { + return new ExecutorManager(); + } + + @Bean(value = {"cse.executor.groupThreadPool", "cse.executor.default", "servicecomb.executor.groupThreadPool"}) + public GroupExecutor scbGroupExecutor(Environment environment) { + GroupExecutor groupExecutor = new GroupExecutor(environment); + groupExecutor.init(); + return groupExecutor; + } + + @Bean + public TransportManager scbTransportManager() { + return new TransportManager(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/Transport.java b/core/src/main/java/org/apache/servicecomb/core/Transport.java index ed9ade43e88..1c40303fce8 100644 --- a/core/src/main/java/org/apache/servicecomb/core/Transport.java +++ b/core/src/main/java/org/apache/servicecomb/core/Transport.java @@ -17,9 +17,8 @@ package org.apache.servicecomb.core; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; +import org.springframework.core.env.Environment; -// TODO:感觉要拆成显式的client、server才好些 public interface Transport { String getName(); @@ -33,6 +32,8 @@ default boolean canInit() { boolean init() throws Exception; + void setEnvironment(Environment environment); + /* * endpoint的格式为 URI,比如rest://192.168.1.1:8080 */ @@ -47,6 +48,4 @@ default boolean canInit() { * 用于上报到服务中心,要求是其他节点可访问的地址 */ Endpoint getPublishEndpoint() throws Exception; - - void send(Invocation invocation, AsyncResponse asyncResp) throws Exception; } diff --git a/core/src/main/java/org/apache/servicecomb/core/annotation/Transport.java b/core/src/main/java/org/apache/servicecomb/core/annotation/Transport.java new file mode 100644 index 00000000000..c81055c7b46 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/annotation/Transport.java @@ -0,0 +1,42 @@ +/* + * 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.core.annotation; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.springframework.stereotype.Component; + +@Inherited +@Documented +@Retention(RUNTIME) +@Target({TYPE, METHOD, ANNOTATION_TYPE}) +@Component +public @interface Transport { + /** + * Transport name. e.g. rest, highway. + */ + String name(); +} diff --git a/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBBootstrap.java b/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBBootstrap.java index 1967e5609b0..21040a3410f 100644 --- a/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBBootstrap.java +++ b/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBBootstrap.java @@ -16,14 +16,41 @@ */ package org.apache.servicecomb.core.bootstrap; +import java.util.Collections; +import java.util.List; + import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.executor.ExecutorManager; +import org.apache.servicecomb.core.provider.LocalOpenAPIRegistry; +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager; +import org.apache.servicecomb.core.provider.consumer.ConsumerProviderManager; +import org.apache.servicecomb.core.transport.TransportManager; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.registry.DiscoveryManager; import org.apache.servicecomb.registry.RegistrationManager; +import org.apache.servicecomb.registry.discovery.TelnetInstancePing; +import org.springframework.core.env.Environment; public class SCBBootstrap { - public static SCBEngine createSCBEngineForTest() { - RegistrationManager.INSTANCE.init(); - DiscoveryManager.INSTANCE.init(); - return new SCBEngineForTest(); + public static SCBEngine createSCBEngineForTest(Environment environment) { + LegacyPropertyFactory.setEnvironment(environment); + RegistrationManager registrationManager = new RegistrationManager(Collections.emptyList()); + DiscoveryManager discoveryManager = new DiscoveryManager(Collections.emptyList(), + List.of(new TelnetInstancePing())); + registrationManager.init(); + discoveryManager.init(); + SCBEngine result = new SCBEngineForTest(environment); + result.setDiscoveryManager(discoveryManager); + result.setRegistrationManager(registrationManager); + result.setBootListeners(Collections.emptyList()); + result.setBootUpInformationCollectors(Collections.emptyList()); + result.setExecutorManager(new ExecutorManager()); + result.setTransportManager(new TransportManager()); + result.setEnvironment(environment); + OpenAPIRegistryManager openAPIRegistryManager = new OpenAPIRegistryManager(); + openAPIRegistryManager.setOpenAPIRegistries(List.of(new LocalOpenAPIRegistry(environment))); + result.setConsumerProviderManager(new ConsumerProviderManager(environment, openAPIRegistryManager)); + result.setOpenAPIRegistryManager(openAPIRegistryManager); + return result; } } diff --git a/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBEngineForTest.java b/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBEngineForTest.java index 71b5af2b3ba..46ccd954155 100644 --- a/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBEngineForTest.java +++ b/core/src/main/java/org/apache/servicecomb/core/bootstrap/SCBEngineForTest.java @@ -17,39 +17,35 @@ package org.apache.servicecomb.core.bootstrap; -import static org.apache.servicecomb.core.executor.ExecutorManager.EXECUTOR_GROUP_THREADPOOL; - -import java.util.Arrays; import java.util.List; import org.apache.servicecomb.config.priority.ConfigObjectFactory; import org.apache.servicecomb.config.priority.PriorityPropertyFactory; import org.apache.servicecomb.config.priority.PriorityPropertyManager; import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.executor.GroupExecutor; -import org.apache.servicecomb.core.filter.Filter; import org.apache.servicecomb.core.filter.FilterChainsManager; import org.apache.servicecomb.core.filter.impl.EmptyFilter; import org.apache.servicecomb.foundation.common.event.EventManager; import org.apache.servicecomb.foundation.common.event.SimpleEventBus; import org.apache.servicecomb.foundation.common.utils.ReflectUtils; +import org.springframework.core.env.Environment; /** * not depend on remote service registry and spring context */ public class SCBEngineForTest extends SCBEngine { - public SCBEngineForTest() { - getExecutorManager().registerExecutor(EXECUTOR_GROUP_THREADPOOL, new GroupExecutor().init()); - - List filters = Arrays.asList( - new EmptyFilter() - ); + public SCBEngineForTest(Environment environment) { + EmptyFilter emptyFilter = new EmptyFilter(); + emptyFilter.setEnvironment(environment); setFilterChainsManager(new FilterChainsManager() - .addFilters(filters)); + .setProviderFilters(List.of(emptyFilter)) + .setConsumerFilters(List.of(emptyFilter)) + .setEdgeFilters(List.of(emptyFilter))); - PriorityPropertyFactory propertyFactory = new PriorityPropertyFactory(); + PriorityPropertyFactory propertyFactory = new PriorityPropertyFactory(environment); ConfigObjectFactory configObjectFactory = new ConfigObjectFactory(propertyFactory); setPriorityPropertyManager(new PriorityPropertyManager(configObjectFactory)); + setEnvironment(environment); } @Override diff --git a/core/src/main/java/org/apache/servicecomb/core/bootup/BootUpInformationCollector.java b/core/src/main/java/org/apache/servicecomb/core/bootup/BootUpInformationCollector.java index 62a9ac5ce2b..4ebae5180f4 100644 --- a/core/src/main/java/org/apache/servicecomb/core/bootup/BootUpInformationCollector.java +++ b/core/src/main/java/org/apache/servicecomb/core/bootup/BootUpInformationCollector.java @@ -18,13 +18,12 @@ package org.apache.servicecomb.core.bootup; import org.apache.servicecomb.core.SCBEngine; +import org.springframework.core.Ordered; -public interface BootUpInformationCollector { +public interface BootUpInformationCollector extends Ordered { default String collect(SCBEngine engine) { return collect(); } String collect(); - - int getOrder(); } diff --git a/core/src/main/java/org/apache/servicecomb/core/bootup/ConfigurationProblemsAlarmEvent.java b/core/src/main/java/org/apache/servicecomb/core/bootup/ConfigurationProblemsAlarmEvent.java new file mode 100644 index 00000000000..631cc361235 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/bootup/ConfigurationProblemsAlarmEvent.java @@ -0,0 +1,32 @@ +/* + * 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.core.bootup; + +import org.apache.servicecomb.foundation.common.event.AlarmEvent; + +public class ConfigurationProblemsAlarmEvent extends AlarmEvent { + private final String problems; + + public ConfigurationProblemsAlarmEvent(Type type, String problems) { + super(type); + this.problems = problems; + } + + public String getProblems() { + return problems; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/bootup/ConfigurationProblemsCollector.java b/core/src/main/java/org/apache/servicecomb/core/bootup/ConfigurationProblemsCollector.java new file mode 100644 index 00000000000..415516f6fea --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/bootup/ConfigurationProblemsCollector.java @@ -0,0 +1,133 @@ +/* + * 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.core.bootup; + +import java.util.Arrays; +import java.util.Set; +import java.util.regex.Pattern; + +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.foundation.common.event.AlarmEvent.Type; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.springframework.core.env.Environment; + +/** + * Detect deprecated and wrong usages of configurations + * and print warning messages + * and sending ConfigurationProblemsAlarmEvent. + */ +public class ConfigurationProblemsCollector implements BootUpInformationCollector { + private static final String SERVICE_NAME_PATTERN_STRING = "([A-Za-z])|([A-Za-z][A-Za-z0-9_\\-.]*[A-Za-z0-9])"; + + private static final Pattern SERVICE_NAME_PATTERN = Pattern.compile(SERVICE_NAME_PATTERN_STRING); + + @Override + public String collect(SCBEngine engine) { + StringBuilder result = new StringBuilder(); + collectCsePrefix(engine.getEnvironment(), result); + collectServiceDefinition(engine.getEnvironment(), result); + collectServiceDefinitionValidation(engine.getEnvironment(), result); + collectTimeoutConfiguration(engine.getEnvironment(), result); + collectIsolationConfiguration(engine.getEnvironment(), result); + if (result.isEmpty()) { + return null; + } + String warnings = "[WARN]Configurations warnings:\n" + result; + EventManager.post(new ConfigurationProblemsAlarmEvent(Type.OPEN, warnings)); + return warnings; + } + + private void collectServiceDefinitionValidation(Environment environment, StringBuilder result) { + String application = BootStrapProperties.readApplication(environment); + if (!SERVICE_NAME_PATTERN.matcher(application).matches()) { + result.append("application does not match pattern ").append(SERVICE_NAME_PATTERN_STRING).append("."); + } + String serviceName = BootStrapProperties.readServiceName(environment); + if (!SERVICE_NAME_PATTERN.matcher(serviceName).matches()) { + result.append("service name does not match pattern ").append(SERVICE_NAME_PATTERN_STRING).append("."); + } + } + + private void collectIsolationConfiguration(Environment environment, StringBuilder result) { + int percentage = environment.getProperty( + "servicecomb.loadbalance.isolation.errorThresholdPercentage", int.class, -1); + int continuous = environment.getProperty( + "servicecomb.loadbalance.isolation.continuousFailureThreshold", int.class, -1); + if (percentage == -1 && continuous == -1) { + return; + } + result.append("Configuration `servicecomb.loadbalance.isolation.*` is removed, use governance instead. " + + "See https://servicecomb.apache.org/references/java-chassis/" + + "zh_CN/references-handlers/governance-best-practise.html"); + } + + private void collectTimeoutConfiguration(Environment environment, StringBuilder result) { + int keepAliveTimeoutInSeconds = environment.getProperty( + "servicecomb.rest.client.connection.keepAliveTimeoutInSeconds", int.class, 60); + int idleTimeoutInSeconds = environment.getProperty( + "servicecomb.rest.client.connection.idleTimeoutInSeconds", int.class, 150); + if (keepAliveTimeoutInSeconds >= idleTimeoutInSeconds) { + result.append("Configuration `servicecomb.rest.client.connection.keepAliveTimeoutInSeconds` is longer than " + + "servicecomb.rest.client.connection.idleTimeoutInSeconds."); + result.append("[").append(keepAliveTimeoutInSeconds).append(",").append(idleTimeoutInSeconds).append("]\n"); + } + keepAliveTimeoutInSeconds = environment.getProperty( + "servicecomb.rest.client.http2.connection.keepAliveTimeoutInSeconds", int.class, 60); + idleTimeoutInSeconds = environment.getProperty( + "servicecomb.rest.client.http2.connection.idleTimeoutInSeconds", int.class, 150); + if (keepAliveTimeoutInSeconds >= idleTimeoutInSeconds) { + result.append("Configuration `servicecomb.rest.client.http2.connection.keepAliveTimeoutInSeconds` is longer than " + + "servicecomb.rest.client.http2.connection.idleTimeoutInSeconds."); + result.append("[").append(keepAliveTimeoutInSeconds).append(",").append(idleTimeoutInSeconds).append("]\n"); + } + } + + private void collectServiceDefinition(Environment environment, StringBuilder result) { + if (environment.getProperty("APPLICATION_ID") != null) { + result.append("Configurations `APPLICATION_ID` is deprecated, " + + "use `servicecomb.service.application` instead.\n"); + } + Set names = ConfigUtil.propertiesWithPrefix(environment, "service_description."); + if (!names.isEmpty()) { + result.append("Configurations with prefix `service_description` is deprecated, " + + "use `servicecomb.service` instead. Find keys "); + result.append(Arrays.toString(names.toArray())); + result.append("\n"); + } + } + + private void collectCsePrefix(Environment environment, StringBuilder result) { + Set names = ConfigUtil.propertiesWithPrefix(environment, "cse."); + if (!names.isEmpty()) { + result.append("Configurations with prefix `cse` is deprecated, use `servicecomb` instead. Find keys "); + result.append(Arrays.toString(names.toArray())); + result.append("\n"); + } + } + + @Override + public String collect() { + return null; + } + + @Override + public int getOrder() { + return 1000; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/bootup/FilterChainCollector.java b/core/src/main/java/org/apache/servicecomb/core/bootup/FilterChainCollector.java index 8d1a8720688..80289d22ce3 100644 --- a/core/src/main/java/org/apache/servicecomb/core/bootup/FilterChainCollector.java +++ b/core/src/main/java/org/apache/servicecomb/core/bootup/FilterChainCollector.java @@ -24,10 +24,6 @@ public class FilterChainCollector implements BootUpInformationCollector { @Override public String collect(SCBEngine engine) { FilterChainsManager mgr = engine.getFilterChainsManager(); - if (!mgr.isEnabled()) { - return null; - } - return mgr.collectResolvedChains(); } diff --git a/core/src/main/java/org/apache/servicecomb/core/bootup/ServiceInformationCollector.java b/core/src/main/java/org/apache/servicecomb/core/bootup/ServiceInformationCollector.java index b94b947993d..fb13033ec99 100644 --- a/core/src/main/java/org/apache/servicecomb/core/bootup/ServiceInformationCollector.java +++ b/core/src/main/java/org/apache/servicecomb/core/bootup/ServiceInformationCollector.java @@ -17,13 +17,31 @@ package org.apache.servicecomb.core.bootup; +import org.apache.servicecomb.registry.DiscoveryManager; import org.apache.servicecomb.registry.RegistrationManager; +import org.springframework.beans.factory.annotation.Autowired; public class ServiceInformationCollector implements BootUpInformationCollector { + private RegistrationManager registrationManager; + + private DiscoveryManager discoveryManager; + + public ServiceInformationCollector() { + } + + @Autowired + public void setRegistrationManager(RegistrationManager registrationManager) { + this.registrationManager = registrationManager; + } + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } @Override public String collect() { - return RegistrationManager.INSTANCE.info(); + return registrationManager.info() + "\n" + discoveryManager.info(); } @Override diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/ConsumerMicroserviceVersionsMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/ConsumerMicroserviceVersionsMeta.java index 4510302728f..78f24e67f78 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/ConsumerMicroserviceVersionsMeta.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/ConsumerMicroserviceVersionsMeta.java @@ -17,18 +17,9 @@ package org.apache.servicecomb.core.definition; import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; public class ConsumerMicroserviceVersionsMeta extends MicroserviceVersionsMeta { - private MicroserviceVersions microserviceVersions; - - public ConsumerMicroserviceVersionsMeta(SCBEngine scbEngine, MicroserviceVersions microserviceVersions) { - super(scbEngine, microserviceVersions.getMicroserviceName()); - - this.microserviceVersions = microserviceVersions; - } - - public MicroserviceVersions getMicroserviceVersions() { - return microserviceVersions; + public ConsumerMicroserviceVersionsMeta(SCBEngine scbEngine) { + super(scbEngine); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/CoreMetaUtils.java b/core/src/main/java/org/apache/servicecomb/core/definition/CoreMetaUtils.java index df4bd490b53..9b164223af7 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/CoreMetaUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/CoreMetaUtils.java @@ -16,48 +16,10 @@ */ package org.apache.servicecomb.core.definition; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; -import org.apache.servicecomb.swagger.engine.SwaggerProducer; - public final class CoreMetaUtils { - public static final String CORE_MICROSERVICE_VERSIONS_META = "scb_microservice_versions_meta"; - - public static final String CORE_MICROSERVICE_META = "scb_microservice_meta"; - - public static final String CORE_MICROSERVICE_VERSION = "scb_microservice_version"; public static final String SWAGGER_PRODUCER = "scb_swagger-producer"; private CoreMetaUtils() { } - - public static T getMicroserviceVersionsMeta( - MicroserviceVersions microserviceVersions) { - return microserviceVersions.getVendorExtensions().get(CORE_MICROSERVICE_VERSIONS_META); - } - - // only for consumer flow - public static MicroserviceVersions getMicroserviceVersions(Invocation invocation) { - return getMicroserviceVersions(invocation.getMicroserviceMeta()); - } - - // only for consumer flow - public static MicroserviceVersions getMicroserviceVersions(MicroserviceMeta microserviceMeta) { - return getMicroserviceVersion(microserviceMeta).getMicroserviceVersions(); - } - - // only for consumer flow - public static MicroserviceVersion getMicroserviceVersion(MicroserviceMeta microserviceMeta) { - return microserviceMeta.getExtData(CORE_MICROSERVICE_VERSION); - } - - public static MicroserviceMeta getMicroserviceMeta(MicroserviceVersion microserviceVersion) { - return microserviceVersion.getVendorExtensions().get(CORE_MICROSERVICE_META); - } - - public static SwaggerProducer getSwaggerProducer(SchemaMeta schemaMeta) { - return schemaMeta.getExtData(SWAGGER_PRODUCER); - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/InvocationRuntimeType.java b/core/src/main/java/org/apache/servicecomb/core/definition/InvocationRuntimeType.java index ca408520b7f..356201b70d7 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/InvocationRuntimeType.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/InvocationRuntimeType.java @@ -19,7 +19,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Type; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.swagger.invocation.arguments.ArgumentsMapper; import org.apache.servicecomb.swagger.invocation.response.ResponsesMeta; @@ -40,7 +40,7 @@ public class InvocationRuntimeType { private Method associatedMethod; - private ResponsesMeta responsesMeta; + private final ResponsesMeta responsesMeta; private ArgumentsMapper argumentsMapper; diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceConfig.java b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceConfig.java deleted file mode 100644 index 68f58b6ab48..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.core.definition; - -import org.apache.servicecomb.config.inject.InjectProperties; -import org.apache.servicecomb.config.inject.InjectProperty; -import org.apache.servicecomb.registry.version.VersionRuleUtils; - -@InjectProperties(prefix = "servicecomb") -public class MicroserviceConfig { - @InjectProperty(keys = { - "references.version-rule.${service}", - "references.${service}.version-rule", // Deprecated - "references.version-rule" - }, defaultValue = "0.0.0.0+") - private String versionRule; - - public String getVersionRule() { - return versionRule; - } - - public void setVersionRule(String versionRule) { - this.versionRule = VersionRuleUtils.getOrCreate(versionRule).getVersionRule(); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceMeta.java index 3cebb69b4bd..9476a34229b 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceMeta.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceMeta.java @@ -16,80 +16,49 @@ */ package org.apache.servicecomb.core.definition; -import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; -import org.apache.servicecomb.core.Handler; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.foundation.common.VendorExtensions; -import org.apache.servicecomb.registry.definition.MicroserviceNameParser; -import org.apache.servicecomb.swagger.SwaggerUtils; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; -/** - * should named MicroserviceVersionMeta
- * but for compatible reason, keep the old name - */ public class MicroserviceMeta { private final SCBEngine scbEngine; private MicroserviceVersionsMeta microserviceVersionsMeta; - private String appId; - - // always not include appId - private String shortName; + private final String appId; - // inside app: equals to shortName - // cross app: appId:shortName - private String microserviceName; + private final String microserviceName; // key is schemaId, this is all schemas - private Map schemaMetas = new HashMap<>(); - - // key is schema interface - // only when list have only one element, then allow query by interface - // otherwise must query by schemaId - // - // value is synchronizedList, only for low frequency query - private Map, List> intfSchemaMetas = new HashMap<>(); + private final Map schemaMetas = new HashMap<>(); // key is OperationMeta.getMicroserviceQualifiedName() - private Map operationMetas = new HashMap<>(); + private final Map operationMetas = new HashMap<>(); - private boolean consumer; + // Used to indicate configuration items type. EDGE & CONSUMER chain are all consumer. + private final boolean consumer; - private List handlerChain = Collections.singletonList((invocation, ar) -> ar.success(null)); + private FilterNode consumerFilterChain = FilterNode.EMPTY; - private FilterNode filterChain = FilterNode.EMPTY; + private FilterNode providerFilterChain = FilterNode.EMPTY; - // providerQpsFlowControlHandler is a temporary field, only for internal usage - private Handler providerQpsFlowControlHandler; + private FilterNode edgeFilterChain = FilterNode.EMPTY; - // providerQpsFlowControlHandlerSearched is a temporary field, only for internal usage - private boolean providerQpsFlowControlHandlerSearched; + private final VendorExtensions vendorExtensions = new VendorExtensions(); - private VendorExtensions vendorExtensions = new VendorExtensions(); - - public MicroserviceMeta(SCBEngine scbEngine, String microserviceName, boolean consumer) { + public MicroserviceMeta(SCBEngine scbEngine, String application, String serviceName, boolean consumer) { this.scbEngine = scbEngine; - MicroserviceNameParser parser = scbEngine.parseMicroserviceName(microserviceName); - this.appId = parser.getAppId(); - this.shortName = parser.getShortName(); - this.microserviceName = parser.getMicroserviceName(); + this.appId = application; + this.microserviceName = serviceName; this.consumer = consumer; } - public MicroserviceConfig getMicroserviceConfig() { - return microserviceVersionsMeta.getMicroserviceConfig(); - } - public MicroserviceVersionsMeta getMicroserviceVersionsMeta() { return microserviceVersionsMeta; } @@ -114,11 +83,7 @@ public String getAppId() { return appId; } - public String getShortName() { - return shortName; - } - - public SchemaMeta registerSchemaMeta(String schemaId, Swagger swagger) { + public SchemaMeta registerSchemaMeta(String schemaId, OpenAPI swagger) { SchemaMeta schemaMeta = new SchemaMeta(this, schemaId, swagger); if (schemaMetas.putIfAbsent(schemaMeta.getSchemaId(), schemaMeta) != null) { @@ -127,14 +92,7 @@ public SchemaMeta registerSchemaMeta(String schemaId, Swagger swagger) { appId, microserviceName, schemaMeta.getSchemaId())); } - Class intf = SwaggerUtils.getInterface(schemaMeta.getSwagger()); - if (intf != null) { - intfSchemaMetas - .computeIfAbsent(intf, k -> Collections.synchronizedList(new ArrayList<>())) - .add(schemaMeta); - } - - schemaMeta.getOperations().values().stream() + schemaMeta.getOperations().values() .forEach(operationMeta -> operationMetas.put(operationMeta.getMicroserviceQualifiedName(), operationMeta)); return schemaMeta; @@ -163,23 +121,6 @@ public SchemaMeta findSchemaMeta(String schemaId) { return schemaMetas.get(schemaId); } - public SchemaMeta findSchemaMeta(Class schemaIntf) { - List schemaList = intfSchemaMetas.get(schemaIntf); - if (schemaList == null) { - return null; - } - - if (schemaList.size() > 1) { - throw new IllegalStateException(String.format( - "failed to find SchemaMeta by interface cause there are multiple SchemaMeta relate to the interface, " - + "please use schemaId to choose a SchemaMeta, " - + "appId=%s, microserviceName=%s, interface=%s.", - appId, microserviceName, schemaIntf.getName())); - } - - return schemaList.get(0); - } - public Map getSchemaMetas() { return schemaMetas; } @@ -192,39 +133,27 @@ public T getExtData(String key) { return vendorExtensions.get(key); } - public List getHandlerChain() { - return handlerChain; + public FilterNode getConsumerFilterChain() { + return consumerFilterChain; } - public void setHandlerChain(List handlerChain) { - this.handlerChain = handlerChain; + public void setConsumerFilterChain(FilterNode consumerFilterChain) { + this.consumerFilterChain = consumerFilterChain; } - public FilterNode getFilterChain() { - return filterChain; + public FilterNode getProviderFilterChain() { + return providerFilterChain; } - public void setFilterChain(FilterNode filterChain) { - this.filterChain = filterChain; + public void setProviderFilterChain(FilterNode providerFilterChain) { + this.providerFilterChain = providerFilterChain; } - /** - * Only for JavaChassis internal usage. - */ - @Deprecated - public Handler getProviderQpsFlowControlHandler() { - if (providerQpsFlowControlHandlerSearched) { - return providerQpsFlowControlHandler; - } + public FilterNode getEdgeFilterChain() { + return edgeFilterChain; + } - for (Handler handler : handlerChain) { - // matching by class name is more or less better than importing an extra maven dependency - if ("org.apache.servicecomb.qps.ProviderQpsFlowControlHandler".equals(handler.getClass().getName())) { - providerQpsFlowControlHandler = handler; - break; - } - } - providerQpsFlowControlHandlerSearched = true; - return providerQpsFlowControlHandler; + public void setEdgeFilterChain(FilterNode edgeFilterChain) { + this.edgeFilterChain = edgeFilterChain; } } diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionsMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionsMeta.java index 05f336200b8..9e98bc2db51 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionsMeta.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/MicroserviceVersionsMeta.java @@ -24,32 +24,11 @@ public class MicroserviceVersionsMeta { protected final SCBEngine scbEngine; - protected final String microserviceName; - // key is operationMeta.getMicroserviceQualifiedName() private final Map configs = new ConcurrentHashMapEx<>(); - protected volatile MicroserviceConfig microserviceConfig; - - public MicroserviceVersionsMeta(SCBEngine scbEngine, String microserviceName) { + public MicroserviceVersionsMeta(SCBEngine scbEngine) { this.scbEngine = scbEngine; - this.microserviceName = microserviceName; - } - - // should not create in constructor - // when invoke not exist microservice, will create DynamicProperty(com.netflix.config.DynamicProperty.getInstance) - // edge scene, if attacker request to forward request to not exist microservice, will cause OOM - public MicroserviceConfig getMicroserviceConfig() { - if (microserviceConfig == null) { - synchronized (this) { - if (microserviceConfig == null) { - this.microserviceConfig = scbEngine.getPriorityPropertyManager() - .createConfigObject(MicroserviceConfig.class, "service", microserviceName); - } - } - } - - return microserviceConfig; } public OperationConfig getOrCreateOperationConfig(OperationMeta operationMeta) { diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java b/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java index 17e5cf10fa3..bc289521a31 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java @@ -24,7 +24,7 @@ import org.apache.servicecomb.config.inject.InjectProperties; import org.apache.servicecomb.config.inject.InjectProperty; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; @InjectProperties(prefix = "servicecomb") public class OperationConfig { @@ -75,13 +75,13 @@ public class OperationConfig { /** * whether to remove certain headers from the 3rd party invocations */ - @InjectProperty(keys = {"request.clientRequestHeaderFilterEnabled${consumer-op-priority}"}, defaultValue = "true") - private boolean clientRequestHeaderFilterEnabled = true; + @InjectProperty(keys = {"request.clientRequestHeaderFilterEnabled${consumer-op-priority}"}, defaultValue = "false") + private boolean clientRequestHeaderFilterEnabled = false; /** * producer wait in thread pool timeout */ - private Map nanoRequestWaitInPoolTimeoutByTransport = new HashMap<>(); + private final Map nanoRequestWaitInPoolTimeoutByTransport = new HashMap<>(); @InjectProperty(keys = "Provider.requestWaitInPoolTimeout${op-priority}", defaultValue = "30000") private long msDefaultRequestWaitInPoolTimeout; @@ -168,7 +168,7 @@ public long getMsHighwayRequestWaitInPoolTimeout() { public void setMsHighwayRequestWaitInPoolTimeout(long msHighwayRequestWaitInPoolTimeout) { this.msHighwayRequestWaitInPoolTimeout = msHighwayRequestWaitInPoolTimeout; this.nanoHighwayRequestWaitInPoolTimeout = TimeUnit.MILLISECONDS.toNanos(msHighwayRequestWaitInPoolTimeout); - registerRequestWaitInPoolTimeout(Const.HIGHWAY, msHighwayRequestWaitInPoolTimeout); + registerRequestWaitInPoolTimeout(CoreConst.HIGHWAY, msHighwayRequestWaitInPoolTimeout); } public long getNanoHighwayRequestWaitInPoolTimeout() { @@ -182,7 +182,7 @@ public long getMsRestRequestWaitInPoolTimeout() { public void setMsRestRequestWaitInPoolTimeout(long msRestRequestWaitInPoolTimeout) { this.msRestRequestWaitInPoolTimeout = msRestRequestWaitInPoolTimeout; this.nanoRestRequestWaitInPoolTimeout = TimeUnit.MILLISECONDS.toNanos(msRestRequestWaitInPoolTimeout); - registerRequestWaitInPoolTimeout(Const.RESTFUL, msRestRequestWaitInPoolTimeout); + registerRequestWaitInPoolTimeout(CoreConst.RESTFUL, msRestRequestWaitInPoolTimeout); } public long getNanoRestRequestWaitInPoolTimeout() { @@ -224,7 +224,7 @@ public String getTransport() { public void setTransport(String transport) { if (transport == null) { - transport = Const.ANY_TRANSPORT; + transport = CoreConst.ANY_TRANSPORT; } this.transport = transport; } diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/OperationMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/OperationMeta.java index 359b93c1214..003daaffab1 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/OperationMeta.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/OperationMeta.java @@ -18,14 +18,14 @@ import java.util.concurrent.Executor; -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Handler; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.foundation.common.VendorExtensions; import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; import org.apache.servicecomb.swagger.generator.core.model.SwaggerOperation; import org.apache.servicecomb.swagger.invocation.response.ResponsesMeta; -import io.swagger.models.Operation; +import io.swagger.v3.oas.models.Operation; + public class OperationMeta { private SchemaMeta schemaMeta; @@ -45,11 +45,9 @@ public class OperationMeta { // run in this executor private Executor executor; - private ResponsesMeta responsesMeta = new ResponsesMeta(); - - private OperationConfig config; + private final ResponsesMeta responsesMeta = new ResponsesMeta(); - private VendorExtensions vendorExtensions = new VendorExtensions(); + private final VendorExtensions vendorExtensions = new VendorExtensions(); public OperationMeta init(SchemaMeta schemaMeta, SwaggerOperation swaggerOperation) { this.schemaMeta = schemaMeta; @@ -60,22 +58,21 @@ public OperationMeta init(SchemaMeta schemaMeta, SwaggerOperation swaggerOperati this.operationPath = swaggerOperation.getPath(); this.swaggerOperation = swaggerOperation.getOperation(); this.executor = schemaMeta.getMicroserviceMeta().getScbEngine().getExecutorManager().findExecutor(this); - this.config = schemaMeta.getMicroserviceMeta().getMicroserviceVersionsMeta().getOrCreateOperationConfig(this); this.responsesMeta.init(schemaMeta.getSwagger(), swaggerOperation.getOperation()); return this; } public void setSwaggerProducerOperation(SwaggerProducerOperation swaggerProducerOperation) { - this.putExtData(Const.PRODUCER_OPERATION, swaggerProducerOperation); + this.putExtData(CoreConst.PRODUCER_OPERATION, swaggerProducerOperation); } public SwaggerProducerOperation getSwaggerProducerOperation() { - return (SwaggerProducerOperation) this.getExtData(Const.PRODUCER_OPERATION); + return (SwaggerProducerOperation) this.getExtData(CoreConst.PRODUCER_OPERATION); } public OperationConfig getConfig() { - return config; + return schemaMeta.getMicroserviceMeta().getMicroserviceVersionsMeta().getOrCreateOperationConfig(this); } public String getHttpMethod() { @@ -96,6 +93,17 @@ public ResponsesMeta getResponsesMeta() { return responsesMeta; } + public int parameterCount() { + int result = 0; + if (swaggerOperation.getRequestBody() != null) { + result++; + } + if (swaggerOperation.getParameters() != null) { + result += swaggerOperation.getParameters().size(); + } + return result; + } + private ResponsesMeta cloneResponseMeta() { ResponsesMeta result = new ResponsesMeta(); this.responsesMeta.cloneTo(result); @@ -155,14 +163,6 @@ public void setExecutor(Executor executor) { this.executor = executor; } - /** - * Only for JavaChassis internal usage. - */ - @Deprecated - public Handler getProviderQpsFlowControlHandler() { - return getMicroserviceMeta().getProviderQpsFlowControlHandler(); - } - public InvocationRuntimeType buildBaseProviderRuntimeType() { SwaggerProducerOperation swaggerProducerOperation = this.getSwaggerProducerOperation(); return new InvocationRuntimeType(swaggerProducerOperation.getProducerClass(), diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/SchemaMeta.java b/core/src/main/java/org/apache/servicecomb/core/definition/SchemaMeta.java index be6ad7b4b95..623ec695b0c 100644 --- a/core/src/main/java/org/apache/servicecomb/core/definition/SchemaMeta.java +++ b/core/src/main/java/org/apache/servicecomb/core/definition/SchemaMeta.java @@ -25,14 +25,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; public class SchemaMeta { private static final Logger LOGGER = LoggerFactory.getLogger(SchemaMeta.class); private final MicroserviceMeta microserviceMeta; - private final Swagger swagger; + private final OpenAPI swagger; private final String schemaId; @@ -43,7 +43,7 @@ public class SchemaMeta { private final VendorExtensions vendorExtensions = new VendorExtensions(); - public SchemaMeta(MicroserviceMeta microserviceMeta, String schemaId, Swagger swagger) { + public SchemaMeta(MicroserviceMeta microserviceMeta, String schemaId, OpenAPI swagger) { this.microserviceMeta = microserviceMeta; this.schemaId = schemaId; this.swagger = swagger; @@ -69,7 +69,7 @@ public MicroserviceMeta getMicroserviceMeta() { return microserviceMeta; } - public Swagger getSwagger() { + public OpenAPI getSwagger() { return swagger; } diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/ServiceRegistryListener.java b/core/src/main/java/org/apache/servicecomb/core/definition/ServiceRegistryListener.java deleted file mode 100644 index 61bf36a3ea1..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/definition/ServiceRegistryListener.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.core.definition; - -import static org.apache.servicecomb.core.definition.CoreMetaUtils.CORE_MICROSERVICE_META; -import static org.apache.servicecomb.core.definition.CoreMetaUtils.CORE_MICROSERVICE_VERSION; -import static org.apache.servicecomb.core.definition.CoreMetaUtils.CORE_MICROSERVICE_VERSIONS_META; -import static org.apache.servicecomb.core.definition.CoreMetaUtils.getMicroserviceVersionsMeta; - -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.foundation.common.event.EnableExceptionPropagation; -import org.apache.servicecomb.foundation.common.event.SubscriberOrder; -import org.apache.servicecomb.registry.api.event.CreateMicroserviceEvent; -import org.apache.servicecomb.registry.api.event.CreateMicroserviceVersionEvent; -import org.apache.servicecomb.registry.api.event.DestroyMicroserviceEvent; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; -import org.apache.servicecomb.registry.definition.DefinitionConst; - -import com.google.common.eventbus.Subscribe; - -import io.swagger.models.Swagger; - -/** - * subscribe event from ServiceRegistry module to create or destroy metas - */ -public class ServiceRegistryListener { - private final SCBEngine scbEngine; - - public ServiceRegistryListener(SCBEngine scbEngine) { - this.scbEngine = scbEngine; - scbEngine.getEventBus().register(this); - } - - @EnableExceptionPropagation - @SubscriberOrder(-1000) - @Subscribe - public void onCreateMicroservice(CreateMicroserviceEvent event) { - MicroserviceVersions microserviceVersions = event.getMicroserviceVersions(); - microserviceVersions.getVendorExtensions() - .put(CORE_MICROSERVICE_VERSIONS_META, - new ConsumerMicroserviceVersionsMeta(scbEngine, microserviceVersions)); - } - - @EnableExceptionPropagation - @SubscriberOrder(-1000) - @Subscribe - public void onDestroyMicroservice(DestroyMicroserviceEvent event) { - - } - - @EnableExceptionPropagation - @SubscriberOrder(-1000) - @Subscribe - public void onCreateMicroserviceVersion(CreateMicroserviceVersionEvent event) { - // TODO:如果失败,应该标记出错,以便删除MicroserviceVersions - MicroserviceVersion microserviceVersion = event.getMicroserviceVersion(); - Microservice microservice = microserviceVersion.getMicroservice(); - - // not shortName, to support cross app invoke - String microserviceName = microserviceVersion.getMicroserviceName(); - MicroserviceMeta microserviceMeta = new MicroserviceMeta(scbEngine, microserviceName, true); - microserviceMeta.setHandlerChain(scbEngine.getConsumerHandlerManager().getOrCreate(microserviceName)); - microserviceMeta.setFilterChain(scbEngine.getFilterChainsManager().findConsumerChain(microserviceName)); - - MicroserviceVersions microserviceVersions = microserviceVersion.getMicroserviceVersions(); - microserviceMeta.setMicroserviceVersionsMeta(getMicroserviceVersionsMeta(microserviceVersions)); - - boolean isServiceCenter = DefinitionConst.REGISTRY_APP_ID.equals(microservice.getAppId()) - && DefinitionConst.REGISTRY_SERVICE_NAME.equals(microservice.getServiceName()); - // do not load service center schemas, because service center did not provide swagger,but can get schema ids.... - // service center better to resolve the problem. - if (!isServiceCenter) { - for (String schemaId : microservice.getSchemas()) { - Swagger swagger = scbEngine.getSwaggerLoader().loadSwagger(microservice, microserviceVersion.getInstances(), - schemaId); - // allow users register schemaId, but without schema contents. This is useful when cooperate with other - // non java-chassis framework. - if (swagger != null) { - microserviceMeta.registerSchemaMeta(schemaId, swagger); - } - } - } - - microserviceMeta.putExtData(CORE_MICROSERVICE_VERSION, microserviceVersion); - microserviceVersion.getVendorExtensions().put(CORE_MICROSERVICE_META, microserviceMeta); - } - - public void destroy() { - scbEngine.getEventBus().unregister(this); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationBaseEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationBaseEvent.java index 6914b31f9a7..09e2949b319 100644 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationBaseEvent.java +++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationBaseEvent.java @@ -19,7 +19,7 @@ import org.apache.servicecomb.core.Invocation; public class InvocationBaseEvent { - private Invocation invocation; + private final Invocation invocation; public InvocationBaseEvent(Invocation invocation) { this.invocation = invocation; diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationFinishEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationFinishEvent.java index 52ef72d5a1a..21a20226d01 100644 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationFinishEvent.java +++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationFinishEvent.java @@ -20,14 +20,7 @@ import org.apache.servicecomb.swagger.invocation.Response; public class InvocationFinishEvent extends InvocationWithResponseEvent { - private long nanoCurrent; - public InvocationFinishEvent(Invocation invocation, Response response) { super(invocation, response); - this.nanoCurrent = invocation.getInvocationStageTrace().getFinish(); - } - - public long getNanoCurrent() { - return nanoCurrent; } } diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationHandlersStartEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationHandlersStartEvent.java deleted file mode 100644 index a064b164855..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationHandlersStartEvent.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.core.event; - -import org.apache.servicecomb.core.Invocation; - -public class InvocationHandlersStartEvent extends InvocationBaseEvent { - public InvocationHandlersStartEvent(Invocation invocation) { - super(invocation); - } -} \ No newline at end of file diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationRunInExecutorFinishEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationRunInExecutorFinishEvent.java deleted file mode 100644 index 73ee6cd6dae..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationRunInExecutorFinishEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.core.event; - -import org.apache.servicecomb.core.Invocation; - -/** - * for async invocation, only indicate finished in executor, not finished invocation - */ -public class InvocationRunInExecutorFinishEvent extends InvocationBaseEvent { - public InvocationRunInExecutorFinishEvent(Invocation invocation) { - super(invocation); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationRunInExecutorStartEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationRunInExecutorStartEvent.java deleted file mode 100644 index 3779bde03f5..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationRunInExecutorStartEvent.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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.core.event; - -import org.apache.servicecomb.core.Invocation; - -public class InvocationRunInExecutorStartEvent extends InvocationBaseEvent { - public InvocationRunInExecutorStartEvent(Invocation invocation) { - super(invocation); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java index a5bd8c8acda..9a8770ea8ec 100644 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java +++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java @@ -23,4 +23,4 @@ public class InvocationStartSendRequestEvent extends InvocationBaseEvent { public InvocationStartSendRequestEvent(Invocation invocation) { super(invocation); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java index 168081eb855..3dc563161e8 100644 --- a/core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java +++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java @@ -23,4 +23,4 @@ public class InvocationTimeoutCheckEvent extends InvocationBaseEvent { public InvocationTimeoutCheckEvent(Invocation invocation) { super(invocation); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/CoreExceptionConfiguration.java b/core/src/main/java/org/apache/servicecomb/core/exception/CoreExceptionConfiguration.java new file mode 100644 index 00000000000..856888764a1 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/exception/CoreExceptionConfiguration.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.core.exception; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CoreExceptionConfiguration { + @Bean + public Exceptions scbExceptions() { + return new Exceptions(); + } + + @Bean + public DefaultExceptionProcessor scbDefaultExceptionProcessor() { + return new DefaultExceptionProcessor(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/DefaultExceptionProcessor.java b/core/src/main/java/org/apache/servicecomb/core/exception/DefaultExceptionProcessor.java index e18f5e8f263..e8817af521d 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/DefaultExceptionProcessor.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/DefaultExceptionProcessor.java @@ -17,9 +17,9 @@ package org.apache.servicecomb.core.exception; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.TOO_MANY_REQUESTS; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; +import static jakarta.ws.rs.core.Response.Status.TOO_MANY_REQUESTS; import static org.apache.commons.lang3.exception.ExceptionUtils.getStackTrace; import static org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_SERVER; import static org.apache.servicecomb.swagger.invocation.InvocationType.CONSUMER; @@ -29,13 +29,10 @@ import java.util.Map; import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.config.inject.InjectProperties; import org.apache.servicecomb.config.inject.InjectProperty; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.tracing.TraceIdLogger; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; @@ -46,11 +43,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import com.fasterxml.jackson.annotation.JsonIgnore; -@Component +import jakarta.ws.rs.core.Response.StatusType; + @InjectProperties(prefix = "servicecomb.invocation.exception") public class DefaultExceptionProcessor implements ExceptionProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionProcessor.class); @@ -64,7 +61,7 @@ public class DefaultExceptionProcessor implements ExceptionProcessor { .map(converter -> (ExceptionConverter) converter) .collect(Collectors.toList()); - @InjectProperty(keys = "print-stack-trace", defaultValue = "false") + @InjectProperty(keys = "print-stack-trace", defaultValue = "true") protected boolean printStackTrace; @InjectProperty(keys = "print-rate-limit", defaultValue = "false") @@ -106,17 +103,29 @@ public DefaultExceptionProcessor setConverters(List findConverter(unwrapped)) - .convert(invocation, unwrapped, genericStatus); + ExceptionConverter converter = + converterCache.computeIfAbsent(unwrapped.getClass(), clazz -> findConverter(unwrapped)); + if (invocation == null) { + LOGGER.warn("Convert unknown operation exception {}/{} using {}.", + throwable.getClass().getSimpleName(), unwrapped.getClass().getSimpleName(), + converter.getClass().getSimpleName()); + } else { + invocation.getTraceIdLogger().warn("{} Convert operation {} exception {}/{} using {}.", + TraceIdLogger.constructSource(DefaultExceptionProcessor.class.getSimpleName()), + invocation.getMicroserviceQualifiedName(), + throwable.getClass().getSimpleName(), unwrapped.getClass().getSimpleName(), + converter.getClass().getSimpleName()); + } + return converter.convert(invocation, unwrapped, genericStatus); } catch (Exception e) { LOGGER.error("BUG: ExceptionConverter.convert MUST not throw exception, please fix it.\n" + "original exception :{}" @@ -146,27 +155,29 @@ public Response toConsumerResponse(Invocation invocation, Throwable throwable) { } @Override - public void logConsumerException(@Nonnull Invocation invocation, @Nonnull InvocationException exception) { + public void logConsumerException(Invocation invocation, InvocationException exception) { if (isIgnoreLog(invocation, exception)) { return; } if (isPrintStackTrace()) { - LOGGER.error("failed to invoke {}, endpoint={}.", + invocation.getTraceIdLogger().error("{} Failed to invoke {}, endpoint={}.", + TraceIdLogger.constructSource(DefaultExceptionProcessor.class.getSimpleName()), invocation.getMicroserviceQualifiedName(), invocation.getEndpoint(), exception); return; } - LOGGER.error("failed to invoke {}, endpoint={}, message={}.", + invocation.getTraceIdLogger().error("{} Failed to invoke {}, endpoint={}, message={}.", + TraceIdLogger.constructSource(DefaultExceptionProcessor.class.getSimpleName()), invocation.getMicroserviceQualifiedName(), invocation.getEndpoint(), ExceptionUtils.getExceptionMessageWithoutTrace(exception)); } @Override - public boolean isIgnoreLog(@Nonnull Invocation invocation, @Nonnull InvocationException exception) { + public boolean isIgnoreLog(Invocation invocation, InvocationException exception) { if (!isPrintRateLimit() && exception.getStatusCode() == TOO_MANY_REQUESTS.getStatusCode()) { return true; } @@ -175,28 +186,29 @@ public boolean isIgnoreLog(@Nonnull Invocation invocation, @Nonnull InvocationEx } @Override - public Response toProducerResponse(@Nullable Invocation invocation, Throwable exception) { + public Response toProducerResponse(Invocation invocation, Throwable exception) { InvocationException invocationException = convert(invocation, exception, INTERNAL_SERVER_ERROR); if (invocation != null) { logProducerException(invocation, invocationException); } - return Response.status(invocationException.getStatus()) - .entity(invocationException.getErrorData()); + return Response.createFail(invocationException); } @Override - public void logProducerException(@Nonnull Invocation invocation, @Nonnull InvocationException exception) { + public void logProducerException(Invocation invocation, InvocationException exception) { if (isIgnoreLog(invocation, exception)) { return; } if (isPrintStackTrace()) { - LOGGER.error("failed to process {} invocation, operation={}.", + invocation.getTraceIdLogger().error("{} Failed to process {} invocation, operation={}.", + TraceIdLogger.constructSource(DefaultExceptionProcessor.class.getSimpleName()), invocation.getInvocationType(), invocation.getMicroserviceQualifiedName(), exception); return; } - LOGGER.error("failed to process {} invocation, operation={}, message={}.", + invocation.getTraceIdLogger().error("{} Failed to process {} invocation, operation={}, message={}.", + TraceIdLogger.constructSource(DefaultExceptionProcessor.class.getSimpleName()), invocation.getInvocationType(), invocation.getMicroserviceQualifiedName(), ExceptionUtils.getExceptionMessageWithoutTrace(exception)); } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionConverter.java index eedfa432523..b6424564747 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionConverter.java @@ -16,17 +16,16 @@ */ package org.apache.servicecomb.core.exception; -import static javax.ws.rs.core.Response.Status.Family.CLIENT_ERROR; +import static jakarta.ws.rs.core.Response.Status.Family.CLIENT_ERROR; import static org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_CLIENT; import static org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_SERVER; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.foundation.common.utils.SPIOrder; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import jakarta.ws.rs.core.Response.StatusType; + public interface ExceptionConverter extends SPIOrder { static boolean isClient(StatusType status) { return CLIENT_ERROR.equals(status.getFamily()); @@ -50,5 +49,5 @@ static String getGenericCode(StatusType status) { * @param genericStatus if can not determine the status type, then use this input value * @return converted invocation exception */ - InvocationException convert(@Nullable Invocation invocation, T throwable, StatusType genericStatus); + InvocationException convert(Invocation invocation, T throwable, StatusType genericStatus); } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionProcessor.java b/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionProcessor.java index 859c7a71daa..ffb3619bb41 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionProcessor.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionProcessor.java @@ -17,15 +17,13 @@ package org.apache.servicecomb.core.exception; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.core.Ordered; +import jakarta.ws.rs.core.Response.StatusType; + /** * will select the min order instance */ @@ -37,17 +35,17 @@ default int getOrder() { boolean isPrintStackTrace(); - InvocationException convert(@Nonnull Invocation invocation, Throwable throwable); + InvocationException convert(Invocation invocation, Throwable throwable); - InvocationException convert(@Nullable Invocation invocation, Throwable throwable, StatusType genericStatus); + InvocationException convert(Invocation invocation, Throwable throwable, StatusType genericStatus); - boolean isIgnoreLog(@Nonnull Invocation invocation, @Nonnull InvocationException exception); + boolean isIgnoreLog(Invocation invocation, InvocationException exception); Response toConsumerResponse(Invocation invocation, Throwable throwable); - void logConsumerException(@Nonnull Invocation invocation, @Nonnull InvocationException exception); + void logConsumerException(Invocation invocation, InvocationException exception); - Response toProducerResponse(@Nullable Invocation invocation, Throwable exception); + Response toProducerResponse(Invocation invocation, Throwable exception); - void logProducerException(@Nonnull Invocation invocation, @Nonnull InvocationException exception); + void logProducerException(Invocation invocation, InvocationException exception); } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java b/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java index 6a049b088fa..0fb8ad418a1 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/Exceptions.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.core.exception; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_CLIENT; import static org.apache.servicecomb.core.exception.ExceptionCodes.GENERIC_SERVER; import static org.apache.servicecomb.swagger.invocation.InvocationType.CONSUMER; @@ -26,18 +26,14 @@ import java.util.Comparator; import java.util.List; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -@Component +import jakarta.ws.rs.core.Response.StatusType; + public class Exceptions { private static ExceptionProcessor processor = new DefaultExceptionProcessor(); @@ -74,6 +70,9 @@ public static InvocationException consumer(String code, String msg) { } public static InvocationException consumer(String code, String msg, Throwable cause) { + if (cause instanceof InvocationException) { + return (InvocationException) cause; + } return create(BAD_REQUEST, code, msg, cause); } @@ -101,7 +100,7 @@ public static InvocationException genericProducer(String msg, Throwable cause) { return producer(GENERIC_SERVER, msg, cause); } - public static StatusType getGenericStatus(@Nonnull Invocation invocation) { + public static StatusType getGenericStatus(Invocation invocation) { return CONSUMER.equals(invocation.getInvocationType()) ? BAD_REQUEST : INTERNAL_SERVER_ERROR; } @@ -109,15 +108,15 @@ public static Response toConsumerResponse(Invocation invocation, Throwable throw return processor.toConsumerResponse(invocation, throwable); } - public static Response toProducerResponse(@Nullable Invocation invocation, Throwable exception) { + public static Response toProducerResponse(Invocation invocation, Throwable exception) { return processor.toProducerResponse(invocation, exception); } - public static InvocationException convert(@Nonnull Invocation invocation, Throwable throwable) { + public static InvocationException convert(Invocation invocation, Throwable throwable) { return processor.convert(invocation, throwable); } - public static InvocationException convert(@Nullable Invocation invocation, Throwable throwable, + public static InvocationException convert(Invocation invocation, Throwable throwable, StatusType genericStatus) { return processor.convert(invocation, throwable, genericStatus); } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/IllegalArgumentExceptionToProducerResponseConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/IllegalArgumentExceptionToProducerResponseConverter.java deleted file mode 100644 index c3c8d2e9f84..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/exception/IllegalArgumentExceptionToProducerResponseConverter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.core.exception; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class IllegalArgumentExceptionToProducerResponseConverter implements - ExceptionToProducerResponseConverter { - @Override - public Class getExceptionClass() { - return IllegalArgumentException.class; - } - - @Override - public int getOrder() { - return 10000; - } - - @Override - public Response convert(SwaggerInvocation swaggerInvocation, IllegalArgumentException e) { - InvocationException invocationException = new InvocationException(Status.BAD_REQUEST.getStatusCode(), "", - new CommonExceptionData("Parameters not valid or types not match."), e); - return Response.failResp(invocationException); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ThrowableExceptionToProducerResponseConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/ThrowableExceptionToProducerResponseConverter.java deleted file mode 100644 index 4ffa2ec9e99..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/exception/ThrowableExceptionToProducerResponseConverter.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.core.exception; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class ThrowableExceptionToProducerResponseConverter implements ExceptionToProducerResponseConverter { - @Override - public Class getExceptionClass() { - return Throwable.class; - } - - @Override - public int getOrder() { - return 20000; - } - - @Override - public Response convert(SwaggerInvocation swaggerInvocation, Throwable e) { - InvocationException invocationException = new InvocationException(Status.INTERNAL_SERVER_ERROR.getStatusCode(), "", - new CommonExceptionData("Unexpected exception when processing the request."), e); - return Response.failResp(invocationException); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConnectTimeoutExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConnectTimeoutExceptionConverter.java index 961eb4f477d..72507d0a3ba 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConnectTimeoutExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConnectTimeoutExceptionConverter.java @@ -16,10 +16,7 @@ */ package org.apache.servicecomb.core.exception.converter; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; - -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.ExceptionConverter; @@ -28,6 +25,7 @@ import org.slf4j.LoggerFactory; import io.netty.channel.ConnectTimeoutException; +import jakarta.ws.rs.core.Response.StatusType; public class ConnectTimeoutExceptionConverter implements ExceptionConverter { private static final Logger LOGGER = LoggerFactory.getLogger(ConnectTimeoutExceptionConverter.class); @@ -45,7 +43,7 @@ public boolean canConvert(Throwable throwable) { } @Override - public InvocationException convert(@Nullable Invocation invocation, ConnectTimeoutException throwable, + public InvocationException convert(Invocation invocation, ConnectTimeoutException throwable, StatusType genericStatus) { // throwable.getMessage: // connection timed out: /1.1.1.1:8080 diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConstraintViolationExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConstraintViolationExceptionConverter.java index c2e08344ef4..2898d4914ae 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConstraintViolationExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/ConstraintViolationExceptionConverter.java @@ -16,41 +16,27 @@ */ package org.apache.servicecomb.core.exception.converter; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; import static org.apache.servicecomb.core.exception.ExceptionCodes.DEFAULT_VALIDATE; import java.util.List; import java.util.stream.Collectors; -import javax.validation.ConstraintViolationException; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import com.google.common.annotations.VisibleForTesting; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.DynamicStringProperty; +import jakarta.validation.ConstraintViolationException; +import jakarta.ws.rs.core.Response.StatusType; public class ConstraintViolationExceptionConverter implements ExceptionConverter { public static final int ORDER = Short.MAX_VALUE; public static final String KEY_CODE = "servicecomb.filters.validate.code"; - private DynamicStringProperty code; - public ConstraintViolationExceptionConverter() { - refreshCode(); - } - - /** - * during UT, DynamicPropertyFactory will be reset, this caused code can not changed by event - */ - @VisibleForTesting - public void refreshCode() { - code = DynamicPropertyFactory.getInstance().getStringProperty(KEY_CODE, DEFAULT_VALIDATE); } @Override @@ -70,7 +56,8 @@ public InvocationException convert(Invocation invocation, ConstraintViolationExc .map(violation -> new ValidateDetail(violation.getPropertyPath().toString(), violation.getMessage())) .collect(Collectors.toList()); - CommonExceptionData exceptionData = new CommonExceptionData(code.get(), "invalid parameters."); + CommonExceptionData exceptionData = new CommonExceptionData(SCBEngine.getInstance().getEnvironment(). + getProperty(KEY_CODE, String.class, DEFAULT_VALIDATE), "invalid parameters."); exceptionData.putDynamic("validateDetail", details); return new InvocationException(BAD_REQUEST, exceptionData); } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/DefaultExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/DefaultExceptionConverter.java index b48bdb4e609..d0338d43628 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/converter/DefaultExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/DefaultExceptionConverter.java @@ -16,14 +16,11 @@ */ package org.apache.servicecomb.core.exception.converter; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + +import jakarta.ws.rs.core.Response.StatusType; /** *
@@ -38,8 +35,6 @@
  * 
*/ public class DefaultExceptionConverter implements ExceptionConverter { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultExceptionConverter.class); - public static final int ORDER = Integer.MAX_VALUE; @Override @@ -53,14 +48,9 @@ public boolean canConvert(Throwable throwable) { } @Override - public InvocationException convert(@Nullable Invocation invocation, Throwable throwable, StatusType genericStatus) { - String msg = throwable.getMessage(); - if (msg == null) { - msg = "Unexpected exception when processing."; - } - - LOGGER.error("convert unknown exception({}) to InvocationException, message={}.", - throwable.getClass().getName(), msg); + public InvocationException convert(Invocation invocation, Throwable throwable, StatusType genericStatus) { + String msg = String.format("Unexpected exception when processing %s. %s", + invocation == null ? "none" : invocation.getMicroserviceQualifiedName(), throwable.getMessage()); return new InvocationException(genericStatus, ExceptionConverter.getGenericCode(genericStatus), msg, throwable); } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/IllegalArgumentExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/IllegalArgumentExceptionConverter.java index 8725ce13679..f80f1a82519 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/converter/IllegalArgumentExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/IllegalArgumentExceptionConverter.java @@ -16,13 +16,12 @@ */ package org.apache.servicecomb.core.exception.converter; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import jakarta.ws.rs.core.Response.StatusType; + public class IllegalArgumentExceptionConverter implements ExceptionConverter { public static final int ORDER = Short.MAX_VALUE; @@ -37,7 +36,7 @@ public boolean canConvert(Throwable throwable) { } @Override - public InvocationException convert(@Nullable Invocation invocation, IllegalArgumentException throwable, + public InvocationException convert(Invocation invocation, IllegalArgumentException throwable, StatusType genericStatus) { return new InvocationException(genericStatus, ExceptionConverter.getGenericCode(genericStatus), "Parameters not valid or types not match.", throwable); diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/InvocationExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/InvocationExceptionConverter.java index 0a7d2714b79..830aec3190c 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/converter/InvocationExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/InvocationExceptionConverter.java @@ -16,13 +16,12 @@ */ package org.apache.servicecomb.core.exception.converter; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import jakarta.ws.rs.core.Response.StatusType; + public class InvocationExceptionConverter implements ExceptionConverter { public static final int ORDER = Byte.MAX_VALUE; @@ -37,7 +36,7 @@ public boolean canConvert(Throwable throwable) { } @Override - public InvocationException convert(@Nullable Invocation invocation, InvocationException throwable, + public InvocationException convert(Invocation invocation, InvocationException throwable, StatusType genericStatus) { return throwable; } diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/ServiceCombExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/ServiceCombExceptionConverter.java new file mode 100644 index 00000000000..9a69f4c988c --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/ServiceCombExceptionConverter.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.core.exception.converter; + +import java.util.concurrent.TimeoutException; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.exception.ExceptionConverter; +import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.StatusType; + +public class ServiceCombExceptionConverter implements ExceptionConverter { + public static final int ORDER = Byte.MAX_VALUE; + + private TimeoutExceptionConverter timeoutExceptionConverter = new TimeoutExceptionConverter(); + + @Override + public int getOrder() { + return ORDER; + } + + @Override + public boolean canConvert(Throwable throwable) { + return throwable instanceof ServiceCombException; + } + + @Override + public InvocationException convert(Invocation invocation, ServiceCombException throwable, + StatusType genericStatus) { + if (throwable.getCause() instanceof TimeoutException) { + return timeoutExceptionConverter.convert(invocation, (TimeoutException) throwable.getCause(), genericStatus); + } + + return new InvocationException(Status.INTERNAL_SERVER_ERROR, + ExceptionConverter.getGenericCode(genericStatus), throwable.getMessage(), + throwable); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverter.java b/core/src/main/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverter.java index 0059e7f4fe5..31d48a82933 100644 --- a/core/src/main/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverter.java +++ b/core/src/main/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverter.java @@ -16,19 +16,18 @@ */ package org.apache.servicecomb.core.exception.converter; -import static javax.ws.rs.core.Response.Status.REQUEST_TIMEOUT; +import static jakarta.ws.rs.core.Response.Status.REQUEST_TIMEOUT; import java.util.concurrent.TimeoutException; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jakarta.ws.rs.core.Response.StatusType; + public class TimeoutExceptionConverter implements ExceptionConverter { private static final Logger LOGGER = LoggerFactory.getLogger(TimeoutExceptionConverter.class); @@ -45,7 +44,7 @@ public boolean canConvert(Throwable throwable) { } @Override - public InvocationException convert(@Nullable Invocation invocation, TimeoutException throwable, + public InvocationException convert(Invocation invocation, TimeoutException throwable, StatusType genericStatus) { // throwable.getMessage: // The timeout period of 30000ms has been exceeded while executing GET /xxx for server 1.1.1.1:8080 diff --git a/core/src/main/java/org/apache/servicecomb/core/executor/ExecutorManager.java b/core/src/main/java/org/apache/servicecomb/core/executor/ExecutorManager.java index bfa38ef888b..f03547c171a 100644 --- a/core/src/main/java/org/apache/servicecomb/core/executor/ExecutorManager.java +++ b/core/src/main/java/org/apache/servicecomb/core/executor/ExecutorManager.java @@ -23,26 +23,37 @@ import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; -import com.netflix.config.DynamicPropertyFactory; - -public class ExecutorManager { +public final class ExecutorManager { public static final String KEY_EXECUTORS_PREFIX = "servicecomb.executors.Provider."; public static final String KEY_EXECUTORS_DEFAULT = "servicecomb.executors.default"; - public static final String EXECUTOR_GROUP_THREADPOOL = "servicecomb.executor.groupThreadPool"; + public static final String EXECUTOR_GROUP_THREAD_POOL = "servicecomb.executor.groupThreadPool"; public static final String EXECUTOR_REACTIVE = "servicecomb.executor.reactive"; - public static final String EXECUTOR_DEFAULT = EXECUTOR_GROUP_THREADPOOL; + private final Map executors = new ConcurrentHashMapEx<>(); + + static String EXECUTOR_DEFAULT = EXECUTOR_GROUP_THREAD_POOL; + + public static void setExecutorDefault(String executorDefault) { + EXECUTOR_DEFAULT = executorDefault; + } - private Map executors = new ConcurrentHashMapEx<>(); + private Environment environment; public ExecutorManager() { registerExecutor(EXECUTOR_REACTIVE, new ReactiveExecutor()); } + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + public void registerExecutor(String id, Executor executor) { Executor existing = executors.putIfAbsent(id, executor); if (existing != null) { @@ -100,8 +111,8 @@ public Executor findExecutor(OperationMeta operationMeta, Executor defaultOperat return findExecutorById(EXECUTOR_DEFAULT); } - protected Executor findByKey(String configKey) { - String id = DynamicPropertyFactory.getInstance().getStringProperty(configKey, null).get(); + private Executor findByKey(String configKey) { + String id = environment.getProperty(configKey); if (id == null) { return null; } diff --git a/core/src/main/java/org/apache/servicecomb/core/executor/GroupExecutor.java b/core/src/main/java/org/apache/servicecomb/core/executor/GroupExecutor.java index 535b8a2f68c..13562914fac 100644 --- a/core/src/main/java/org/apache/servicecomb/core/executor/GroupExecutor.java +++ b/core/src/main/java/org/apache/servicecomb/core/executor/GroupExecutor.java @@ -30,8 +30,7 @@ import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicPropertyFactory; +import org.springframework.core.env.Environment; public class GroupExecutor implements Executor, Closeable { private static final Logger LOGGER = LoggerFactory.getLogger(GroupExecutor.class); @@ -51,6 +50,8 @@ public class GroupExecutor implements Executor, Closeable { private static final AtomicBoolean LOG_PRINTED = new AtomicBoolean(); + private final Environment environment; + protected String groupName; protected int groupCount; @@ -64,13 +65,17 @@ public class GroupExecutor implements Executor, Closeable { protected int maxQueueSize; // to avoid multiple network thread conflicted when put tasks to executor queue - private List executorList = new ArrayList<>(); + private final List executorList = new ArrayList<>(); // for bind network thread to one executor // it's impossible that has too many network thread, so index will not too big that less than 0 - private AtomicInteger index = new AtomicInteger(); + private final AtomicInteger index = new AtomicInteger(); - private Map threadExecutorMap = new ConcurrentHashMapEx<>(); + private final Map threadExecutorMap = new ConcurrentHashMapEx<>(); + + public GroupExecutor(Environment environment) { + this.environment = environment; + } public GroupExecutor init() { return init("group"); @@ -95,7 +100,7 @@ public GroupExecutor init(String groupName) { return this; } - public void initConfig() { + public synchronized void initConfig() { if (LOG_PRINTED.compareAndSet(false, true)) { LOGGER.info("thread pool rules:\n" + "1.use core threads.\n" @@ -104,12 +109,12 @@ public void initConfig() { + "4.if queue is full, and threads count is max, then reject the request."); } - groupCount = DynamicPropertyFactory.getInstance().getIntProperty(KEY_GROUP, 2).get(); - coreThreads = DynamicPropertyFactory.getInstance().getIntProperty(KEY_CORE_THREADS, 25).get(); + groupCount = environment.getProperty(KEY_GROUP, int.class, 2); + coreThreads = environment.getProperty(KEY_CORE_THREADS, int.class, 25); - maxThreads = DynamicPropertyFactory.getInstance().getIntProperty(KEY_MAX_THREADS, -1).get(); + maxThreads = environment.getProperty(KEY_MAX_THREADS, int.class, -1); if (maxThreads <= 0) { - maxThreads = DynamicPropertyFactory.getInstance().getIntProperty(KEY_OLD_MAX_THREAD, -1).get(); + maxThreads = environment.getProperty(KEY_OLD_MAX_THREAD, int.class, -1); if (maxThreads > 0) { LOGGER.warn("{} is deprecated, recommended to use {}.", KEY_OLD_MAX_THREAD, KEY_MAX_THREADS); } else { @@ -121,8 +126,8 @@ public void initConfig() { coreThreads = maxThreads; } - maxIdleInSecond = DynamicPropertyFactory.getInstance().getIntProperty(KEY_MAX_IDLE_SECOND, 60).get(); - maxQueueSize = DynamicPropertyFactory.getInstance().getIntProperty(KEY_MAX_QUEUE_SIZE, Integer.MAX_VALUE).get(); + maxIdleInSecond = environment.getProperty(KEY_MAX_IDLE_SECOND, int.class, 60); + maxQueueSize = environment.getProperty(KEY_MAX_QUEUE_SIZE, int.class, Integer.MAX_VALUE); LOGGER.info( "executor name={}, group={}. per group settings, coreThreads={}, maxThreads={}, maxIdleInSecond={}, maxQueueSize={}.", diff --git a/core/src/main/java/org/apache/servicecomb/core/executor/GroupThreadFactory.java b/core/src/main/java/org/apache/servicecomb/core/executor/GroupThreadFactory.java index cf08f609098..e6dbfb27227 100644 --- a/core/src/main/java/org/apache/servicecomb/core/executor/GroupThreadFactory.java +++ b/core/src/main/java/org/apache/servicecomb/core/executor/GroupThreadFactory.java @@ -32,9 +32,7 @@ public class GroupThreadFactory implements ThreadFactory { public GroupThreadFactory(String prefix) { Objects.requireNonNull(prefix); - SecurityManager s = System.getSecurityManager(); - group = (s != null) ? s.getThreadGroup() : - Thread.currentThread().getThreadGroup(); + group = Thread.currentThread().getThreadGroup(); namePrefix = prefix + "-" + poolNumber.getAndIncrement() + "-thread-"; } diff --git a/core/src/main/java/org/apache/servicecomb/core/executor/ThreadPoolExecutorEx.java b/core/src/main/java/org/apache/servicecomb/core/executor/ThreadPoolExecutorEx.java index c8e5b116dcd..7249e6e7e18 100644 --- a/core/src/main/java/org/apache/servicecomb/core/executor/ThreadPoolExecutorEx.java +++ b/core/src/main/java/org/apache/servicecomb/core/executor/ThreadPoolExecutorEx.java @@ -24,11 +24,11 @@ import java.util.concurrent.atomic.AtomicInteger; public class ThreadPoolExecutorEx extends ThreadPoolExecutor { - private AtomicInteger submittedCount = new AtomicInteger(); + private final AtomicInteger submittedCount = new AtomicInteger(); - private AtomicInteger finishedCount = new AtomicInteger(); + private final AtomicInteger finishedCount = new AtomicInteger(); - private AtomicInteger rejectedCount = new AtomicInteger(); + private final AtomicInteger rejectedCount = new AtomicInteger(); public ThreadPoolExecutorEx(int coreThreads, int maxThreads, int maxIdleInSecond, TimeUnit timeUnit, BlockingQueue queue, ThreadFactory threadFactory) { diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/AbstractFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/AbstractFilter.java new file mode 100644 index 00000000000..17d555fc8d1 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/AbstractFilter.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.core.filter; + +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; + +public abstract class AbstractFilter implements Filter, EnvironmentAware { + private static final String ORDER_KEY = "servicecomb.filter.%s.%s.%s.order"; + + private static final String ENABLE_KEY = "servicecomb.filter.%s.%s.%s.enabled"; + + protected Environment environment; + + private String nameWithOrder; + + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + public int getOrder(String application, String serviceName) { + Integer custom = environment.getProperty(String.format(ORDER_KEY, getName(), application, serviceName), + Integer.class); + if (custom != null) { + return custom; + } + return getOrder(); + } + + @Override + public boolean enabledForMicroservice(String application, String serviceName) { + Boolean custom = environment.getProperty(String.format(ENABLE_KEY, getName(), application, serviceName), + Boolean.class); + if (custom != null) { + return custom; + } + return true; + } + + @Override + public String getNameWithOrder() { + if (nameWithOrder == null) { + nameWithOrder = String.format("F(%1$06d)-%2$s", getOrder(), getName()); + } + return nameWithOrder; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java index 2ede1f02503..de13aa0ac2e 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java @@ -16,17 +16,6 @@ */ package org.apache.servicecomb.core.filter; -import java.util.Collections; -import java.util.List; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.swagger.invocation.InvocationType; - public interface ConsumerFilter extends Filter { - @Nonnull - @Override - default List getInvocationTypes() { - return Collections.singletonList(InvocationType.CONSUMER); - } + } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java b/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java new file mode 100644 index 00000000000..0d9ce402624 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.core.filter; + +import org.apache.servicecomb.core.filter.impl.ContextMapperFilter; +import org.apache.servicecomb.core.filter.impl.ParameterValidatorFilter; +import org.apache.servicecomb.core.filter.impl.ProviderOperationFilter; +import org.apache.servicecomb.core.filter.impl.RetryFilter; +import org.apache.servicecomb.core.filter.impl.ScheduleFilter; +import org.apache.servicecomb.governance.handler.MapperHandler; +import org.apache.servicecomb.governance.handler.RetryHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CoreFilterConfiguration { + @Bean + public ProviderOperationFilter scbProducerOperationFilter() { + return new ProviderOperationFilter(); + } + + @Bean + public ScheduleFilter scbScheduleFilter() { + return new ScheduleFilter(); + } + + @Bean + public RetryFilter scbRetryFilter(RetryHandler retryHandler) { + return new RetryFilter(retryHandler); + } + + @Bean + public ContextMapperFilter scbContextMapperFilter(MapperHandler mapperHandler) { + return new ContextMapperFilter(mapperHandler); + } + + @Bean + public FilterChainsManager scbFilterChainsManager() { + return new FilterChainsManager(); + } + + @Bean + public ParameterValidatorFilter scbParameterValidatorFilter() { + return new ParameterValidatorFilter(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/EdgeFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/EdgeFilter.java new file mode 100644 index 00000000000..70d8bef4ef5 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/EdgeFilter.java @@ -0,0 +1,21 @@ +/* + * 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.core.filter; + +public interface EdgeFilter extends Filter { + +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java b/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java index 6ea36313214..99ed798e686 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java @@ -16,26 +16,18 @@ */ package org.apache.servicecomb.core.filter; -import java.util.Arrays; -import java.util.List; import java.util.concurrent.CompletableFuture; -import javax.annotation.Nonnull; - import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.provider.consumer.InvokerUtils; -import org.apache.servicecomb.swagger.invocation.InvocationType; import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.core.Ordered; /** *
- * unified extension for replace old version extensions:
- *   1. Handler
- *   2. HttpClientFilter
- *   3. HttpServerFilter
+ *  Filters are the basics of how an invocation is executed.
  *
  * thread rule:
- *   assume a producer filter chains is: f1, f2, schedule, f3, f4
+ *   assume a provider filter chains is: f1, f2, schedule, f3, f4
  *
  *   schedule is a builtIn filter, which will dispatch invocations to operation related threadPool
  *
@@ -55,29 +47,33 @@
  *        (reactive golden rule)
  * 
*/ -public interface Filter { - default boolean isEnabled() { +public interface Filter extends Ordered { + int PROVIDER_SCHEDULE_FILTER_ORDER = 0; + + int CONSUMER_LOAD_BALANCE_ORDER = 0; + + default boolean enabledForTransport(String transport) { return true; } - default boolean isInEventLoop() { - return InvokerUtils.isInEventLoop(); + default boolean enabledForMicroservice(String application, String serviceName) { + return true; } - @Nonnull - default String getName() { - throw new IllegalStateException("must provide filter name."); + default int getOrder(String application, String serviceName) { + return 0; } - /** - * - * @return can be used for the specific invocation type - */ - @Nonnull - default List getInvocationTypes() { - return Arrays.asList(InvocationType.CONSUMER, InvocationType.PRODUCER); + default int getOrder() { + return 0; + } + + default String getName() { + throw new IllegalStateException("must provide unique filter name."); } + String getNameWithOrder(); + /** * * @param invocation invocation @@ -88,7 +84,8 @@ default List getInvocationTypes() { * all fail data can only express by exception
*
* special for producer:
- * if response is failure, then after encode response, response.result will be exception.errorData, not a exception + * if response is failure, then after encode response, response.result will + * be exception.errorData, not a exception */ CompletableFuture onFilter(Invocation invocation, FilterNode nextNode); } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java b/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java index 962e371184f..2cc6281d018 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java @@ -20,56 +20,49 @@ import static org.apache.servicecomb.foundation.common.utils.StringBuilderUtils.deleteLast; import java.util.List; -import java.util.Map.Entry; import java.util.stream.Collectors; -import org.apache.servicecomb.core.filter.config.FilterChainsConfig; -import org.apache.servicecomb.swagger.invocation.InvocationType; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -@Component public class FilterChainsManager { - private final FilterChainsConfig chainsConfig = new FilterChainsConfig(); + private InvocationFilterChains consumerChains; - private final InvocationFilterChains consumerChains = new InvocationFilterChains(); + private InvocationFilterChains providerChains; - private final InvocationFilterChains producerChains = new InvocationFilterChains(); + private InvocationFilterChains edgeChains; @Autowired - public FilterChainsManager addFilters(List filters) { - for (Filter filter : filters) { - if (filter.getInvocationTypes().contains(InvocationType.CONSUMER)) { - consumerChains.addFilter(filter); - } + public FilterChainsManager setEdgeFilters(List filters) { + edgeChains = new InvocationFilterChains(filters); + return this; + } - if (filter.getInvocationTypes().contains(InvocationType.PRODUCER)) { - producerChains.addFilter(filter); - } - } + @Autowired + public FilterChainsManager setConsumerFilters(List filters) { + consumerChains = new InvocationFilterChains(filters); + return this; + } + @Autowired + public FilterChainsManager setProviderFilters(List filters) { + providerChains = new InvocationFilterChains(filters); return this; } public FilterChainsManager init() { - chainsConfig.load(); - - consumerChains.resolve(chainsConfig.getResolver(), chainsConfig.getConsumer()); - producerChains.resolve(chainsConfig.getResolver(), chainsConfig.getProducer()); - return this; } - public boolean isEnabled() { - return chainsConfig.isEnabled(); + public FilterNode findConsumerChain(String application, String serviceName) { + return consumerChains.findChain(application, serviceName); } - public FilterNode findConsumerChain(String microserviceName) { - return consumerChains.findChain(microserviceName); + public FilterNode findProducerChain(String application, String serviceName) { + return providerChains.findChain(application, serviceName); } - public FilterNode findProducerChain(String microserviceName) { - return producerChains.findChain(microserviceName); + public FilterNode findEdgeChain(String application, String serviceName) { + return edgeChains.findChain(application, serviceName); } public String collectResolvedChains() { @@ -77,28 +70,19 @@ public String collectResolvedChains() { appendLine(sb, "consumer: "); appendLine(sb, " filters: %s", collectFilterNames(consumerChains)); - collectChainsByInvocationType(sb, consumerChains); appendLine(sb, "producer: "); - appendLine(sb, " filters: %s", collectFilterNames(producerChains)); - collectChainsByInvocationType(sb, producerChains); + appendLine(sb, " filters: %s", collectFilterNames(providerChains)); + + appendLine(sb, "edge: "); + appendLine(sb, " filters: %s", collectFilterNames(edgeChains)); return deleteLast(sb, 1).toString(); } - public List collectFilterNames(InvocationFilterChains chains) { + private List collectFilterNames(InvocationFilterChains chains) { return chains.getFilters().stream() - .filter(filter -> !(filter instanceof InternalFilter)) - .map(Filter::getName) + .map(filter -> filter.getName() + "(" + filter.getOrder() + ")") .collect(Collectors.toList()); } - - private void collectChainsByInvocationType(StringBuilder sb, InvocationFilterChains chains) { - appendLine(sb, " chains:"); - appendLine(sb, " framework: %s", chains.getResolvedFrameworkConfig()); - appendLine(sb, " default : %s", chains.getResolvedDefaultConfig()); - for (Entry> entry : chains.getResolvedMicroserviceConfig().entrySet()) { - appendLine(sb, " %s: %s", entry.getKey(), entry.getValue()); - } - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java b/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java index bc6bda0a0bf..44a5b34d901 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java @@ -19,10 +19,8 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.filter.impl.TransportFilters; import org.apache.servicecomb.foundation.common.utils.AsyncUtils; import org.apache.servicecomb.swagger.invocation.Response; @@ -40,31 +38,17 @@ public static FilterNode buildChain(Filter... filters) { public static FilterNode buildChain(List filters) { List filterNodes = filters.stream() - .map(FilterNode::new) - .collect(Collectors.toList()); + .map(FilterNode::new).toList(); for (int idx = 0; idx < filterNodes.size() - 1; idx++) { FilterNode currentNode = filterNodes.get(idx); FilterNode nextNode = filterNodes.get(idx + 1); currentNode.setNextNode(nextNode); - - if (currentNode.filter instanceof TransportFilters) { - mergeToChain((TransportFilters) currentNode.filter, nextNode); - } } return filterNodes.get(0); } - private static void mergeToChain(TransportFilters filter, FilterNode nextNode) { - for (FilterNode node : filter.getChainByTransport().values()) { - while (node.nextNode != null) { - node = node.nextNode; - } - node.nextNode = nextNode; - } - } - private final Filter filter; private FilterNode nextNode; @@ -78,19 +62,14 @@ private void setNextNode(FilterNode nextNode) { } public CompletableFuture onFilter(Invocation invocation) { - if (!filter.isEnabled()) { + // When transport name is empty, maybe edge transport filters need to be executed. + // Can't set Endpoint before load balance in edge. + if (invocation.getTransportName() != null && !filter.enabledForTransport(invocation.getTransportName())) { return nextNode.onFilter(invocation); } - return AsyncUtils.tryCatchSupplierFuture(() -> filter.onFilter(invocation, nextNode)) - .thenApply(this::rethrowExceptionInResponse); - } - - private Response rethrowExceptionInResponse(Response response) { - if (response.isFailed() && response.getResult() instanceof Throwable) { - AsyncUtils.rethrow(response.getResult()); - } - - return response; + String stage = invocation.getInvocationStageTrace().recordStageBegin(this.filter.getNameWithOrder()); + return AsyncUtils.tryCatchSupplierFuture(() -> filter.onFilter(invocation, nextNode) + .whenComplete((r, e) -> invocation.getInvocationStageTrace().recordStageEnd(stage))); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/InternalFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/InternalFilter.java deleted file mode 100644 index a79032def5d..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/InternalFilter.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * 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.core.filter; - -public interface InternalFilter extends Filter { -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java b/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java index c7191664775..6dde66c3354 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java @@ -14,100 +14,38 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.apache.servicecomb.core.filter; -import java.util.Collection; -import java.util.HashMap; +import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.function.Function; import java.util.stream.Collectors; -import org.apache.servicecomb.core.filter.config.InvocationFilterChainsConfig; -import org.apache.servicecomb.core.filter.config.TransportChainsConfig; -import org.apache.servicecomb.core.filter.impl.TransportFilters; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; public class InvocationFilterChains { - private final Map filters = new HashMap<>(); - - private List resolvedFrameworkConfig; - - private List resolvedDefaultConfig; - - private final Map> resolvedMicroserviceConfig = new HashMap<>(); - - private FilterNode defaultChain; - - private final Map microserviceChains = new HashMap<>(); - - public Collection getFilters() { - return filters.values(); - } - - public void addFilter(Filter filter) { - filters.put(filter.getName(), filter); - } - - public List getResolvedFrameworkConfig() { - return resolvedFrameworkConfig; - } - public List getResolvedDefaultConfig() { - return resolvedDefaultConfig; - } - - public Map> getResolvedMicroserviceConfig() { - return resolvedMicroserviceConfig; - } - - public void resolve(Function, List> resolver, - InvocationFilterChainsConfig config) { - resolvedFrameworkConfig = resolver.apply(config.getFrameworkChain()); - resolvedDefaultConfig = resolver.apply(config.getDefaultChain()); - - defaultChain = createChain(resolvedDefaultConfig); - for (Entry> entry : config.getMicroserviceChains().entrySet()) { - List resolveConfig = resolver.apply(entry.getValue()); - - resolvedMicroserviceConfig.put(entry.getKey(), resolveConfig); - microserviceChains.put(entry.getKey(), createChain(resolveConfig)); - } - } - - private FilterNode createChain(List chain) { - List filters = createFilters(chain); - return FilterNode.buildChain(filters); - } - - private List createFilters(List chain) { - return chain.stream() - .map(this::findFilter) - .collect(Collectors.toList()); - } + private final List filters; - private Filter findFilter(Object filterConfig) { - if (filterConfig instanceof TransportChainsConfig) { - return createTransportFilter((TransportChainsConfig) filterConfig); - } + private final Map> microserviceChains = new ConcurrentHashMapEx<>(); - Filter filter = filters.get(filterConfig); - if (filter == null) { - throw new IllegalStateException("failed to find filter, name=" + filterConfig); - } - return filter; + public InvocationFilterChains(List filters) { + this.filters = filters; } - private Filter createTransportFilter(TransportChainsConfig config) { - TransportFilters transportFilters = new TransportFilters(); - for (Entry> entry : config.getChainByTransport().entrySet()) { - List filters = createFilters(entry.getValue()); - transportFilters.getChainByTransport().put(entry.getKey(), FilterNode.buildChain(filters)); - } - return transportFilters; + public List getFilters() { + return filters; } - public FilterNode findChain(String microserviceName) { - return microserviceChains.getOrDefault(microserviceName, defaultChain); + public FilterNode findChain(String application, String serviceName) { + return microserviceChains.computeIfAbsent(application, key -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(serviceName, (serviceNameInner) -> { + List serviceFilters = filters.stream() + .filter(e -> e.enabledForMicroservice(application, serviceName)) + .sorted(Comparator.comparingInt(a -> a.getOrder(application, serviceName))) + .collect(Collectors.toList()); + return FilterNode.buildChain(serviceFilters); + }); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java deleted file mode 100644 index 969e4252f67..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.core.filter; - -import java.util.Collections; -import java.util.List; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.swagger.invocation.InvocationType; - -public interface ProducerFilter extends Filter { - @Nonnull - @Override - default List getInvocationTypes() { - return Collections.singletonList(InvocationType.PRODUCER); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/ProviderFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/ProviderFilter.java new file mode 100644 index 00000000000..6d5edd7814e --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/ProviderFilter.java @@ -0,0 +1,21 @@ +/* + * 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.core.filter; + +public interface ProviderFilter extends Filter { + +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/AbstractFilterChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/AbstractFilterChainsConfig.java deleted file mode 100644 index 125724510e4..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/config/AbstractFilterChainsConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.core.filter.config; - -import java.util.function.Consumer; - -import org.apache.commons.configuration.Configuration; - -import com.netflix.config.DynamicPropertyFactory; - -public class AbstractFilterChainsConfig { - public static final String ROOT = "servicecomb.filter-chains."; - - protected final Configuration config = (Configuration) DynamicPropertyFactory.getBackingConfigurationSource(); - - protected void loadKeys(String root, Consumer loadKey) { - config.getKeys(root).forEachRemaining(loadKey); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/FilterChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/FilterChainsConfig.java deleted file mode 100644 index db364c2a9f1..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/config/FilterChainsConfig.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.core.filter.config; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.servicecomb.config.ConfigUtil; - -public class FilterChainsConfig extends AbstractFilterChainsConfig { - public static final String TRANSPORT_ROOT = ROOT + "transport"; - - public static final String DEFINITION_ROOT = ROOT + "definition"; - - // key is chain name - private final Map transportChains = new HashMap<>(); - - private final Map> definitions = new HashMap<>(); - - private InvocationFilterChainsConfig consumer; - - private InvocationFilterChainsConfig producer; - - private boolean enabled; - - public void load() { - enabled = config.getBoolean(ROOT + "enabled", false); - - loadKeys(TRANSPORT_ROOT, this::loadTransportChain); - loadKeys(DEFINITION_ROOT, this::loadDefinitionChain); - - consumer = new InvocationFilterChainsConfig(ROOT + "consumer"); - producer = new InvocationFilterChainsConfig(ROOT + "producer"); - } - - private void loadTransportChain(String qualifiedKey) { - String qualifiedName = qualifiedKey.substring(TRANSPORT_ROOT.length() + 1); - int dotIdx = qualifiedName.indexOf('.'); - String chainName = qualifiedName.substring(0, dotIdx); - String transport = qualifiedName.substring(dotIdx + 1); - - transportChains.computeIfAbsent(chainName, key -> new TransportChainsConfig()) - .add(transport, ConfigUtil.getStringList(config, qualifiedKey)); - } - - private void loadDefinitionChain(String qualifiedKey) { - String chainName = qualifiedKey.substring(DEFINITION_ROOT.length() + 1); - - definitions.put(chainName, ConfigUtil.getStringList(config, qualifiedKey)); - } - - public boolean isEnabled() { - return enabled; - } - - public InvocationFilterChainsConfig getConsumer() { - return consumer; - } - - public InvocationFilterChainsConfig getProducer() { - return producer; - } - - public Function, List> getResolver() { - return this::resolveChain; - } - - private List resolveChain(List chain) { - return chain.stream() - .flatMap(filterOrReference -> resolveFilterOrReference(filterOrReference).stream()) - .collect(Collectors.toList()); - } - - private List resolveFilterOrReference(String filterOrReference) { - TransportChainsConfig transportChain = transportChains.get(filterOrReference); - if (transportChain != null) { - return Collections.singletonList(transportChain); - } - - List chain = definitions.get(filterOrReference); - if (chain == null) { - return Collections.singletonList(filterOrReference); - } - - return resolveChain(chain); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/InvocationFilterChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/InvocationFilterChainsConfig.java deleted file mode 100644 index 417aea5a784..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/config/InvocationFilterChainsConfig.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.core.filter.config; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.config.ConfigUtil; -import org.springframework.util.CollectionUtils; - -public class InvocationFilterChainsConfig extends AbstractFilterChainsConfig { - private final String policiesRoot; - - private final List frameworkChain; - - private final List defaultChain; - - private final Map> microserviceChains = new HashMap<>(); - - public InvocationFilterChainsConfig(String root) { - frameworkChain = ConfigUtil.getStringList(config, root + ".framework"); - defaultChain = loadDefaultChain(root); - - policiesRoot = root + ".policies"; - loadKeys(policiesRoot, this::loadPolicies); - } - - private List loadDefaultChain(String root) { - String defaultChainKey = root + ".default"; - List defaultChain = ConfigUtil.getStringList(config, defaultChainKey); - if (CollectionUtils.isEmpty(defaultChain) && config.getProperty(defaultChainKey) == null) { - defaultChain = frameworkChain; - } - return defaultChain; - } - - private void loadPolicies(String qualifiedKey) { - String microserviceName = qualifiedKey.substring(policiesRoot.length() + 1); - - microserviceChains.put(microserviceName, ConfigUtil.getStringList(config, qualifiedKey)); - } - - public List getFrameworkChain() { - return frameworkChain; - } - - public List getDefaultChain() { - return defaultChain; - } - - public Map> getMicroserviceChains() { - return microserviceChains; - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/TransportChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/TransportChainsConfig.java deleted file mode 100644 index 5ef2dcd8c4b..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/config/TransportChainsConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.core.filter.config; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class TransportChainsConfig { - private Map> chainByTransport = new HashMap<>(); - - public Map> getChainByTransport() { - return chainByTransport; - } - - public TransportChainsConfig add(String transport, List chain) { - chainByTransport.put(transport, chain); - - return this; - } - - @Override - public String toString() { - return chainByTransport.toString(); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ContextMapperFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ContextMapperFilter.java new file mode 100644 index 00000000000..a14e41dd660 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ContextMapperFilter.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.core.filter.impl; + +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.governance.handler.MapperHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.processor.mapping.Mapper; +import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.util.CollectionUtils; + +public class ContextMapperFilter extends AbstractFilter implements ProviderFilter, EdgeFilter { + private final MapperHandler mapperHandler; + + public ContextMapperFilter(MapperHandler mapperHandler) { + this.mapperHandler = mapperHandler; + } + + @Override + public boolean enabledForTransport(String transport) { + return CoreConst.RESTFUL.equals(transport); + } + + @Override + public int getOrder() { + return -1995; + } + + @Override + public String getName() { + return "context-mapper"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + Mapper mapper = mapperHandler.getActuator(request); + if (mapper == null || CollectionUtils.isEmpty(mapper.target())) { + return nextNode.onFilter(invocation); + } + Map properties = mapper.target(); + properties.forEach((k, v) -> { + if (StringUtils.isEmpty(v)) { + return; + } + if ("$U".equals(v)) { + invocation.addContext(k, request.apiPath()); + } else if ("$M".equals(v)) { + invocation.addContext(k, request.method()); + } else if (v.startsWith("$H{") && v.endsWith("}")) { + invocation.addContext(k, request.header(v.substring(3, v.length() - 1))); + } else if (v.startsWith("$Q{") && v.endsWith("}")) { + invocation.addContext(k, request.query(v.substring(3, v.length() - 1))); + } else { + invocation.addContext(k, v); + } + }); + return nextNode.onFilter(invocation); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java index 95da754bc78..d2b8eb82319 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java @@ -18,16 +18,16 @@ import java.util.concurrent.CompletableFuture; -import javax.annotation.Nonnull; - import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.filter.InternalFilter; +import org.apache.servicecomb.core.filter.ProviderFilter; import org.apache.servicecomb.swagger.invocation.Response; // just for test -public class EmptyFilter implements InternalFilter { - @Nonnull +public class EmptyFilter extends AbstractFilter implements ProviderFilter, ConsumerFilter, EdgeFilter { @Override public String getName() { return "empty"; @@ -37,4 +37,9 @@ public String getName() { public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { return CompletableFuture.completedFuture(Response.ok(null)); } + + @Override + public int getOrder() { + return 0; + } } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/JacksonPropertyNodeNameProvider.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/JacksonPropertyNodeNameProvider.java index 403ca6cfdd5..f617f5fe567 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/JacksonPropertyNodeNameProvider.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/JacksonPropertyNodeNameProvider.java @@ -54,4 +54,4 @@ private String getJavaBeanPropertyName(JavaBeanProperty property) { .findFirst() .orElse(property.getName()); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java index c1d1e70df5a..b4bf065792f 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java @@ -17,20 +17,16 @@ package org.apache.servicecomb.core.filter.impl; import java.lang.reflect.Method; +import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; -import javax.annotation.Nonnull; -import javax.validation.ConstraintViolation; -import javax.validation.ConstraintViolationException; -import javax.validation.Validation; -import javax.validation.ValidatorFactory; -import javax.validation.executable.ExecutableValidator; -import javax.validation.groups.Default; - +import org.apache.servicecomb.config.ConfigUtil; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.filter.ProducerFilter; +import org.apache.servicecomb.core.filter.ProviderFilter; import org.apache.servicecomb.foundation.common.utils.AsyncUtils; import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; import org.apache.servicecomb.swagger.invocation.Response; @@ -41,38 +37,92 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; -import org.springframework.stereotype.Component; -import com.netflix.config.DynamicPropertyFactory; +import jakarta.validation.Configuration; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.ConstraintViolationException; +import jakarta.validation.Valid; +import jakarta.validation.Validation; +import jakarta.validation.ValidatorFactory; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.executable.ExecutableValidator; +import jakarta.validation.groups.Default; + +public class ParameterValidatorFilter extends AbstractFilter implements ProviderFilter, InitializingBean { + private static class Service { + @SuppressWarnings("unused") + public void service(@Valid Model model) { + + } + } + + private static class Model { + @NotNull + String name; + + @Min(10) + int age; + + Model(String name, int age) { + this.name = name; + this.age = age; + } + } -@Component -public class ParameterValidatorFilter implements ProducerFilter, InitializingBean { private static final Logger LOGGER = LoggerFactory.getLogger(ParameterValidatorFilter.class); public static final String NAME = "validator"; - private static final String ENABLE_EL = "servicecomb.filters.validation.useResourceBundleMessageInterpolator"; + public static final String HIBERNATE_VALIDATE_PREFIX = "hibernate.validator"; + + public static final String ENABLE_EL = "servicecomb.filters.validation.useResourceBundleMessageInterpolator"; protected ExecutableValidator validator; - @Nonnull @Override public String getName() { return NAME; } + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER + 1000; + } + @Override public void afterPropertiesSet() { validator = createValidatorFactory() .getValidator().forExecutables(); + initValidate(); + } + + private void initValidate() { + // This method is intended to make first rpc call faster + // Because validation cache bean class, this way only make first rpc call a little faster. + try { + Model model = new Model("foo", 23); + Service instance = new Service(); + Method method = Service.class.getMethod("service", Model.class); + Object[] args = new Object[] {model}; + validator.validateParameters(instance, method, args, Default.class); + } catch (Throwable e) { + throw new IllegalStateException(e); + } } protected ValidatorFactory createValidatorFactory() { - return Validation.byProvider(HibernateValidator.class) + Configuration validatorConfiguration = Validation.byProvider(HibernateValidator.class) .configure() .propertyNodeNameProvider(new JacksonPropertyNodeNameProvider()) - .messageInterpolator(messageInterpolator()) - .buildValidatorFactory(); + .messageInterpolator(messageInterpolator()); + Map properties = ConfigUtil.stringPropertiesWithPrefix(environment, HIBERNATE_VALIDATE_PREFIX); + if (!properties.isEmpty()) { + for (Map.Entry entry : properties.entrySet()) { + validatorConfiguration.addProperty(entry.getKey(), entry.getValue()); + } + } + return validatorConfiguration.buildValidatorFactory(); } protected AbstractMessageInterpolator messageInterpolator() { @@ -83,14 +133,14 @@ protected AbstractMessageInterpolator messageInterpolator() { } private boolean useResourceBundleMessageInterpolator() { - return DynamicPropertyFactory.getInstance().getBooleanProperty(ENABLE_EL, false).get(); + return environment.getProperty(ENABLE_EL, boolean.class, false); } @Override public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { Set> violations = doValidate(invocation); if (violations.size() > 0) { - LOGGER.error("Parameter validation failed : " + violations.toString()); + LOGGER.error("Parameter validation failed : " + violations); return AsyncUtils.completeExceptionally(new ConstraintViolationException(violations)); } @@ -99,9 +149,7 @@ public CompletableFuture onFilter(Invocation invocation, FilterNode ne protected Set> doValidate(Invocation invocation) { SwaggerProducerOperation producerOperation = invocation.getOperationMeta().getSwaggerProducerOperation(); - Object instance = producerOperation.getProducerInstance(); - Method method = producerOperation.getProducerMethod(); - Object[] args = invocation.toProducerArguments(); - return validator.validateParameters(instance, method, args, Default.class); + return validator.validateParameters(producerOperation.getProducerInstance(), producerOperation.getProducerMethod(), + invocation.toProducerArguments(), Default.class); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java deleted file mode 100644 index cb06081f5c2..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.core.filter.impl; - -import java.lang.reflect.Method; -import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.Exceptions; -import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.filter.ProducerFilter; -import org.apache.servicecomb.foundation.common.utils.AsyncUtils; -import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.springframework.stereotype.Component; - -@Component -public class ProducerOperationFilter implements ProducerFilter { - public static final String NAME = "producer-operation"; - - @Nonnull - @Override - public String getName() { - return NAME; - } - - @Override - public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { - invocation.onBusinessMethodStart(); - - SwaggerProducerOperation producerOperation = invocation.getOperationMeta().getSwaggerProducerOperation(); - Object instance = producerOperation.getProducerInstance(); - Method method = producerOperation.getProducerMethod(); - Object[] args = invocation.toProducerArguments(); - return invoke(invocation, instance, method, args) - .thenApply(result -> convertResultToResponse(invocation, producerOperation, result)) - .whenComplete((response, throwable) -> processMetrics(invocation)); - } - - @SuppressWarnings("unchecked") - protected CompletableFuture invoke(Invocation invocation, Object instance, Method method, Object[] args) { - ContextUtils.setInvocationContext(invocation); - - try { - Object result = method.invoke(instance, args); - if (result instanceof CompletableFuture) { - return (CompletableFuture) result; - } - - return CompletableFuture.completedFuture(result); - } catch (Throwable e) { - return AsyncUtils.completeExceptionally(Exceptions.unwrap(e)); - } finally { - ContextUtils.removeInvocationContext(); - } - } - - protected Response convertResultToResponse(Invocation invocation, SwaggerProducerOperation producerOperation, - Object result) { - return producerOperation.getResponseMapper().mapResponse(invocation.getStatus(), result); - } - - protected void processMetrics(Invocation invocation) { - invocation.onBusinessMethodFinish(); - invocation.onBusinessFinish(); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProviderOperationFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProviderOperationFilter.java new file mode 100644 index 00000000000..c8f757bf3e2 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProviderOperationFilter.java @@ -0,0 +1,101 @@ +/* + * 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.core.filter.impl; + +import java.lang.reflect.Method; +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.exception.Exceptions; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.foundation.common.utils.AsyncUtils; +import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.context.ContextUtils; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +import jakarta.ws.rs.core.Response.Status; + +public class ProviderOperationFilter extends AbstractFilter implements ProviderFilter { + public static final String NAME = "producer-operation"; + + @Override + public String getName() { + return NAME; + } + + @Override + public int getOrder() { + // almost time, should be the last filter. + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER + 2000; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (!transportAccessAllowed(invocation)) { + return CompletableFuture.failedFuture(new InvocationException(Status.UNAUTHORIZED, + new CommonExceptionData("transport access not allowed."))); + } + invocation.onBusinessMethodStart(); + + SwaggerProducerOperation producerOperation = invocation.getOperationMeta().getSwaggerProducerOperation(); + Object instance = producerOperation.getProducerInstance(); + Method method = producerOperation.getProducerMethod(); + Object[] args = invocation.toProducerArguments(); + return invoke(invocation, instance, method, args) + .thenApply(result -> convertResultToResponse(invocation, producerOperation, result)) + .whenComplete((response, throwable) -> processMetrics(invocation)); + } + + private boolean transportAccessAllowed(Invocation invocation) { + if (invocation.getProviderTransportName() == null) { + return true; + } + return invocation.getProviderTransportName().equals(invocation.getTransportName()); + } + + @SuppressWarnings("unchecked") + protected CompletableFuture invoke(Invocation invocation, Object instance, Method method, Object[] args) { + ContextUtils.setInvocationContext(invocation); + + try { + Object result = method.invoke(instance, args); + if (result instanceof CompletableFuture) { + return (CompletableFuture) result; + } + + return CompletableFuture.completedFuture(result); + } catch (Throwable e) { + return AsyncUtils.completeExceptionally(Exceptions.unwrap(e)); + } finally { + ContextUtils.removeInvocationContext(); + } + } + + protected Response convertResultToResponse(Invocation invocation, SwaggerProducerOperation producerOperation, + Object result) { + return producerOperation.getResponseMapper().mapResponse(invocation.getStatus(), result); + } + + protected void processMetrics(Invocation invocation) { + invocation.onBusinessFinish(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/RetryFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/RetryFilter.java new file mode 100644 index 00000000000..e423b8f7ebb --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/RetryFilter.java @@ -0,0 +1,135 @@ +/* + * 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.core.filter.impl; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.governance.GovernanceConfiguration; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.core.governance.RetryContext; +import org.apache.servicecomb.governance.handler.RetryHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.beans.factory.annotation.Autowired; + +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; +import io.github.resilience4j.retry.Retry; + +public class RetryFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private static final Object LOCK = new Object(); + + private static volatile ScheduledExecutorService reactiveRetryPool; + + private static ScheduledExecutorService getOrCreateRetryPool() { + if (reactiveRetryPool == null) { + synchronized (LOCK) { + if (reactiveRetryPool == null) { + reactiveRetryPool = Executors.newScheduledThreadPool(2, new ThreadFactory() { + private final AtomicInteger count = new AtomicInteger(0); + + @Override + public Thread newThread(Runnable r) { + Thread thread = new Thread(r, "reactive-retry-pool-thread-" + count.getAndIncrement()); + // avoid block shutdown + thread.setDaemon(true); + return thread; + } + }); + } + } + } + return reactiveRetryPool; + } + + private final RetryHandler retryHandler; + + @Autowired + public RetryFilter(RetryHandler retryHandler) { + this.retryHandler = retryHandler; + } + + @Override + public String getName() { + return "retry"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + Retry retry = retryHandler.getActuator(request); + if (retry == null) { + return nextNode.onFilter(invocation); + } + + Supplier> next = createBusinessCompletionStageSupplier(invocation, nextNode); + DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); + dcs.withRetry(retry, getOrCreateRetryPool()); + CompletableFuture future = new CompletableFuture<>(); + dcs.get().whenComplete((r, e) -> { + if (e == null) { + future.complete(r); + return; + } + + future.completeExceptionally(e); + }); + + return future; + } + + private Supplier> createBusinessCompletionStageSupplier(Invocation invocation, + FilterNode nextNode) { + return () -> { + updateRetryStatus(invocation); + return nextNode.onFilter(invocation); + }; + } + + private static void updateRetryStatus(Invocation invocation) { + if (invocation.getLocalContext(RetryContext.RETRY_CONTEXT) != null) { + if (invocation.getLocalContext(RetryContext.RETRY_LOAD_BALANCE) != null + && (boolean) invocation.getLocalContext(RetryContext.RETRY_LOAD_BALANCE)) { + // clear last server to avoid using user defined endpoint + invocation.setEndpoint(null); + } + RetryContext retryContext = invocation.getLocalContext(RetryContext.RETRY_CONTEXT); + retryContext.incrementRetry(); + return; + } + + invocation.addLocalContext(RetryContext.RETRY_CONTEXT, + new RetryContext(GovernanceConfiguration.getRetrySameServer(invocation.getMicroserviceName()))); + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1990; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java index e144d81f091..341c01fa877 100644 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java +++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java @@ -19,62 +19,52 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -import javax.annotation.Nonnull; - import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.Exceptions; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.filter.ProducerFilter; -import org.apache.servicecomb.core.invocation.InvocationStageTrace; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.core.tracing.TraceIdLogger; import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.MDC; + +import jakarta.ws.rs.core.Response.Status; -@Component -public class ScheduleFilter implements ProducerFilter { +public class ScheduleFilter extends AbstractFilter implements ProviderFilter { public static final String NAME = "schedule"; - @Nonnull @Override public String getName() { return NAME; } + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER; + } + @Override public CompletableFuture onFilter(Invocation invocation, FilterNode next) { - invocation.getInvocationStageTrace().startSchedule(); + invocation.getInvocationStageTrace().startProviderQueue(); Executor executor = invocation.getOperationMeta().getExecutor(); return CompletableFuture.completedFuture(null) .thenComposeAsync(response -> runInExecutor(invocation, next), executor); } protected CompletableFuture runInExecutor(Invocation invocation, FilterNode next) { - invocation.onExecuteStart(); - - try { - InvocationStageTrace trace = invocation.getInvocationStageTrace(); - trace.startServerFiltersRequest(); - invocation.onStartHandlersRequest(); - - checkInQueueTimeout(invocation); - - return next.onFilter(invocation) - .whenComplete((response, throwable) -> whenComplete(invocation)); - } finally { - invocation.onExecuteFinish(); - } + invocation.getInvocationStageTrace().finishProviderQueue(); + MDC.put(TraceIdLogger.KEY_TRACE_ID, invocation.getTraceId()); + checkInQueueTimeout(invocation); + return next.onFilter(invocation); } private void checkInQueueTimeout(Invocation invocation) { long nanoTimeout = invocation.getOperationMeta().getConfig() .getNanoRequestWaitInPoolTimeout(invocation.getTransport().getName()); - if (System.nanoTime() - invocation.getInvocationStageTrace().getStart() > nanoTimeout) { - throw Exceptions.genericProducer("Request in the queue timed out."); + if (invocation.getInvocationStageTrace().calcQueue() > nanoTimeout) { + throw new InvocationException(Status.REQUEST_TIMEOUT, "Request in the queue timed out."); } } - - private void whenComplete(Invocation invocation) { - invocation.getInvocationStageTrace().finishHandlersResponse(); - invocation.getInvocationStageTrace().finishServerFiltersResponse(); - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java deleted file mode 100644 index 0282b959b74..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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.core.filter.impl; - -import static org.apache.servicecomb.core.exception.ExceptionCodes.LB_ADDRESS_NOT_FOUND; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.Exceptions; -import org.apache.servicecomb.core.filter.ConsumerFilter; -import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.handler.impl.SimpleLoadBalanceHandler; -import org.apache.servicecomb.core.registry.discovery.EndpointDiscoveryFilter; -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryTree; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -/** - * build-in round robin LB, for demo scenes - */ -@Component -public class SimpleLoadBalanceFilter implements ConsumerFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(SimpleLoadBalanceHandler.class); - - public static final String NAME = "simple-load-balance"; - - private static class Service { - private final String name; - - private final DiscoveryTree discoveryTree = new DiscoveryTree(); - - // key is grouping filter qualified name - private final Map indexMap = new ConcurrentHashMapEx<>(); - - public Service(String name) { - this.name = name; - discoveryTree.loadFromSPI(DiscoveryFilter.class); - discoveryTree.addFilter(new EndpointDiscoveryFilter()); - discoveryTree.sort(); - } - - public String getName() { - return name; - } - - public Endpoint selectEndpoint(Invocation invocation) { - DiscoveryContext context = new DiscoveryContext(); - context.setInputParameters(invocation); - VersionedCache endpointsVersionedCache = discoveryTree.discovery(context, - invocation.getAppId(), - invocation.getMicroserviceName(), - invocation.getMicroserviceVersionRule()); - if (endpointsVersionedCache.isEmpty()) { - String msg = "No available address found."; - LOGGER.error("{} microserviceName={}, version={}, discoveryGroupName={}", - msg, - invocation.getMicroserviceName(), - invocation.getMicroserviceVersionRule(), - endpointsVersionedCache.name()); - throw Exceptions.consumer(LB_ADDRESS_NOT_FOUND, msg); - } - - List endpoints = endpointsVersionedCache.data(); - AtomicInteger index = indexMap.computeIfAbsent(endpointsVersionedCache.name(), name -> { - LOGGER.info("Create loadBalancer for {}.", name); - return new AtomicInteger(); - }); - LOGGER.debug("invocation {} use discoveryGroup {}.", - invocation.getMicroserviceQualifiedName(), - endpointsVersionedCache.name()); - - int idx = Math.abs(index.getAndIncrement()); - idx = idx % endpoints.size(); - return endpoints.get(idx); - } - } - - private final Map servicesByName = new ConcurrentHashMapEx<>(); - - @Nonnull - @Override - public String getName() { - return NAME; - } - - @Override - public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { - if (invocation.getEndpoint() != null) { - return nextNode.onFilter(invocation); - } - - Service service = servicesByName.computeIfAbsent(invocation.getMicroserviceName(), Service::new); - Endpoint endpoint = service.selectEndpoint(invocation); - invocation.setEndpoint(endpoint); - return nextNode.onFilter(invocation); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/TransportFilters.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/TransportFilters.java deleted file mode 100644 index 40e83622e51..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/TransportFilters.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.core.filter.impl; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.core.filter.InternalFilter; -import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; - -/** - * Internal use only - */ -@Component -public class TransportFilters implements InternalFilter { - public static final String NAME = "transport-filters"; - - private Map chainByTransport = new HashMap<>(); - - @Nonnull - @Override - public String getName() { - return NAME; - } - - public Map getChainByTransport() { - return chainByTransport; - } - - @Override - public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { - FilterNode filterNode = chainByTransport.get(invocation.getTransport().getName()); - if (filterNode == null) { - return nextNode.onFilter(invocation); - } - - return filterNode.onFilter(invocation); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/CoreGovernanceConfiguration.java b/core/src/main/java/org/apache/servicecomb/core/governance/CoreGovernanceConfiguration.java new file mode 100644 index 00000000000..948c12bb46a --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/CoreGovernanceConfiguration.java @@ -0,0 +1,49 @@ +/* + * 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.core.governance; + +import org.apache.servicecomb.core.SCBEngine; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CoreGovernanceConfiguration { + @Bean + public ServiceCombCircuitBreakerExtension serviceCombCircuitBreakerExtension() { + return new ServiceCombCircuitBreakerExtension(); + } + + @Bean + public ServiceCombInstanceIsolationExtension serviceCombInstanceIsolationExtension() { + return new ServiceCombInstanceIsolationExtension(); + } + + @Bean + public ServiceCombMicroserviceMeta serviceCombMicroserviceMeta(SCBEngine scbEngine) { + return new ServiceCombMicroserviceMeta(scbEngine); + } + + @Bean + public ServiceCombRetryExtension serviceCombRetryExtension() { + return new ServiceCombRetryExtension(); + } + + @Bean + public ServiceCombConfigurationEventAdapter serviceCombConfigurationEventAdapter() { + return new ServiceCombConfigurationEventAdapter(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/GovernanceConfiguration.java b/core/src/main/java/org/apache/servicecomb/core/governance/GovernanceConfiguration.java new file mode 100644 index 00000000000..e0e65b9eec8 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/GovernanceConfiguration.java @@ -0,0 +1,72 @@ +/* + * 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.core.governance; + +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; + +public class GovernanceConfiguration { + public static final String ROOT = "servicecomb.loadbalance."; + + // retry configurations + public static final String RETRY_ENABLED = "retryEnabled"; + + public static final String RETRY_ON_NEXT = "retryOnNext"; + + public static final String RETRY_ON_SAME = "retryOnSame"; + + public static boolean isRetryEnabled(String microservice) { + String p = getStringProperty("false", + ROOT + microservice + "." + RETRY_ENABLED, + ROOT + RETRY_ENABLED); + return Boolean.parseBoolean(p); + } + + public static int getRetryNextServer(String microservice) { + return getRetryServer(microservice, RETRY_ON_NEXT); + } + + public static int getRetrySameServer(String microservice) { + return getRetryServer(microservice, RETRY_ON_SAME); + } + + private static int getRetryServer(String microservice, String retryType) { + final int defaultValue = 0; + String p = getStringProperty("0", + ROOT + microservice + "." + retryType, + ROOT + retryType); + try { + int result = Integer.parseInt(p); + if (result > 0) { + return result; + } + return defaultValue; + } catch (NumberFormatException e) { + return defaultValue; + } + } + + public static String getStringProperty(String defaultValue, String... keys) { + String property; + for (String key : keys) { + property = LegacyPropertyFactory.getStringProperty(key); + if (property != null) { + return property; + } + } + return defaultValue; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java b/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java new file mode 100644 index 00000000000..15d58d66610 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java @@ -0,0 +1,117 @@ +/* + * 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.core.governance; + +import java.util.Map; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.swagger.SwaggerUtils; + +public final class MatchType { + private static class GovernanceRequestExtractorImpl implements GovernanceRequestExtractor { + private final Invocation invocation; + + private GovernanceRequestExtractorImpl(Invocation invocation) { + this.invocation = invocation; + } + + @Override + public String apiPath() { + if (MatchType.REST.equalsIgnoreCase(invocation.getOperationMeta().getConfig().getGovernanceMatchType())) { + if (!invocation.isProducer()) { + return SwaggerUtils.concatAbsolutePath(invocation.getSchemaMeta().getSwagger(), + invocation.getOperationMeta().getOperationPath()); + } + // not highway + if (invocation.getRequestEx() != null) { + return invocation.getRequestEx().getRequestURI(); + } + } + + if (!invocation.isProducer()) { + return invocation.getOperationMeta().getMicroserviceQualifiedName(); + } + return invocation.getOperationMeta().getSchemaQualifiedName(); + } + + @Override + public String method() { + return invocation.getOperationMeta().getHttpMethod(); + } + + @Override + public String header(String key) { + Map arguments = invocation.getSwaggerArguments(); + if (arguments != null && arguments.get(key) != null) { + return arguments.get(key).toString(); + } + + if (invocation.getContext(key) != null) { + return invocation.getContext(key); + } + + if (invocation.getRequestEx() != null) { + return invocation.getRequestEx().getHeader(key); + } + + return null; + } + + @Override + public String query(String key) { + HttpServletRequestEx requestEx = invocation.getRequestEx(); + if (requestEx == null) { + return null; + } + return requestEx.getParameter(key); + } + + @Override + public String instanceId() { + if (!invocation.isProducer()) { + if (invocation.getEndpoint() != null && invocation.getEndpoint().getMicroserviceInstance() != null) { + return invocation.getEndpoint().getMicroserviceInstance().getInstanceId(); + } + } + return null; + } + + @Override + public String serviceName() { + if (!invocation.isProducer()) { + return invocation.getMicroserviceName(); + } + return null; + } + + @Override + public Object sourceRequest() { + return invocation; + } + } + + public static final String REST = "rest"; + + public static final String RPC = "rpc"; + + public static GovernanceRequestExtractor createGovHttpRequest(Invocation invocation) { + return new GovernanceRequestExtractorImpl(invocation); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/RetryContext.java b/core/src/main/java/org/apache/servicecomb/core/governance/RetryContext.java new file mode 100644 index 00000000000..47792792e14 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/RetryContext.java @@ -0,0 +1,49 @@ +/* + * 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.core.governance; + +public class RetryContext { + public static final String RETRY_CONTEXT = "x-context-retry"; + + // weather need reset Endpoint in retry + public static final String RETRY_LOAD_BALANCE = "x-context-retry-loadbalance"; + + private boolean retry; + + private int triedCount; + + private final int retryOnSame; + + public RetryContext(int retryOnSame) { + this.retryOnSame = retryOnSame; + this.retry = false; + this.triedCount = 0; + } + + public boolean isRetry() { + return retry; + } + + public void incrementRetry() { + this.retry = true; + this.triedCount++; + } + + public boolean trySameServer() { + return triedCount <= retryOnSame; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombCircuitBreakerExtension.java b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombCircuitBreakerExtension.java new file mode 100644 index 00000000000..9177ca71820 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombCircuitBreakerExtension.java @@ -0,0 +1,50 @@ +/* + * 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.core.governance; + +import java.util.List; + +import org.apache.servicecomb.governance.handler.ext.AbstractCircuitBreakerExtension; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +public class ServiceCombCircuitBreakerExtension extends AbstractCircuitBreakerExtension { + @Override + protected String extractStatusCode(Object result) { + if (!(result instanceof Response)) { + return null; + } + Response resp = (Response) result; + if (resp.isFailed()) { + if (resp.getResult() instanceof InvocationException) { + InvocationException e = resp.getResult(); + return String.valueOf(e.getStatusCode()); + } + } + return String.valueOf(resp.getStatusCode()); + } + + @Override + public boolean isFailedResult(List statusList, Throwable e) { + if (e instanceof InvocationException) { + InvocationException invocationException = (InvocationException) e; + return statusList.contains(String.valueOf(invocationException.getStatusCode())); + } + return super.isFailedResult(statusList, e); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombConfigurationEventAdapter.java b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombConfigurationEventAdapter.java new file mode 100644 index 00000000000..e5ee61cd586 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombConfigurationEventAdapter.java @@ -0,0 +1,38 @@ +/* + * 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.core.governance; + + +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; +import org.apache.servicecomb.governance.event.GovernanceEventManager; + +import com.google.common.eventbus.Subscribe; + +public class ServiceCombConfigurationEventAdapter { + public ServiceCombConfigurationEventAdapter() { + EventManager.register(this); + } + + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + GovernanceConfigurationChangedEvent newEvent = new GovernanceConfigurationChangedEvent(event.getChanged()); + GovernanceEventManager.post(newEvent); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombInstanceIsolationExtension.java b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombInstanceIsolationExtension.java new file mode 100644 index 00000000000..2bbf6d3c87d --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombInstanceIsolationExtension.java @@ -0,0 +1,36 @@ +/* + * 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.core.governance; + +import java.util.List; + +import org.apache.servicecomb.governance.handler.ext.AbstractInstanceIsolationExtension; + +public class ServiceCombInstanceIsolationExtension extends AbstractInstanceIsolationExtension { + private final ServiceCombRetryExtension retryExtension = new ServiceCombRetryExtension(); + + @Override + protected String extractStatusCode(Object result) { + return retryExtension.extractStatusCode(result); + } + + @Override + public boolean isFailedResult(List statusList, Throwable e) { + return retryExtension.isFailedResult(statusList, e); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombMicroserviceMeta.java b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombMicroserviceMeta.java new file mode 100644 index 00000000000..3893e3e4207 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombMicroserviceMeta.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.core.governance; + +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.governance.MicroserviceMeta; + +public class ServiceCombMicroserviceMeta implements MicroserviceMeta { + private SCBEngine scbEngine; + + public ServiceCombMicroserviceMeta(SCBEngine scbEngine) { + this.scbEngine = scbEngine; + } + + @Override + public String getName() { + return BootStrapProperties.readServiceName(scbEngine.getEnvironment()); + } + + @Override + public String getVersion() { + return BootStrapProperties.readServiceVersion(scbEngine.getEnvironment()); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombRetryExtension.java b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombRetryExtension.java new file mode 100644 index 00000000000..871a03bfa30 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/governance/ServiceCombRetryExtension.java @@ -0,0 +1,50 @@ +/* + * 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.core.governance; + +import java.util.List; + +import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +public class ServiceCombRetryExtension extends AbstractRetryExtension { + @Override + protected String extractStatusCode(Object result) { + if (!(result instanceof Response)) { + return null; + } + Response resp = (Response) result; + if (resp.isFailed()) { + if (resp.getResult() instanceof InvocationException) { + InvocationException e = resp.getResult(); + return String.valueOf(e.getStatusCode()); + } + } + return String.valueOf(resp.getStatusCode()); + } + + @Override + public boolean isFailedResult(List statusList, Throwable e) { + if (e instanceof InvocationException) { + InvocationException invocationException = (InvocationException) e; + return statusList.contains(String.valueOf(invocationException.getStatusCode())); + } + return super.isFailedResult(statusList, e); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java b/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java deleted file mode 100644 index 460e849b3aa..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/AbstractHandlerManager.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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.core.handler; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.handler.config.Config; -import org.apache.servicecomb.foundation.common.AbstractObjectManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; - -import com.netflix.config.DynamicPropertyFactory; - -// key为microserviceName -public abstract class AbstractHandlerManager extends AbstractObjectManager> { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractHandlerManager.class); - - private String defaultChainDef; - - private Config config; - - protected abstract String getName(); - - // consumer、provider端,最后一个handler,都是由框架指定的,业务不可配置 - protected abstract Handler getLastHandler(); - - // 内置默认值,用于业务未指定时的取值 - protected abstract String getInnerDefaultChainDef(); - - private void loadDefaultChainDef() { - String key = "servicecomb.handler.chain." + getName() + ".default"; - - defaultChainDef = DynamicPropertyFactory.getInstance() - .getStringProperty(key, getInnerDefaultChainDef()) - .get(); - } - - private List> convertToChainClass(String chainDef) { - List> result = new ArrayList<>(); - if (StringUtils.isEmpty(chainDef)) { - return result; - } - - String[] handlerIds = chainDef.split(","); - Map> handlerMaps = config.getHandlerClassMap(); - for (String handlerId : handlerIds) { - if (handlerId != null) { - handlerId = handlerId.trim(); - } - if (StringUtils.isEmpty(handlerId)) { - continue; - } - - Class cls = handlerMaps.get(handlerId); - if (cls == null) { - throw new Error("can not find handler :" + handlerId); - } - result.add(cls); - } - return result; - } - - public void init(Config config) { - this.config = config; - - loadDefaultChainDef(); - } - - private List createHandlerChain(String chainDef) { - List> chainClasses = convertToChainClass(chainDef); - - List handlerList = new ArrayList<>(); - for (Class cls : chainClasses) { - try { - handlerList.add(cls.newInstance()); - } catch (Exception e) { - // 在启动阶段直接抛异常出来 - throw new Error(e); - } - } - handlerList.add(getLastHandler()); - return handlerList; - } - - @Override - protected String getKey(String microserviceName) { - return microserviceName; - } - - @Override - protected List create(String microserviceName) { - String handlerChainKey = "servicecomb.handler.chain." + getName() + ".service." + microserviceName; - String chainDef = DynamicPropertyFactory.getInstance() - .getStringProperty(handlerChainKey, - defaultChainDef) - .get(); - LOGGER.info("get handler chain for [{}]: [{}]", handlerChainKey, chainDef); - return createHandlerChain(chainDef); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/ConsumerHandlerManager.java b/core/src/main/java/org/apache/servicecomb/core/handler/ConsumerHandlerManager.java deleted file mode 100644 index 34a253dae81..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/ConsumerHandlerManager.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.core.handler; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.handler.impl.TransportClientHandler; - -public class ConsumerHandlerManager extends AbstractHandlerManager { - @Override - protected String getName() { - return "Consumer"; - } - - @Override - protected String getInnerDefaultChainDef() { - return "simpleLB"; - } - - @Override - protected Handler getLastHandler() { - return TransportClientHandler.INSTANCE; - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/HandlerConfigUtils.java b/core/src/main/java/org/apache/servicecomb/core/handler/HandlerConfigUtils.java deleted file mode 100644 index cbd354c848f..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/HandlerConfigUtils.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.core.handler; - -import java.util.List; - -import org.apache.servicecomb.core.handler.config.Config; -import org.apache.servicecomb.foundation.common.config.PaaSResourceUtils; -import org.apache.servicecomb.foundation.common.config.impl.XmlLoaderUtils; -import org.springframework.core.io.Resource; - -public final class HandlerConfigUtils { - private HandlerConfigUtils() { - } - - private static Config loadConfig() throws Exception { - Config config = new Config(); - - List resList = - PaaSResourceUtils.getSortedResources("classpath*:config/cse.handler.xml", ".handler.xml"); - for (Resource res : resList) { - Config tmpConfig = XmlLoaderUtils.load(res, Config.class); - config.mergeFrom(tmpConfig); - } - - return config; - } - - public static void init(ConsumerHandlerManager consumerHandlerManager, ProducerHandlerManager producerHandlerManager) - throws Exception { - Config config = loadConfig(); - consumerHandlerManager.init(config); - producerHandlerManager.init(config); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/ProducerHandlerManager.java b/core/src/main/java/org/apache/servicecomb/core/handler/ProducerHandlerManager.java deleted file mode 100644 index 88c726b80d7..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/ProducerHandlerManager.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.core.handler; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.handler.impl.ProducerOperationHandler; - -public class ProducerHandlerManager extends AbstractHandlerManager { - @Override - protected String getName() { - return "Provider"; - } - - @Override - protected String getInnerDefaultChainDef() { - return ""; - } - - @Override - protected Handler getLastHandler() { - return ProducerOperationHandler.INSTANCE; - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/config/Config.java b/core/src/main/java/org/apache/servicecomb/core/handler/config/Config.java deleted file mode 100644 index 53dee5a79bf..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/config/Config.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.core.handler.config; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.core.Handler; - -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; - -@JacksonXmlRootElement -public class Config { - // key为handler id - private Map> handlerClassMap = new HashMap<>(); - - public void mergeFrom(Config otherConfig) { - handlerClassMap.putAll(otherConfig.handlerClassMap); - } - - public Map> getHandlerClassMap() { - return this.handlerClassMap; - } - - @JacksonXmlProperty(localName = "handler") - @JacksonXmlElementWrapper(useWrapping = false) - public void setHandlerConfigList(List handlerConfigList) { - for (HandlerConfig handlerConfig : handlerConfigList) { - handlerClassMap.put(handlerConfig.getHandlerId(), handlerConfig.getClazz()); - } - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/config/HandlerConfig.java b/core/src/main/java/org/apache/servicecomb/core/handler/config/HandlerConfig.java deleted file mode 100644 index cf00c7f3aba..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/config/HandlerConfig.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.core.handler.config; - -import org.apache.servicecomb.core.Handler; - -import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; - -public class HandlerConfig { - private String handlerId; - - private Class clazz; - - @JacksonXmlProperty(localName = "id", isAttribute = true) - public String getHandlerId() { - return handlerId; - } - - public void setHandlerId(String handlerId) { - this.handlerId = handlerId; - } - - @JacksonXmlProperty(localName = "class", isAttribute = true) - public Class getClazz() { - return clazz; - } - - public void setClazz(Class clazz) { - this.clazz = clazz; - } - - @SuppressWarnings("unchecked") - public void setClazz(String clazz) throws ClassNotFoundException { - this.clazz = (Class) Class.forName(clazz); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/impl/AbstractHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/impl/AbstractHandler.java deleted file mode 100644 index 940fd97859e..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/impl/AbstractHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.core.handler.impl; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.swagger.invocation.InvocationType; - -@Deprecated -public abstract class AbstractHandler implements Handler { - @Override - public void init(MicroserviceMeta microserviceMeta, InvocationType invocationType) { - - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/impl/ProducerOperationHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/impl/ProducerOperationHandler.java deleted file mode 100644 index 488a504331e..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/impl/ProducerOperationHandler.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * 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.core.handler.impl; - -import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.ExceptionUtils; -import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; -import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.apache.servicecomb.swagger.invocation.extension.ProducerInvokeExtension; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ProducerOperationHandler implements Handler { - private static final Logger LOGGER = LoggerFactory.getLogger(ProducerOperationHandler.class); - - public static final ProducerOperationHandler INSTANCE = new ProducerOperationHandler(); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) { - SwaggerProducerOperation producerOperation = invocation.getOperationMeta().getSwaggerProducerOperation(); - if (producerOperation == null) { - asyncResp.producerFail( - ExceptionUtils.producerOperationNotExist(invocation.getSchemaId(), - invocation.getOperationName())); - return; - } - invoke(invocation, producerOperation, asyncResp); - } - - private void invoke(Invocation invocation, SwaggerProducerOperation producerOperation, AsyncResponse asyncResp) { - if (CompletableFuture.class.equals(producerOperation.getProducerMethod().getReturnType())) { - completableFutureInvoke(invocation, producerOperation, asyncResp); - return; - } - - syncInvoke(invocation, producerOperation, asyncResp); - } - - public void completableFutureInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, - AsyncResponse asyncResp) { - ContextUtils.setInvocationContext(invocation); - doCompletableFutureInvoke(invocation, producerOperation, asyncResp); - ContextUtils.removeInvocationContext(); - } - - @SuppressWarnings("unchecked") - public void doCompletableFutureInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, - AsyncResponse asyncResp) { - try { - invocation.onBusinessMethodStart(); - - Object[] args = invocation.toProducerArguments(); - for (ProducerInvokeExtension producerInvokeExtension : producerOperation.getProducerInvokeExtenstionList()) { - producerInvokeExtension.beforeMethodInvoke(invocation, producerOperation, args); - } - - Object result = producerOperation.getProducerMethod().invoke(producerOperation.getProducerInstance(), args); - invocation.onBusinessMethodFinish(); - - ((CompletableFuture) result).whenComplete((realResult, ex) -> { - invocation.onBusinessFinish(); - if (ex == null) { - asyncResp.handle(producerOperation.getResponseMapper().mapResponse(invocation.getStatus(), realResult)); - return; - } - - asyncResp.handle(processException(invocation, ex)); - }); - } catch (Throwable e) { - if (shouldPrintErrorLog(e)) { - invocation.getTraceIdLogger().error(LOGGER, "unexpected error {}, message={}", - invocation.getInvocationQualifiedName(), - org.apache.servicecomb.foundation.common.utils.ExceptionUtils.getExceptionMessageWithoutTrace(e)); - } - invocation.onBusinessMethodFinish(); - invocation.onBusinessFinish(); - asyncResp.handle(processException(invocation, e)); - } - } - - public void syncInvoke(Invocation invocation, SwaggerProducerOperation producerOperation, AsyncResponse asyncResp) { - ContextUtils.setInvocationContext(invocation); - Response response = doInvoke(invocation, producerOperation); - ContextUtils.removeInvocationContext(); - asyncResp.handle(response); - } - - public Response doInvoke(Invocation invocation, SwaggerProducerOperation producerOperation) { - Response response; - try { - invocation.onBusinessMethodStart(); - - Object[] args = invocation.toProducerArguments(); - for (ProducerInvokeExtension producerInvokeExtension : producerOperation.getProducerInvokeExtenstionList()) { - producerInvokeExtension.beforeMethodInvoke(invocation, producerOperation, args); - } - - Object result = producerOperation.getProducerMethod().invoke(producerOperation.getProducerInstance(), args); - response = producerOperation.getResponseMapper().mapResponse(invocation.getStatus(), result); - - invocation.onBusinessMethodFinish(); - invocation.onBusinessFinish(); - } catch (Throwable e) { - if (shouldPrintErrorLog(e)) { - invocation.getTraceIdLogger().error(LOGGER, "unexpected error operation={}, message={}", - invocation.getInvocationQualifiedName(), - org.apache.servicecomb.foundation.common.utils.ExceptionUtils.getExceptionMessageWithoutTrace(e)); - } - invocation.onBusinessMethodFinish(); - invocation.onBusinessFinish(); - response = processException(invocation, e); - } - return response; - } - - protected boolean shouldPrintErrorLog(Throwable throwable) { - if (!(throwable instanceof InvocationTargetException)) { - return true; - } - Throwable targetException = ((InvocationTargetException) throwable).getTargetException(); - return !(targetException instanceof InvocationException); - } - - protected Response processException(SwaggerInvocation invocation, Throwable e) { - if (e instanceof InvocationTargetException) { - e = ((InvocationTargetException) e).getTargetException(); - } - - return ExceptionFactory.convertExceptionToResponse(invocation, e); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/impl/SimpleLoadBalanceHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/impl/SimpleLoadBalanceHandler.java deleted file mode 100644 index a3d4205c8b0..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/impl/SimpleLoadBalanceHandler.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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.core.handler.impl; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.ExceptionUtils; -import org.apache.servicecomb.core.registry.discovery.EndpointDiscoveryFilter; -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryTree; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 内置轮询lb,方便demo之类的场景,不必去依赖lb包 - */ -public class SimpleLoadBalanceHandler implements Handler { - private static final Logger LOGGER = LoggerFactory.getLogger(SimpleLoadBalanceHandler.class); - - private DiscoveryTree discoveryTree = new DiscoveryTree(); - - // key为grouping filter qualified name - private volatile Map indexMap = new ConcurrentHashMapEx<>(); - - public SimpleLoadBalanceHandler() { - discoveryTree.loadFromSPI(DiscoveryFilter.class); - discoveryTree.addFilter(new EndpointDiscoveryFilter()); - discoveryTree.sort(); - } - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - if (invocation.getEndpoint() != null) { - invocation.next(asyncResp); - return; - } - - DiscoveryContext context = new DiscoveryContext(); - context.setInputParameters(invocation); - VersionedCache endpointsVersionedCache = discoveryTree.discovery(context, - invocation.getAppId(), - invocation.getMicroserviceName(), - invocation.getMicroserviceVersionRule()); - if (endpointsVersionedCache.isEmpty()) { - asyncResp.consumerFail(ExceptionUtils.lbAddressNotFound(invocation.getMicroserviceName(), - invocation.getMicroserviceVersionRule(), - endpointsVersionedCache.name())); - return; - } - - List endpoints = endpointsVersionedCache.data(); - AtomicInteger index = indexMap.computeIfAbsent(endpointsVersionedCache.name(), name -> { - LOGGER.info("Create loadBalancer for {}.", name); - return new AtomicInteger(); - }); - LOGGER.debug("invocation {} use discoveryGroup {}.", - invocation.getMicroserviceQualifiedName(), - endpointsVersionedCache.name()); - - int idx = Math.abs(index.getAndIncrement()); - idx = idx % endpoints.size(); - Endpoint endpoint = endpoints.get(idx); - - invocation.setEndpoint(endpoint); - - invocation.next(asyncResp); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/handler/impl/TransportClientHandler.java b/core/src/main/java/org/apache/servicecomb/core/handler/impl/TransportClientHandler.java deleted file mode 100644 index 2213df90373..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/handler/impl/TransportClientHandler.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.core.handler.impl; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TransportClientHandler implements Handler { - - private static final Logger log = LoggerFactory.getLogger(TransportClientHandler.class); - - public static final TransportClientHandler INSTANCE = new TransportClientHandler(); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - Transport transport = invocation.getTransport(); - - log.debug( - "Sending request {} to {}", - invocation.getMicroserviceQualifiedName(), - invocation.getEndpoint().getEndpoint()); - - transport.send(invocation, asyncResp); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/CoreInvocationConfiguration.java b/core/src/main/java/org/apache/servicecomb/core/invocation/CoreInvocationConfiguration.java new file mode 100644 index 00000000000..abfe2f05330 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/CoreInvocationConfiguration.java @@ -0,0 +1,47 @@ +/* + * 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.core.invocation; + +import java.util.List; + +import org.apache.servicecomb.core.invocation.timeout.PassingTimeStrategy; +import org.apache.servicecomb.core.invocation.timeout.ProcessingTimeStrategy; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +import com.google.common.eventbus.EventBus; + +@Configuration +public class CoreInvocationConfiguration { + @Bean + public InvocationTimeoutBootListener scbInvocationTimeoutBootListener(EventBus eventBus, + List strategies, + Environment environment) { + return new InvocationTimeoutBootListener(eventBus, strategies, environment); + } + + @Bean + public PassingTimeStrategy scbPassingTimeStrategy() { + return new PassingTimeStrategy(); + } + + @Bean + public ProcessingTimeStrategy scbProcessingTimeStrategy() { + return new ProcessingTimeStrategy(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java index a413fce1016..323ad924a09 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationCreator.java @@ -20,9 +20,6 @@ import org.apache.servicecomb.core.Invocation; -/** - * better to named InvocationFactory, but already be used by old version - */ public interface InvocationCreator { CompletableFuture createAsync(); } diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationFactory.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationFactory.java index f3504b03409..776fdb32568 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationFactory.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationFactory.java @@ -19,17 +19,14 @@ import java.util.Map; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.InvocationRuntimeType; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.Microservice; - -import com.netflix.config.DynamicPropertyFactory; public final class InvocationFactory { private InvocationFactory() { @@ -45,25 +42,28 @@ public static Invocation forConsumer(ReferenceConfig referenceConfig, OperationM } public static Invocation setSrcMicroservice(Invocation invocation) { - Microservice microservice = RegistrationManager.INSTANCE.getMicroservice(); - invocation.addContext(Const.SRC_MICROSERVICE, microservice.getServiceName()); + invocation.addContext(CoreConst.SRC_MICROSERVICE, + BootStrapProperties.readServiceName(SCBEngine.getInstance().getEnvironment())); + // TODO: hard code registry name here. This is an old feature not for all registry implementations. if (addSourceServiceId()) { - invocation.addContext(Const.SRC_SERVICE_ID, microservice.getServiceId()); + invocation.addContext(CoreConst.SRC_SERVICE_ID, + SCBEngine.getInstance().getRegistrationManager().getServiceId("sc-registration")); } if (addSourceInstanceId()) { - invocation.addContext(Const.SRC_INSTANCE_ID, microservice.getInstance().getInstanceId()); + invocation.addContext(CoreConst.SRC_INSTANCE_ID, + SCBEngine.getInstance().getRegistrationManager().getInstanceId("sc-registration")); } return invocation; } public static boolean addSourceServiceId() { - return DynamicPropertyFactory.getInstance(). - getBooleanProperty("servicecomb.context.source.serviceId", true).get(); + return SCBEngine.getInstance().getEnvironment(). + getProperty("servicecomb.context.source.serviceId", boolean.class, true); } public static boolean addSourceInstanceId() { - return DynamicPropertyFactory.getInstance(). - getBooleanProperty("servicecomb.context.source.instanceId", true).get(); + return SCBEngine.getInstance().getEnvironment(). + getProperty("servicecomb.context.source.instanceId", boolean.class, true); } /* diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java index 20029bc8891..f9d0166a458 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationStageTrace.java @@ -16,362 +16,336 @@ */ package org.apache.servicecomb.core.invocation; +import java.util.HashMap; +import java.util.Map; + import org.apache.servicecomb.core.Invocation; /** *
- * important:
- *   all time point is about invocation stage, not java method
- *   all time is nanoTime
- *   not all stage relate to a event, currently, we only have 4 event:
- *     start/finish/startBusiness/finishBusiness
- *
  * for consumer:
- *         (prepare)                      (handlerReq)                                       (clientFilterReq)
- *   start --------> startHandlersRequest -----------> startClientFiltersRequest --------------------------------------
- *                                                        <----------------(sendRequest)----------------->            |
- *                        (receiveResponse)              (writeToBuffer)                   (getConnection)            |
- *    ---finishReceiveResponse <----- finishWriteToBuffer <----------- finishGetConnection <-------------- startSend <-
- *   | (wakeConsumer)            (clientFiltersResponse)               (handlersResponse)
- *   |-----> startClientFiltersResponse -------> finishClientFiltersResponse -------> finishHandlersResponse --> finish
  *
- * for producer:
- *       (prepare)       (threadPoolQueue)                                (serverFiltersRequest)
- *   start ----> startSchedule -----> startExecution -> startServerFiltersRequest -------> startHandlersRequest -------
- *                          (handlersResponse)          <-------------(business)------------->      (handlersRequest) |
- *   -----finishHandlersResponse <------ finishBusiness <------- finishBusinessMethod <------ startBusinessMethod------
- *   | (serverFiltersResponse)     (sendResponse)
- *   |---> finishServerFiltersResponse ------> finish
+ *  1. total: start create invocation -> all filters finished
+ *  2. prepare: start create invocation -> finish create invocation
+ *  3. filters-(filter-name): start call on filter -> on complete
+ *  4. connection: start get connection -> finish get connection
+ *  5. consumer-encode: start encode request -> finish encode request
+ *  6. consumer-decode: start decode response -> finish decode response
+ *  7. consumer-send: start send request -> finish send request
+ *  8. wait: finish send request -> start decode response
+ *
+ * for provider:
+ *  1. total: start create invocation -> all filters finished
+ *  2. prepare: start create invocation -> finish create invocation
+ *  3. filters-(filter-name): start call on filter -> on complete
+ *  4. queue: add in queue -> execute in thread
+ *  5. provider-decode: start decode request -> finish decode request
+ *  6. provider-encode: start encode response -> finish encode response
+ *  7. provider-send: start send response -> finish send response
+ *  8. execute: start business execute -> finish business execute
  *
  * for edge:
- *      (prepare)         (threadPoolQueue)                               (serverFiltersRequest)
- *   start ----> startSchedule -----> startExecution -> startServerFiltersRequest ----> startHandlersRequest ----------
- *                           <----------(sendRequest)---------->                                                      |
- *                       (writeToBuffer)              (getConnection)  (clientFilterReq)            (handlersRequest) |
- *   --- finishWriteToBuffer <------ finishGetConnection <------ startSend <------ startClientFiltersRequest <---------
- *   | (receiveResponse)     (wakeConsumer)                 (clientFiltersResponse)
- *   ---> finishReceiveResponse ------> startClientFiltersResponse ------> finishClientFiltersResponse ----------------
- *                                   (sendResponse)                  (serverFiltersResponse)       (handlersResponse) |
- *                              finish <------ finishServerFiltersResponse <------ finishHandlersResponse <------------
+ *
+ *  *  1. total: start create invocation -> all filters finished
+ *  *  2. prepare: start create invocation -> finish create invocation
+ *  *  3. filters-(filter-name): start call on filter -> on complete
+ *  *  4. connection: start get connection -> finish get connection
+ *  *  5. provider-decode: start decode request -> finish decode request
+ *  *  6. provider-encode: start encode response -> finish encode response
+ *  *  7. consumer-encode: start encode request -> finish encode request
+ *  *  8. consumer-decode: start decode response -> finish decode response
+ *  *  9. consumer-send: start send request -> finish send request
+ *  *  10. provider-send: start send response -> finish send response
+ *  *  11. wait: finish send request -> start decode response
  *
  * 
*/ public class InvocationStageTrace { - public static final String PREPARE = "prepare"; + public static class Stage { + private long beginTime; - public static final String HANDLERS_REQUEST = "handlers request"; + private long endTime; - public static final String HANDLERS_RESPONSE = "handlers response"; + public long getBeginTime() { + return beginTime; + } - public static final String CLIENT_FILTERS_REQUEST = "client filters request"; + public long getEndTime() { + return endTime; + } + } - public static final String CONSUMER_SEND_REQUEST = "send request"; + public static final String STAGE_TOTAL = "total"; - public static final String CONSUMER_GET_CONNECTION = "get connection"; + public static final String STAGE_PREPARE = "prepare"; - public static final String CONSUMER_WRITE_TO_BUF = "write to buf"; + public static final String STAGE_PROVIDER_QUEUE = "queue"; - public static final String CONSUMER_WAIT_RESPONSE = "wait response"; + public static final String STAGE_PROVIDER_DECODE_REQUEST = "provider-decode"; - public static final String CONSUMER_WAKE_CONSUMER = "wake consumer"; + public static final String STAGE_PROVIDER_ENCODE_RESPONSE = "provider-encode"; - public static final String CLIENT_FILTERS_RESPONSE = "client filters response"; + public static final String STAGE_PROVIDER_SEND = "provider-send"; - public static final String THREAD_POOL_QUEUE = "threadPoolQueue"; + public static final String STAGE_PROVIDER_BUSINESS = "execute"; - public static final String SERVER_FILTERS_REQUEST = "server filters request"; + public static final String STAGE_CONSUMER_CONNECTION = "connection"; - public static final String SERVER_FILTERS_RESPONSE = "server filters response"; + public static final String STAGE_CONSUMER_ENCODE_REQUEST = "consumer-encode"; - public static final String PRODUCER_SEND_RESPONSE = "send response"; + public static final String STAGE_CONSUMER_DECODE_RESPONSE = "consumer-decode"; - private Invocation invocation; + public static final String STAGE_CONSUMER_SEND = "consumer-send"; - // current time for start invocation - private long startTimeMillis; + public static final String STAGE_CONSUMER_WAIT = "wait"; - private long start; + private final Invocation invocation; - private long startHandlersRequest; + // invocation start time in millis, for passing strategy use only + private long startInMillis; - private long startClientFiltersRequest; + // invocation start time in nanos, for passing strategy use only + private long start; - // only for consumer - private long startSend; + private long finish; - // only for consumer - private long startGetConnection; + private long startCreateInvocation; - // only for consumer - private long finishGetConnection; + private long finishCreateInvocation; - // only for consumer - private long finishWriteToBuffer; + private long startProviderQueue; - // only for consumer - private long finishReceiveResponse; + private long finishProviderQueue; - private long startClientFiltersResponse; + private long startConsumerConnection; - private long finishClientFiltersResponse; + private long finishConsumerConnection; - private long finishHandlersResponse; + private long startProviderDecodeRequest; - private long finish; + private long finishProviderDecodeRequest; - // only for producer: put producer task to thread pool - private long startSchedule; + private long startProviderEncodeResponse; - private long startServerFiltersRequest; + private long finishProviderEncodeResponse; - private long finishServerFiltersResponse; + private long startConsumerEncodeRequest; - // only for producer: start execute in work thread - // for reactive mode, work thread is eventloop - private long startExecution; + private long finishConsumerEncodeRequest; - // only for producer - private long startBusinessMethod; + private long startConsumerDecodeResponse; - // only for producer - private long finishBusiness; + private long finishConsumerDecodeResponse; - public InvocationStageTrace(Invocation invocation) { - this.invocation = invocation; - } + private long startProviderSendResponse; - public void start(long start) { - // remember the current time to start invocation - this.startTimeMillis = System.currentTimeMillis(); - this.start = start; - } + private long finishProviderSendResponse; - public long getStart() { - return start; - } + private long startConsumerSendRequest; - public long getStartTimeMillis() { - return startTimeMillis; - } + private long finishConsumerSendRequest; - public InvocationStageTrace setStartTimeMillis(long startTimeMillis) { - this.startTimeMillis = startTimeMillis; - return this; - } + private long startBusinessExecute; - public long getStartHandlersRequest() { - return startHandlersRequest; - } + private long finishBusinessExecute; - public void startHandlersRequest() { - this.startHandlersRequest = System.nanoTime(); - } + private long startWaitResponse; - public long getStartClientFiltersRequest() { - return startClientFiltersRequest; - } + private long finishWaitResponse; - public void startClientFiltersRequest() { - this.startClientFiltersRequest = System.nanoTime(); - } + // invocation stage can not be used in concurrent access + private final Map stages = new HashMap<>(); - public long getStartSchedule() { - return startSchedule; + public InvocationStageTrace(Invocation invocation) { + this.invocation = invocation; } - public void startSchedule() { - this.startSchedule = System.nanoTime(); + public String recordStageBegin(String stageName) { + String realStageName = stageName; + while (stages.get(realStageName) != null) { + realStageName = realStageName + "@"; + } + Stage stage = new Stage(); + stage.beginTime = System.nanoTime(); + stages.put(realStageName, stage); + return realStageName; } - public long getStartExecution() { - return startExecution; + public void recordStageEnd(String realStageName) { + Stage stage = stages.get(realStageName); + stage.endTime = nanoTime(); } - public void startExecution() { - this.startExecution = System.nanoTime(); + public Map getStages() { + return stages; } - public long getStartSend() { - return startSend; + public void finish() { + this.finish = nanoTime(); } - public void startSend() { - this.startSend = System.nanoTime(); + public void startCreateInvocation(long nano) { + this.startCreateInvocation = nano; + this.startInMillis = millisTime(); + this.start = nanoTime(); } - public long getFinishGetConnection() { - return finishGetConnection; + public void finishCreateInvocation() { + this.finishCreateInvocation = nanoTime(); } - public void startGetConnection() { - this.startGetConnection = System.nanoTime(); + public long calcPrepare() { + return calc(finishCreateInvocation, startCreateInvocation); } - public void finishGetConnection() { - this.finishGetConnection = System.nanoTime(); + public void startProviderQueue() { + this.startProviderQueue = nanoTime(); } - public long getFinishWriteToBuffer() { - return finishWriteToBuffer; + public void finishProviderQueue() { + this.finishProviderQueue = nanoTime(); } - public void finishWriteToBuffer(long finishWriteToBuffer) { - this.finishWriteToBuffer = finishWriteToBuffer; + public long calcQueue() { + return calc(finishProviderQueue, startProviderQueue); } - public long getFinishReceiveResponse() { - return finishReceiveResponse; + public void startProviderDecodeRequest() { + this.startProviderDecodeRequest = nanoTime(); } - public void finishReceiveResponse() { - this.finishReceiveResponse = System.nanoTime(); + public void finishProviderDecodeRequest() { + this.finishProviderDecodeRequest = nanoTime(); } - public long getStartClientFiltersResponse() { - return startClientFiltersResponse; + public long calcProviderDecodeRequest() { + return calc(finishProviderDecodeRequest, startProviderDecodeRequest); } - public void startClientFiltersResponse() { - this.startClientFiltersResponse = System.nanoTime(); + public void startProviderEncodeResponse() { + this.startProviderEncodeResponse = nanoTime(); } - public long getFinishClientFiltersResponse() { - return finishClientFiltersResponse; + public void finishProviderEncodeResponse() { + this.finishProviderEncodeResponse = nanoTime(); } - public void finishClientFiltersResponse() { - this.finishClientFiltersResponse = System.nanoTime(); + public long calcProviderEncodeResponse() { + return calc(finishProviderEncodeResponse, startProviderEncodeResponse); } - public long getFinishHandlersResponse() { - return finishHandlersResponse; + public void startConsumerEncodeRequest() { + this.startConsumerEncodeRequest = nanoTime(); } - public void finishHandlersResponse() { - this.finishHandlersResponse = System.nanoTime(); + public void finishConsumerEncodeRequest() { + this.finishConsumerEncodeRequest = nanoTime(); } - public long getStartServerFiltersRequest() { - return startServerFiltersRequest; + public long calcConsumerEncodeRequest() { + return calc(finishConsumerEncodeRequest, startConsumerEncodeRequest); } - public void startServerFiltersRequest() { - this.startServerFiltersRequest = System.nanoTime(); + public void startConsumerDecodeResponse() { + this.startConsumerDecodeResponse = nanoTime(); } - public long getFinishServerFiltersResponse() { - return finishServerFiltersResponse; + public void finishConsumerDecodeResponse() { + this.finishConsumerDecodeResponse = nanoTime(); } - public void finishServerFiltersResponse() { - this.finishServerFiltersResponse = System.nanoTime(); + public long calcConsumerDecodeResponse() { + return calc(finishConsumerDecodeResponse, startConsumerDecodeResponse); } - public long getStartBusinessMethod() { - return startBusinessMethod; + public void startProviderSendResponse() { + this.startProviderSendResponse = nanoTime(); } - public void startBusinessMethod() { - this.startBusinessMethod = System.nanoTime(); + public void finishProviderSendResponse() { + this.finishProviderSendResponse = nanoTime(); } - public long getFinishBusiness() { - return finishBusiness; + public long calcProviderSendResponse() { + return calc(finishProviderSendResponse, startProviderSendResponse); } - public void finishBusiness() { - this.finishBusiness = System.nanoTime(); + public void startBusinessExecute() { + this.startBusinessExecute = nanoTime(); } - public long getFinish() { - return finish; + public void finishBusinessExecute() { + this.finishBusinessExecute = nanoTime(); } - public void finish() { - this.finish = System.nanoTime(); + public long calcBusinessExecute() { + return calc(finishBusinessExecute, startBusinessExecute); } - private double calc(long finish, long start) { - if (finish == 0 || start == 0) { - return Double.NaN; - } - - return finish - start; + public void startConsumerConnection() { + this.startConsumerConnection = nanoTime(); } - public double calcTotalTime() { - return calc(finish, start); + public void finishConsumerConnection() { + this.finishConsumerConnection = nanoTime(); } - public double calcInvocationPrepareTime() { - if (invocation.isConsumer() && !invocation.isEdge()) { - return calc(startHandlersRequest, start); - } - - return calc(startSchedule, start); - } - - public double calcHandlersRequestTime() { - if (invocation.isConsumer()) { - return calc(startClientFiltersRequest, startHandlersRequest); - } - - return calc(startBusinessMethod, startHandlersRequest); + public long calcConnection() { + return calc(finishConsumerConnection, startConsumerConnection); } - public double calcClientFiltersRequestTime() { - return calc(startSend, startClientFiltersRequest); + public void startConsumerSendRequest() { + this.startConsumerSendRequest = nanoTime(); } - public double calcServerFiltersRequestTime() { - return calc(startHandlersRequest, startServerFiltersRequest); + public void finishConsumerSendRequest() { + this.finishConsumerSendRequest = nanoTime(); } - public double calcSendRequestTime() { - return calc(finishWriteToBuffer, startSend); + public long calcConsumerSendRequest() { + return calc(finishConsumerSendRequest, startConsumerSendRequest); } - public double calcGetConnectionTime() { - return calc(finishGetConnection, startGetConnection); + public void startWaitResponse() { + this.startWaitResponse = nanoTime(); } - public double calcWriteToBufferTime() { - return calc(finishWriteToBuffer, finishGetConnection); + public void finishWaitResponse() { + this.finishWaitResponse = nanoTime(); } - public double calcReceiveResponseTime() { - return calc(finishReceiveResponse, finishWriteToBuffer); + public long calcWait() { + return calc(finishWaitResponse, startWaitResponse); } - public double calcWakeConsumer() { - return calc(startClientFiltersResponse, finishReceiveResponse); + public long calcTotal() { + return calc(finish, this.startCreateInvocation); } - public double calcClientFiltersResponseTime() { - return calc(finishClientFiltersResponse, startClientFiltersResponse); + public long getStartInMillis() { + return this.startInMillis; } - public double calcServerFiltersResponseTime() { - return calc(finishServerFiltersResponse, finishHandlersResponse); + public long getStart() { + return this.start; } - public double calcHandlersResponseTime() { - if (invocation.isConsumer()) { - return calc(finishHandlersResponse, finishClientFiltersResponse); + public static long calc(long finish, long start) { + if (finish == 0 || start == 0) { + return 0; } - return calc(finishHandlersResponse, finishBusiness); - } - - public double calcThreadPoolQueueTime() { - return calc(startExecution, startSchedule); + return finish - start; } - public double calcBusinessTime() { - return calc(finishBusiness, startBusinessMethod); + /* + * Holder for testing purpose + */ + protected long nanoTime() { + return System.nanoTime(); } - public double calcSendResponseTime() { - return calc(finish, finishServerFiltersResponse); + protected long millisTime() { + return System.currentTimeMillis(); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java index 5c8ac67ecd0..6a5e929a8bd 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java @@ -21,8 +21,6 @@ import org.apache.servicecomb.core.event.InvocationBusinessFinishEvent; import org.apache.servicecomb.core.event.InvocationBusinessMethodStartEvent; -import org.apache.servicecomb.core.event.InvocationHandlersStartEvent; -import org.apache.servicecomb.core.event.InvocationRunInExecutorStartEvent; import org.apache.servicecomb.core.event.InvocationStartEvent; import org.apache.servicecomb.core.event.InvocationStartSendRequestEvent; import org.apache.servicecomb.core.event.InvocationTimeoutCheckEvent; @@ -31,14 +29,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -@SuppressWarnings({"UnstableApiUsage", "unused"}) -@Component -public class InvocationTimeoutBootListener { +@SuppressWarnings({"unused"}) +public final class InvocationTimeoutBootListener { private static final Logger LOGGER = LoggerFactory.getLogger(InvocationTimeoutBootListener.class); public static final String PREFIX = "servicecomb.invocation.timeout.check"; @@ -76,18 +72,6 @@ public void onInvocationStartEvent(InvocationStartEvent event) { strategy.start(event.getInvocation()); } - @Subscribe - @EnableExceptionPropagation - public void onInvocationRunInExecutorStartEvent(InvocationRunInExecutorStartEvent event) { - strategy.startRunInExecutor(event.getInvocation()); - } - - @Subscribe - @EnableExceptionPropagation - public void onInvocationHandlersStartEvent(InvocationHandlersStartEvent event) { - strategy.startHandlers(event.getInvocation()); - } - @Subscribe @EnableExceptionPropagation public void onInvocationBusinessMethodStartEvent(InvocationBusinessMethodStartEvent event) { diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutStrategy.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutStrategy.java index 5e31c59136c..c530acfca29 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutStrategy.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutStrategy.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.core.invocation; -import static javax.ws.rs.core.Response.Status.REQUEST_TIMEOUT; +import static jakarta.ws.rs.core.Response.Status.REQUEST_TIMEOUT; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.ExceptionCodes; @@ -37,10 +37,6 @@ default void startRunInExecutor(Invocation invocation) { checkTimeout(invocation); } - default void startHandlers(Invocation invocation) { - checkTimeout(invocation); - } - default void startBusinessMethod(Invocation invocation) { checkTimeout(invocation); } diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java b/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java index 6f4f8e2ff2d..ec589f37733 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlow.java @@ -19,14 +19,16 @@ import java.util.concurrent.CompletableFuture; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.Exceptions; -import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import jakarta.ws.rs.core.Response.Status; + public abstract class ProducerInvocationFlow { private static final Logger LOGGER = LoggerFactory.getLogger(ProducerInvocationFlow.class); @@ -60,57 +62,49 @@ private void tryRunInvocation(Invocation invocation) { if (invocation == null) { return; } - - invocation.onStart(requestEx, startTime); - invocation.getMicroserviceMeta().getFilterChain() - .onFilter(invocation) - .whenComplete((response, Throwable) -> sendResponse(invocation, response)) - .whenComplete((response, Throwable) -> finishInvocation(invocation, response, Throwable)); - } - - private void finishInvocation(Invocation invocation, Response response, Throwable throwable) { - invocation.onFinish(response); - - tryLogException(invocation, throwable); - } - - private void tryLogException(Invocation invocation, Throwable throwable) { - if (throwable == null) { - return; - } - - throwable = Exceptions.unwrap(throwable); - if (requestEx == null) { - logException(invocation, throwable); + invocation.getInvocationStageTrace().startCreateInvocation(this.startTime); + invocation.getInvocationStageTrace().finishCreateInvocation(); + invocation.onStart(requestEx); + if (invocation.isEdge()) { + invocation.getMicroserviceMeta().getEdgeFilterChain() + .onFilter(invocation) + .whenComplete((response, throwable) -> { + if (throwable != null) { + // Server codec operates on Response. So the filter chain result should be Response and + // will never throw exception. + // Sometimes Server Codec will throw exception, e.g. Connection Closed. + LOGGER.error("Maybe a fatal bug that should be addressed or codec exception for {}.", + invocation.getInvocationQualifiedName(), throwable); + response = Response.createFail(new InvocationException(Status.INTERNAL_SERVER_ERROR, + new CommonExceptionData("Internal error, check logs for details."))); + } + endResponse(invocation, response); + finishInvocation(invocation, response); + }); return; } - - logException(invocation, requestEx, throwable); - } - - private void logException(Invocation invocation, Throwable throwable) { - if (Exceptions.isPrintInvocationStackTrace()) { - LOGGER.error("Failed to finish invocation, operation:{}.", invocation.getMicroserviceQualifiedName(), throwable); - return; - } - - LOGGER.error("Failed to finish invocation, operation:{}, message={}.", invocation.getMicroserviceQualifiedName(), - ExceptionUtils.getExceptionMessageWithoutTrace(throwable)); + invocation.getMicroserviceMeta().getProviderFilterChain() + .onFilter(invocation) + .whenComplete((response, throwable) -> { + if (throwable != null) { + // Server codec operates on Response. So the filter chain result should be Response and + // will never throw exception. + // Sometimes Server Codec will throw exception, e.g. Connection Closed. + LOGGER.error("Maybe a fatal bug that should be addressed or codec exception for {}.", + invocation.getInvocationQualifiedName(), throwable); + response = Response.createFail(new InvocationException(Status.INTERNAL_SERVER_ERROR, + new CommonExceptionData("Internal error, check logs for details."))); + } + endResponse(invocation, response); + finishInvocation(invocation, response); + }); } - private void logException(Invocation invocation, HttpServletRequestEx requestEx, Throwable throwable) { - if (Exceptions.isPrintInvocationStackTrace()) { - LOGGER.error("Failed to finish invocation, operation:{}, request uri:{}.", - invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), throwable); - return; - } - - LOGGER.error("Failed to finish invocation, operation:{}, request uri:{}, message={}.", - invocation.getMicroserviceQualifiedName(), requestEx.getRequestURI(), - ExceptionUtils.getExceptionMessageWithoutTrace(throwable)); + private void finishInvocation(Invocation invocation, Response response) { + invocation.onFinish(response); } protected abstract Invocation sendCreateInvocationException(Throwable throwable); - protected abstract void sendResponse(Invocation invocation, Response response); + protected abstract void endResponse(Invocation invocation, Response response); } diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointCacheUtils.java b/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointCacheUtils.java index 316a48bf21c..141a6e9063b 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointCacheUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointCacheUtils.java @@ -44,4 +44,4 @@ public static Endpoint getOrCreate(String uri) { public static Endpoint create(String uri) { return EndpointUtils.parse(EndpointUtils.formatFromUri(uri)); } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtils.java b/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtils.java index 6aa4cc53111..2d8b37c997a 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtils.java @@ -88,7 +88,7 @@ public static Endpoint parse(String uriEndpoint) { } /** - *
+   * {@code
    *   http://xxx  -> rest://xxx
    *   https://xxx -> rest://xxx?sslEnabled=true
    *
@@ -98,7 +98,7 @@ public static Endpoint parse(String uriEndpoint) {
    *   xxx         -> rest://xxx:port?protocol=http2
    *   xxx?a=a1    -> rest://xxx:port?a=a1&protocol=http2
    *   other://xxx -> other://xxx
-   * 
+ * } * * 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. @@ -135,7 +135,7 @@ private static String extractHostFromPath(URIBuilder builder) { if (path.startsWith("/")) { path = path.substring(1); } - if (path.indexOf("/") != -1) { + if (path.contains("/")) { path = path.substring(0, path.indexOf("/")); } return path; diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategy.java b/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategy.java index 4e9ce740437..6d55c7a7f51 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategy.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategy.java @@ -24,7 +24,6 @@ import org.apache.commons.lang3.math.NumberUtils; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.invocation.InvocationTimeoutStrategy; -import org.springframework.stereotype.Component; /** *
@@ -53,7 +52,6 @@
  * ......
  * 
*/ -@Component public class PassingTimeStrategy implements InvocationTimeoutStrategy { public static final String NAME = "passing-time"; @@ -80,7 +78,7 @@ public void start(Invocation invocation) { return; } - long startTimeMillis = invocation.getInvocationStageTrace().getStartTimeMillis(); + long startTimeMillis = invocation.getInvocationStageTrace().getStartInMillis(); String contextChainStartTime = invocation.getContext(CHAIN_START_TIME); if (StringUtils.isEmpty(contextChainStartTime)) { invocation.addContext(CHAIN_START_TIME, String.valueOf(startTimeMillis)); diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategy.java b/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategy.java index 8fbed64bc69..4c2c021a42b 100644 --- a/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategy.java +++ b/core/src/main/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategy.java @@ -20,7 +20,6 @@ import org.apache.commons.lang3.math.NumberUtils; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.invocation.InvocationTimeoutStrategy; -import org.springframework.stereotype.Component; import com.google.common.base.Ticker; @@ -56,7 +55,6 @@ * ...... * */ -@Component public class ProcessingTimeStrategy implements InvocationTimeoutStrategy { public static final String NAME = "processing-time"; diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/LocalOpenAPIRegistry.java b/core/src/main/java/org/apache/servicecomb/core/provider/LocalOpenAPIRegistry.java new file mode 100644 index 00000000000..14a27530c92 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/provider/LocalOpenAPIRegistry.java @@ -0,0 +1,90 @@ +/* + * 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.core.provider; + +import java.util.Collections; +import java.util.Map; + +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager.OpenAPIChangeListener; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; + +import io.swagger.v3.oas.models.OpenAPI; + +/** + * register and load OpenAPI from local file store or memory + */ +public class LocalOpenAPIRegistry implements OpenAPIRegistry { + private static final Logger LOGGER = LoggerFactory.getLogger(LocalOpenAPIRegistry.class); + + // first key : appId + // second key: microservice short name + // third key : schemaId + private final Map>> apps = new ConcurrentHashMapEx<>(); + + private final Environment environment; + + private OpenAPIChangeListener openAPIChangeListener; + + public LocalOpenAPIRegistry(Environment environment) { + this.environment = environment; + } + + @Override + public boolean enabled() { + return true; + } + + @Override + public void registerOpenAPI(String application, String serviceName, String schemaId, OpenAPI api) { + apps.computeIfAbsent(application, k -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(serviceName, k -> new ConcurrentHashMapEx<>()) + .put(schemaId, api); + openAPIChangeListener.onOpenAPIChanged(application, serviceName); + LOGGER.info("register swagger appId={}, name={}, schemaId={}.", + application, serviceName, schemaId); + } + + /** + * Method for retrieve myself schema contents. + */ + public Map loadOpenAPI() { + return loadOpenAPI(BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment)); + } + + @Override + public Map loadOpenAPI(String application, String serviceName) { + if (apps.get(application) != null && apps.get(application).get(serviceName) != null) { + return apps.get(application).get(serviceName); + } + return Collections.emptyMap(); + } + + @Override + public void setOpenAPIChangeListener(OpenAPIChangeListener listener) { + this.openAPIChangeListener = listener; + } + + @Override + public int getOrder() { + return -10000; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/OpenAPIRegistry.java b/core/src/main/java/org/apache/servicecomb/core/provider/OpenAPIRegistry.java new file mode 100644 index 00000000000..440c297d7ae --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/provider/OpenAPIRegistry.java @@ -0,0 +1,39 @@ +/* + * 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.core.provider; + +import java.util.Map; + +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager.OpenAPIChangeListener; +import org.springframework.core.Ordered; + +import io.swagger.v3.oas.models.OpenAPI; + +/** + * Register and load OpenAPI extensions. + */ +public interface OpenAPIRegistry extends Ordered { + String CONFIG_PREFIX = "servicecomb.openAPI.registry"; + + boolean enabled(); + + void registerOpenAPI(String application, String serviceName, String schemaId, OpenAPI api); + + Map loadOpenAPI(String application, String serviceName); + + void setOpenAPIChangeListener(OpenAPIChangeListener listener); +} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/OpenAPIRegistryManager.java b/core/src/main/java/org/apache/servicecomb/core/provider/OpenAPIRegistryManager.java new file mode 100644 index 00000000000..c357e6a24ae --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/provider/OpenAPIRegistryManager.java @@ -0,0 +1,116 @@ +/* + * 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.core.provider; + +import java.net.URI; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.FilenameUtils; +import org.apache.servicecomb.foundation.common.utils.ResourceUtil; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.apache.servicecomb.swagger.generator.SwaggerGenerator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; + +import io.swagger.v3.oas.models.OpenAPI; + +/** + * Register and load OpenAPI from various OpenAPIRegistry + */ +public class OpenAPIRegistryManager { + private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIRegistryManager.class); + + public interface OpenAPIChangeListener { + void onOpenAPIChanged(String application, String serviceName); + } + + private List openAPIRegistries; + + private final List changeListeners = new ArrayList<>(); + + @Autowired + public void setOpenAPIRegistries(List openAPIRegistries) { + List target = new ArrayList<>(openAPIRegistries.size()); + for (OpenAPIRegistry registry : openAPIRegistries) { + if (registry.enabled()) { + registry.setOpenAPIChangeListener(this::onOpenAPIChanged); + target.add(registry); + } + } + this.openAPIRegistries = target; + } + + public void addOpenAPIChangeListener(OpenAPIChangeListener changeListener) { + this.changeListeners.add(changeListener); + } + + public void onOpenAPIChanged(String application, String serviceName) { + for (OpenAPIChangeListener listener : this.changeListeners) { + try { + listener.onOpenAPIChanged(application, serviceName); + } catch (Exception e) { + LOGGER.warn("event process error {}/{}, {}", application, serviceName, e.getMessage()); + } + } + } + + public void registerOpenAPI(String application, String serviceName, String schemaId, OpenAPI api) { + for (OpenAPIRegistry registry : this.openAPIRegistries) { + registry.registerOpenAPI(application, serviceName, schemaId, api); + } + } + + public void registerOpenAPI(String application, String serviceName, String schemaId, Class cls) { + OpenAPI api = SwaggerGenerator.generate(cls); + registerOpenAPI(application, serviceName, schemaId, api); + } + + public void registerOpenAPIInLocation(String application, String serviceName, String swaggersLocation) { + try { + List resourceUris = ResourceUtil.findResourcesBySuffix(swaggersLocation, ".yaml"); + if (resourceUris.isEmpty()) { + return; + } + for (URI uri : resourceUris) { + URL url = uri.toURL(); + OpenAPI swagger = SwaggerUtils.parseAndValidateSwagger(url); + String schemaId = FilenameUtils.getBaseName(url.getPath()); + registerOpenAPI(application, serviceName, schemaId, swagger); + } + } catch (Throwable e) { + throw new IllegalStateException(String.format( + "failed to register swaggers, microserviceName=%s, location=%s.", + serviceName, swaggersLocation), e); + } + } + + public Map loadOpenAPI(String appId, String microserviceName) { + for (OpenAPIRegistry registry : this.openAPIRegistries) { + Map result = registry.loadOpenAPI(appId, microserviceName); + if (!CollectionUtils.isEmpty(result)) { + return result; + } + } + return Collections.emptyMap(); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/RegistryOpenAPIRegistry.java b/core/src/main/java/org/apache/servicecomb/core/provider/RegistryOpenAPIRegistry.java new file mode 100644 index 00000000000..cc5e6fe22dd --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/provider/RegistryOpenAPIRegistry.java @@ -0,0 +1,101 @@ +/* + * 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.core.provider; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager.OpenAPIChangeListener; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.router.util.VersionCompareUtil; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.util.CollectionUtils; + +import io.swagger.v3.oas.models.OpenAPI; +import jakarta.ws.rs.core.Response.Status; + +/** + * register and load OpenAPI from registration and discovery registry. + */ +public class RegistryOpenAPIRegistry implements OpenAPIRegistry { + private DiscoveryManager discoveryManager; + + private Environment environment; + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + + @Override + public boolean enabled() { + return environment.getProperty(OpenAPIRegistry.CONFIG_PREFIX + ".registry.enabled", boolean.class, false); + } + + @Override + public void registerOpenAPI(String application, String serviceName, String schemaId, OpenAPI api) { + // do noting + } + + @Override + public Map loadOpenAPI(String application, String serviceName) { + List discoveryInstances = + discoveryManager.findServiceInstances(application, serviceName); + if (discoveryInstances.isEmpty()) { + throw new InvocationException(Status.INTERNAL_SERVER_ERROR, "no instances"); + } + discoveryInstances.sort((a, b) -> VersionCompareUtil.compareVersion(b.getVersion(), a.getVersion())); + + Map result = new HashMap<>(); + String version = null; + for (DiscoveryInstance instance : discoveryInstances) { + if (version != null && !version.equals(instance.getVersion())) { + break; + } + version = instance.getVersion(); + instance.getSchemas().forEach((k, v) -> result.computeIfAbsent(k, (key) -> SwaggerUtils.parseSwagger(v))); + } + return result; + } + + @Override + public void setOpenAPIChangeListener(OpenAPIChangeListener listener) { + this.discoveryManager.addInstanceChangeListener( + (registryName, application, serviceName, instances) -> { + if (CollectionUtils.isEmpty(instances)) { + return; + } + listener.onOpenAPIChanged(application, serviceName); + }); + } + + @Override + public int getOrder() { + return -8000; + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/AbstractConsumerProvider.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/AbstractConsumerProvider.java deleted file mode 100644 index c9093c330dc..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/AbstractConsumerProvider.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.core.provider.consumer; - -import org.apache.servicecomb.core.ConsumerProvider; - -public abstract class AbstractConsumerProvider implements ConsumerProvider { - @Override - public void init() { - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ConsumerProviderManager.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ConsumerProviderManager.java index b20d0c773d8..615063bd3b4 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ConsumerProviderManager.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ConsumerProviderManager.java @@ -17,23 +17,70 @@ package org.apache.servicecomb.core.provider.consumer; -import java.util.ArrayList; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.List; -import org.apache.servicecomb.core.ConsumerProvider; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager; +import org.apache.servicecomb.foundation.common.utils.ResourceUtil; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; public class ConsumerProviderManager { - private List consumerProviderList = new ArrayList<>( - SPIServiceUtils.getOrLoadSortedService(ConsumerProvider.class)); + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerProviderManager.class); - public List getConsumerProviderList() { - return consumerProviderList; + private final OpenAPIRegistryManager openAPIRegistryManager; + + private final Environment environment; + + public ConsumerProviderManager(Environment environment, OpenAPIRegistryManager openAPIRegistryManager) { + this.environment = environment; + this.openAPIRegistryManager = openAPIRegistryManager; } public void init() throws Exception { - for (ConsumerProvider provider : consumerProviderList) { - provider.init(); + registerSwaggerFromApplications(); + registerSwaggerFromMicroservices(); + } + + private void registerSwaggerFromApplications() { + try { + List resourceUris = ResourceUtil.findResourcesBySuffix("applications", ".yaml"); + for (URI uri : resourceUris) { + String path = uri.toURL().getPath(); + String[] segments = path.split("/"); + if (segments.length < 4 || !"applications".equals(segments[segments.length - 4])) { + continue; + } + openAPIRegistryManager.registerOpenAPI(segments[segments.length - 3], segments[segments.length - 2], + segments[segments.length - 1].substring(0, segments[segments.length - 1].indexOf(".yaml")), + SwaggerUtils.parseAndValidateSwagger(uri.toURL())); + } + } catch (IOException | URISyntaxException e) { + LOGGER.error("Load schema ids failed from applications. {}.", e.getMessage()); + } + } + + private void registerSwaggerFromMicroservices() { + try { + List resourceUris = ResourceUtil.findResourcesBySuffix("microservices", ".yaml"); + for (URI uri : resourceUris) { + String path = uri.toURL().getPath(); + String[] segments = path.split("/"); + if (segments.length < 3 || !"microservices".equals(segments[segments.length - 3])) { + continue; + } + openAPIRegistryManager.registerOpenAPI(BootStrapProperties.readApplication(environment), + segments[segments.length - 2], + segments[segments.length - 1].substring(0, segments[segments.length - 1].indexOf(".yaml")), + SwaggerUtils.parseAndValidateSwagger(uri.toURL())); + } + } catch (IOException | URISyntaxException e) { + LOGGER.error("Load schema ids failed from microservices. {}.", e.getMessage()); } } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java index 640bf4416e3..152f43a5034 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java @@ -23,8 +23,9 @@ import java.lang.reflect.Type; import java.util.Map; import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nonnull; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; @@ -36,98 +37,82 @@ import org.apache.servicecomb.foundation.common.utils.AsyncUtils; import org.apache.servicecomb.swagger.invocation.AsyncResponse; import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.context.ContextUtils; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicPropertyFactory; import io.vertx.core.Context; +import jakarta.ws.rs.core.Response.Status; public final class InvokerUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(InvokerUtils.class); - - private static boolean enableEventLoopBlockingCallCheck = - DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.invocation.enableEventLoopBlockingCallCheck", true).get(); - @SuppressWarnings({"unchecked"}) - public static T syncInvoke(String microserviceName, String microserviceVersion, String transport, + public static T syncInvoke(String microserviceName, String transport, String schemaId, String operationId, Map swaggerArguments, Type responseType) { - Invocation invocation = createInvocation(microserviceName, microserviceVersion, transport, schemaId, operationId, + Invocation invocation = createInvocation(microserviceName, transport, schemaId, operationId, swaggerArguments, responseType); return (T) syncInvoke(invocation); } - public static void reactiveInvoke(String microserviceName, String microserviceVersion, String transport, + public static void reactiveInvoke(String microserviceName, String transport, String schemaId, String operationId, Map swaggerArguments, Type responseType, AsyncResponse asyncResp) { - Invocation invocation = createInvocation(microserviceName, microserviceVersion, transport, schemaId, operationId, + Invocation invocation = createInvocation(microserviceName, transport, schemaId, operationId, swaggerArguments, responseType); reactiveInvoke(invocation, asyncResp); } public static T syncInvoke(String microserviceName, String schemaId, String operationId, Map swaggerArguments, Type responseType) { - return syncInvoke(microserviceName, null, null, + return syncInvoke(microserviceName, null, schemaId, operationId, swaggerArguments, responseType); } public static void reactiveInvoke(String microserviceName, String schemaId, String operationId, Map swaggerArguments, Type responseType, AsyncResponse asyncResp) { - reactiveInvoke(microserviceName, null, null, + reactiveInvoke(microserviceName, null, schemaId, operationId, swaggerArguments, responseType, asyncResp); } - private static Invocation createInvocation(String microserviceName, String microserviceVersion, String transport, + public static Invocation createInvocation(String microserviceName, String transport, String schemaId, String operationId, Map swaggerArguments, Type responseType) { + long startCreateInvocation = System.nanoTime(); MicroserviceReferenceConfig microserviceReferenceConfig = SCBEngine.getInstance() - .createMicroserviceReferenceConfig(microserviceName, microserviceVersion); - MicroserviceMeta microserviceMeta = microserviceReferenceConfig.getLatestMicroserviceMeta(); + .getOrCreateReferenceConfig(microserviceName); + if (microserviceReferenceConfig == null) { + throw new InvocationException(Status.INTERNAL_SERVER_ERROR, + new CommonExceptionData(String.format("Failed to invoke service %s. Maybe service" + + " not registered or no active instance.", microserviceName))); + } + MicroserviceMeta microserviceMeta = microserviceReferenceConfig.getMicroserviceMeta(); SchemaMeta schemaMeta = microserviceMeta.ensureFindSchemaMeta(schemaId); OperationMeta operationMeta = schemaMeta.ensureFindOperation(operationId); ReferenceConfig referenceConfig = microserviceReferenceConfig.createReferenceConfig(transport, operationMeta); InvocationRuntimeType invocationRuntimeType = operationMeta.buildBaseConsumerRuntimeType(); invocationRuntimeType.setSuccessResponseType(responseType); - Invocation invocation = InvocationFactory + Invocation result = InvocationFactory .forConsumer(referenceConfig, operationMeta, invocationRuntimeType, swaggerArguments); - return invocation; - } - - /** - * - * use of this method , the response type can not be determined. - * use {@link #syncInvoke(String, String, String, Map, Type)} instead. - * - */ - @Deprecated - public static Object syncInvoke(String microserviceName, String schemaId, String operationId, - Map swaggerArguments) { - return syncInvoke(microserviceName, null, null, schemaId, operationId, swaggerArguments); + result.getInvocationStageTrace().startCreateInvocation(startCreateInvocation); + result.getInvocationStageTrace().finishCreateInvocation(); + return result; } /** * * use of this method , the response type can not be determined. - * use {@link #syncInvoke(String, String, String, String, String, Map, Type)} instead. + * use {@link #syncInvoke(String, String, String, String, Map, Type)} instead. * */ @Deprecated - public static Object syncInvoke(String microserviceName, String microserviceVersion, String transport, + public static Object syncInvoke(String microserviceName, String transport, String schemaId, String operationId, Map swaggerArguments) { - return syncInvoke(microserviceName, microserviceVersion, transport, schemaId, operationId, swaggerArguments, + return syncInvoke(microserviceName, transport, schemaId, operationId, swaggerArguments, null); } /** * This is an internal API, caller make sure already invoked SCBEngine.ensureStatusUp - * @param invocation - * @return contract result - * @throws InvocationException */ public static Object syncInvoke(Invocation invocation) throws InvocationException { Response response = innerSyncInvoke(invocation); @@ -143,104 +128,64 @@ public static boolean isInEventLoop() { /** * This is an internal API, caller make sure already invoked SCBEngine.ensureStatusUp - * @param invocation - * @return servicecomb response object */ public static Response innerSyncInvoke(Invocation invocation) { - try { - if (enableEventLoopBlockingCallCheck && isInEventLoop()) { - throw new IllegalStateException("Can not execute sync logic in event loop. "); - } - invocation.onStart(null, System.nanoTime()); - SyncResponseExecutor respExecutor = new SyncResponseExecutor(); - invocation.setResponseExecutor(respExecutor); - - invocation.onStartHandlersRequest(); - invocation.next(respExecutor::setResponse); - - Response response = respExecutor.waitResponse(invocation); - invocation.getInvocationStageTrace().finishHandlersResponse(); - invocation.onFinish(response); - return response; - } catch (Throwable e) { - String msg = - String.format("invoke failed, %s", invocation.getOperationMeta().getMicroserviceQualifiedName()); - LOGGER.error(msg, e); - - Response response = Response.createConsumerFail(e); - invocation.onFinish(response); - return response; + if (isInEventLoop() && + SCBEngine.getInstance() + .getEnvironment() + .getProperty("servicecomb.invocation.enableEventLoopBlockingCallCheck", boolean.class, true)) { + throw new IllegalStateException("Can not execute sync logic in event loop."); } + return toSync(invoke(invocation), invocation.getWaitTime()); } /** * This is an internal API, caller make sure already invoked SCBEngine.ensureStatusUp - * @param invocation - * @param asyncResp */ public static void reactiveInvoke(Invocation invocation, AsyncResponse asyncResp) { - try { - invocation.onStart(null, System.nanoTime()); - invocation.setSync(false); - - ReactiveResponseExecutor respExecutor = new ReactiveResponseExecutor(); - invocation.setResponseExecutor(respExecutor); - - invocation.onStartHandlersRequest(); - invocation.next(ar -> { - ContextUtils.setInvocationContext(invocation.getParentContext()); - try { - invocation.getInvocationStageTrace().finishHandlersResponse(); - invocation.onFinish(ar); - asyncResp.handle(ar); - } finally { - ContextUtils.removeInvocationContext(); - } - }); - } catch (Throwable e) { - invocation.getInvocationStageTrace().finishHandlersResponse(); - //if throw exception,we can use 500 for status code ? - Response response = Response.createConsumerFail(e); - invocation.onFinish(response); - LOGGER.error("invoke failed, {}", invocation.getOperationMeta().getMicroserviceQualifiedName()); - asyncResp.handle(response); - } + invoke(invocation).whenComplete((r, e) -> { + if (e == null) { + asyncResp.complete(r); + } else { + asyncResp.consumerFail(e); + } + }); } - public static boolean isSyncMethod(@Nonnull Method method) { + public static boolean isSyncMethod(Method method) { return !isAsyncMethod(method); } - public static boolean isAsyncMethod(@Nonnull Method method) { - // todo: should be extendable to support other reactive return type, eg: rxJava / project-reactor + public static boolean isAsyncMethod(Method method) { + // currently only support CompletableFuture for async method definition return method.getReturnType().equals(CompletableFuture.class); } + public static T toSync(CompletableFuture future, long waitInMillis) { + try { + if (waitInMillis > 0) { + return future.get(waitInMillis, TimeUnit.MILLISECONDS); + } + return future.get(); + } catch (ExecutionException executionException) { + throw AsyncUtils.rethrow(executionException.getCause()); + } catch (TimeoutException timeoutException) { + throw new InvocationException(Status.REQUEST_TIMEOUT, + new CommonExceptionData("Invocation Timeout."), timeoutException); + } catch (Throwable e) { + throw AsyncUtils.rethrow(e); + } + } + /** - * should never throw exception directly - * - * @param invocation invocation - * @return CompletableFuture + * This method is used in new Filter implementation to replace Handler + * NOTE: this method should never throw exception directly */ public static CompletableFuture invoke(Invocation invocation) { - invocation.onStart(null, System.nanoTime()); - invocation.onStartHandlersRequest(); - return invocation.getMicroserviceMeta().getFilterChain() + invocation.onStart(null); + return invocation.getMicroserviceMeta().getConsumerFilterChain() .onFilter(invocation) .exceptionally(throwable -> toConsumerResponse(invocation, throwable)) - .whenComplete((response, throwable) -> finishInvocation(invocation, response)); - } - - private static void finishInvocation(Invocation invocation, Response response) { - processMetrics(invocation, response); - - if (response.isFailed()) { - AsyncUtils.rethrow(response.getResult()); - } - } - - private static void processMetrics(Invocation invocation, Response response) { - invocation.getInvocationStageTrace().finishHandlersResponse(); - invocation.onFinish(response); + .whenComplete((response, throwable) -> invocation.onFinish(response)); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/MicroserviceReferenceConfig.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/MicroserviceReferenceConfig.java index d2670476ae2..60948bd130d 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/MicroserviceReferenceConfig.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/MicroserviceReferenceConfig.java @@ -16,74 +16,38 @@ */ package org.apache.servicecomb.core.provider.consumer; -import java.util.Objects; -import java.util.function.Supplier; - -import org.apache.servicecomb.core.definition.ConsumerMicroserviceVersionsMeta; -import org.apache.servicecomb.core.definition.CoreMetaUtils; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; -import org.apache.servicecomb.registry.consumer.MicroserviceVersionRule; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; -import org.apache.servicecomb.registry.consumer.StaticMicroserviceVersions; /** - *
- *   when the list data changed, MicroserviceReferenceConfig should rebuild:
- *     1.versionRule
- *     2.latestMicroserviceMeta
- *     3.microservice deleted
- * 
+ * microservice meta data for consumer. */ public class MicroserviceReferenceConfig { - private final ConsumerMicroserviceVersionsMeta microserviceVersionsMeta; - - private final MicroserviceVersionRule microserviceVersionRule; - - private final MicroserviceVersion latestMicroserviceVersion; - - private final MicroserviceMeta latestMicroserviceMeta; - - private final String versionRule; - - // return true means changed - private final Supplier versionRuleChangedChecker; - - public MicroserviceReferenceConfig(ConsumerMicroserviceVersionsMeta microserviceVersionsMeta, String versionRule) { - this.microserviceVersionsMeta = microserviceVersionsMeta; + private final String appId; - this.versionRule = - versionRule != null ? versionRule : microserviceVersionsMeta.getMicroserviceConfig().getVersionRule(); - this.versionRuleChangedChecker = this.versionRule != null ? this::checkByConfig : this::notChange; + private final String microserviceName; - microserviceVersionRule = microserviceVersionsMeta.getMicroserviceVersions() - .getOrCreateMicroserviceVersionRule(this.versionRule); - latestMicroserviceVersion = microserviceVersionRule.getLatestMicroserviceVersion(); - latestMicroserviceMeta = - latestMicroserviceVersion != null ? CoreMetaUtils.getMicroserviceMeta(latestMicroserviceVersion) : null; - } - - private Boolean notChange() { - return false; - } + private final MicroserviceMeta microserviceMeta; - private Boolean checkByConfig() { - return !Objects.equals(versionRule, microserviceVersionsMeta.getMicroserviceConfig().getVersionRule()); + public MicroserviceReferenceConfig( + String appId, + String microserviceName, + MicroserviceMeta microserviceMeta) { + this.appId = appId; + this.microserviceName = microserviceName; + this.microserviceMeta = microserviceMeta; } - public MicroserviceMeta getLatestMicroserviceMeta() { - if (latestMicroserviceVersion == null) { + public MicroserviceMeta getMicroserviceMeta() { + if (microserviceMeta == null) { throw new IllegalStateException( String.format( - "Probably invoke a service before it is registered, or no instance found for it, appId=%s, name=%s, versionRule=%s.", - microserviceVersionRule.getAppId(), - microserviceVersionRule.getMicroserviceName(), - versionRule)); + "Probably invoke a service before it is registered, or no instance found for it, appId=%s, name=%s.", + appId, + microserviceName)); } - return latestMicroserviceMeta; + return microserviceMeta; } public ReferenceConfig createReferenceConfig(OperationMeta operationMeta) { @@ -94,25 +58,7 @@ public ReferenceConfig createReferenceConfig(String transport, OperationMeta ope if (transport == null) { transport = operationMeta.getConfig().getTransport(); } - final ReferenceConfig referenceConfig = new ReferenceConfig(transport, versionRule); - mark3rdPartyService(operationMeta, referenceConfig); + final ReferenceConfig referenceConfig = new ReferenceConfig(transport); return referenceConfig; } - - private void mark3rdPartyService(OperationMeta operationMeta, ReferenceConfig referenceConfig) { - final MicroserviceVersions microserviceVersions = DiscoveryManager.INSTANCE - .getOrCreateMicroserviceVersions( - operationMeta.getMicroserviceMeta().getAppId(), - operationMeta.getMicroserviceName()); - referenceConfig.setThirdPartyService(microserviceVersions instanceof StaticMicroserviceVersions); - } - - public boolean isExpired() { - // 1.microservice deleted - // 2.latest version changed - // 3.versionRule configuration changed - return microserviceVersionsMeta.getMicroserviceVersions().isWaitingDelete() || - latestMicroserviceVersion != microserviceVersionRule.getLatestMicroserviceVersion() || - versionRuleChangedChecker.get(); - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfig.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfig.java index 0932f923f90..3b6ad24e610 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfig.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfig.java @@ -21,13 +21,8 @@ public class ReferenceConfig { protected String transport; - protected String versionRule; - - private boolean thirdPartyService; - - public ReferenceConfig(String transport, String versionRule) { + public ReferenceConfig(String transport) { this.transport = transport; - this.versionRule = versionRule; } public String getTransport() { @@ -37,21 +32,4 @@ public String getTransport() { public void setTransport(String transport) { this.transport = transport; } - - public boolean is3rdPartyService() { - return isThirdPartyService(); - } - - public String getVersionRule() { - return versionRule; - } - - public boolean isThirdPartyService() { - return thirdPartyService; - } - - public ReferenceConfig setThirdPartyService(boolean thirdPartyService) { - this.thirdPartyService = thirdPartyService; - return this; - } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigManager.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigManager.java new file mode 100644 index 00000000000..dffecfd62bf --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/ReferenceConfigManager.java @@ -0,0 +1,160 @@ +/* + * 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.core.provider.consumer; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.SCBEngine.CreateMicroserviceMetaEvent; +import org.apache.servicecomb.core.definition.ConsumerMicroserviceVersionsMeta; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.provider.OpenAPIRegistryManager; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.vertx.executor.VertxWorkerExecutor; +import org.apache.servicecomb.registry.definition.MicroserviceNameParser; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.beans.factory.annotation.Autowired; + +import io.swagger.v3.oas.models.OpenAPI; +import jakarta.ws.rs.core.Response.Status; + +public class ReferenceConfigManager { + // application -> microservice name + private final Map> referenceConfigs = new ConcurrentHashMapEx<>(); + + private final Map> referenceConfigsLocks = new ConcurrentHashMapEx<>(); + + private OpenAPIRegistryManager openAPIRegistryManager; + + @Autowired + public void setOpenAPIRegistryManager(OpenAPIRegistryManager openAPIRegistryManager) { + this.openAPIRegistryManager = openAPIRegistryManager; + this.openAPIRegistryManager.addOpenAPIChangeListener(this::onOpenAPIChanged); + } + + private void onOpenAPIChanged(String application, String serviceName) { + if (referenceConfigs.get(application) != null && referenceConfigs.get(application).get(serviceName) != null) { + MicroserviceReferenceConfig config = buildMicroserviceReferenceConfig(SCBEngine.getInstance(), application, + serviceName); + referenceConfigs.get(application).put(serviceName, config); + } + } + + public CompletableFuture getOrCreateReferenceConfigAsync + (SCBEngine scbEngine, String qualifiedName) { + MicroserviceNameParser parser = parseMicroserviceName(scbEngine, qualifiedName); + MicroserviceReferenceConfig config = referenceConfigs.computeIfAbsent(parser.getAppId(), + app -> new ConcurrentHashMapEx<>()) + .get(parser.getMicroserviceName()); + + if (config != null) { + return CompletableFuture.completedFuture(config); + } + + if (InvokerUtils.isInEventLoop()) { + CompletableFuture result = new CompletableFuture<>(); + VertxWorkerExecutor executor = new VertxWorkerExecutor(); + executor.execute(() -> { + synchronized (referenceConfigsLocks.computeIfAbsent(parser.getAppId(), key -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(parser.getMicroserviceName(), key -> new Object())) { + try { + MicroserviceReferenceConfig temp = referenceConfigs.get(parser.getAppId()) + .get(parser.getMicroserviceName()); + if (temp != null) { + result.complete(temp); + return; + } + temp = buildMicroserviceReferenceConfig(scbEngine, parser.getAppId(), + parser.getMicroserviceName()); + referenceConfigs.get(parser.getAppId()).put(parser.getMicroserviceName(), temp); + result.complete(temp); + } catch (Exception e) { + result.completeExceptionally(e); + } + } + }); + return result; + } else { + synchronized (referenceConfigsLocks.computeIfAbsent(parser.getAppId(), key -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(parser.getMicroserviceName(), key -> new Object())) { + MicroserviceReferenceConfig temp = referenceConfigs.get(parser.getAppId()) + .get(parser.getMicroserviceName()); + if (temp != null) { + return CompletableFuture.completedFuture(temp); + } + temp = buildMicroserviceReferenceConfig(scbEngine, parser.getAppId(), + parser.getMicroserviceName()); + referenceConfigs.get(parser.getAppId()).put(parser.getMicroserviceName(), temp); + return CompletableFuture.completedFuture(temp); + } + } + } + + public MicroserviceReferenceConfig getOrCreateReferenceConfig(SCBEngine scbEngine, String qualifiedName) { + MicroserviceNameParser parser = parseMicroserviceName(scbEngine, qualifiedName); + MicroserviceReferenceConfig config = referenceConfigs.computeIfAbsent(parser.getAppId(), + app -> new ConcurrentHashMapEx<>()) + .get(parser.getMicroserviceName()); + if (config == null) { + synchronized (referenceConfigsLocks.computeIfAbsent(parser.getAppId(), key -> new ConcurrentHashMapEx<>()) + .computeIfAbsent(parser.getMicroserviceName(), key -> new Object())) { + config = referenceConfigs.get(parser.getAppId()).get(parser.getMicroserviceName()); + if (config != null) { + return config; + } + config = buildMicroserviceReferenceConfig(scbEngine, parser.getAppId(), parser.getMicroserviceName()); + referenceConfigs.get(parser.getAppId()).put(parser.getMicroserviceName(), config); + return config; + } + } + return config; + } + + private MicroserviceNameParser parseMicroserviceName(SCBEngine scbEngine, String microserviceName) { + return new MicroserviceNameParser(scbEngine.getAppId(), microserviceName); + } + + private MicroserviceReferenceConfig buildMicroserviceReferenceConfig(SCBEngine engine, + String application, String microserviceName) { + ConsumerMicroserviceVersionsMeta microserviceVersionsMeta = new ConsumerMicroserviceVersionsMeta(engine); + MicroserviceMeta microserviceMeta = new MicroserviceMeta(engine, application, microserviceName, true); + microserviceMeta.setConsumerFilterChain(engine.getFilterChainsManager() + .findConsumerChain(application, microserviceName)); + microserviceMeta.setEdgeFilterChain(engine.getFilterChainsManager() + .findEdgeChain(application, microserviceName)); + microserviceMeta.setMicroserviceVersionsMeta(microserviceVersionsMeta); + + Map schemas = this.openAPIRegistryManager.loadOpenAPI(application, microserviceName); + for (Entry entry : schemas.entrySet()) { + OpenAPI swagger = entry.getValue(); + if (swagger != null) { + microserviceMeta.registerSchemaMeta(entry.getKey(), entry.getValue()); + continue; + } + throw new InvocationException(Status.INTERNAL_SERVER_ERROR, + String.format("Swagger %s/%s/%s can not be empty or load swagger failed.", + application, microserviceName, entry.getKey())); + } + + EventManager.getEventBus().post(new CreateMicroserviceMetaEvent(microserviceMeta)); + return new MicroserviceReferenceConfig(application, + microserviceName, microserviceMeta); + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/SyncResponseExecutor.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/SyncResponseExecutor.java index 1c5a2603cce..8e86d9d7f90 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/SyncResponseExecutor.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/SyncResponseExecutor.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.core.provider.consumer; -import static javax.ws.rs.core.Response.Status.REQUEST_TIMEOUT; +import static jakarta.ws.rs.core.Response.Status.REQUEST_TIMEOUT; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; @@ -33,7 +33,7 @@ * 将应答流程包装为Runnable,先唤醒业务线程,再在业务线程中执行runnable */ public class SyncResponseExecutor implements Executor { - private CountDownLatch latch; + private final CountDownLatch latch; private Runnable cmd; @@ -91,13 +91,14 @@ private void guardedWait(Invocation invocation) throws InvocationException { } private long getWaitTime(Invocation invocation) { - if (invocation.getOperationMeta().getConfig().getMsRequestTimeout() <= 0) { + if (invocation.getOperationMeta().getConfig().getMsInvocationTimeout() > 0) { + // if invocation timeout configured, use it. return invocation.getOperationMeta().getConfig().getMsInvocationTimeout(); } - if (invocation.getOperationMeta().getConfig().getMsInvocationTimeout() <= 0) { - return invocation.getOperationMeta().getConfig().getMsRequestTimeout(); - } - return Math.min(invocation.getOperationMeta().getConfig().getMsRequestTimeout(), - invocation.getOperationMeta().getConfig().getMsInvocationTimeout()); + + // In invocation handlers, may call other microservices, invocation + // timeout may be much longer than request timeout. + // For simplicity, default 30000 or two times of request timeout. + return Math.max(invocation.getOperationMeta().getConfig().getMsRequestTimeout() * 2, 30000); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerBootListener.java b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerBootListener.java index 0c0a5733e06..7dc291157d3 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerBootListener.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerBootListener.java @@ -18,87 +18,78 @@ package org.apache.servicecomb.core.provider.producer; import java.io.Closeable; -import java.util.LinkedHashMap; -import java.util.Map; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.concurrent.ExecutorService; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.io.FileUtils; +import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.foundation.common.utils.ClassLoaderScopeContext; import org.apache.servicecomb.foundation.common.utils.IOUtils; import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.BasePath; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.definition.DefinitionConst; import org.apache.servicecomb.swagger.SwaggerUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; -import com.netflix.config.DynamicPropertyFactory; - -import io.swagger.models.Scheme; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; public class ProducerBootListener implements BootListener { private static final Logger LOGGER = LoggerFactory.getLogger(ProducerBootListener.class); - @Override - public void onAfterTransport(BootEvent event) { - // register schema to microservice; - Microservice microservice = RegistrationManager.INSTANCE.getMicroservice(); + private static final String PATTERN = File.separator + "microservices" + + File.separator + "%s" + File.separator + "%s.yaml"; - String swaggerSchema = "http"; - for (String endpoint : microservice.getInstance().getEndpoints()) { - if (endpoint.startsWith("rest://") && endpoint.indexOf("sslEnabled=true") > 0) { - swaggerSchema = "https"; - } - } + private static final String TMP_DIR = System.getProperty("java.io.tmpdir"); - MicroserviceMeta microserviceMeta = event.getScbEngine().getProducerMicroserviceMeta(); - for (SchemaMeta schemaMeta : microserviceMeta.getSchemaMetas().values()) { - Swagger swagger = schemaMeta.getSwagger(); - swagger.addScheme(Scheme.forValue(swaggerSchema)); - String content = SwaggerUtils.swaggerToString(swagger); - LOGGER.info("generate swagger for {}/{}/{}, swagger: {}", - microserviceMeta.getAppId(), - microserviceMeta.getMicroserviceName(), - schemaMeta.getSchemaId(), - content); + private RegistrationManager registrationManager; - RegistrationManager.INSTANCE.addSchema(schemaMeta.getSchemaId(), content); - } + private Environment environment; - saveBasePaths(microserviceMeta); + @Autowired + public void setRegistrationManager(RegistrationManager registrationManager) { + this.registrationManager = registrationManager; } - // just compatible to old 3rd components, servicecomb not use it...... - private void saveBasePaths(MicroserviceMeta microserviceMeta) { - if (!DynamicPropertyFactory.getInstance().getBooleanProperty(DefinitionConst.REGISTER_SERVICE_PATH, false).get()) { - return; - } + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } - String urlPrefix = ClassLoaderScopeContext.getClassLoaderScopeProperty(DefinitionConst.URL_PREFIX); - Map basePaths = new LinkedHashMap<>(); - for (SchemaMeta schemaMeta : microserviceMeta.getSchemaMetas().values()) { - Swagger swagger = schemaMeta.getSwagger(); + @Override + public void onAfterTransport(BootEvent event) { + boolean exportToFile = environment.getProperty(CoreConst.SWAGGER_EXPORT_ENABLED, boolean.class, true); + String filePath = environment.getProperty(CoreConst.SWAGGER_DIRECTORY, String.class, TMP_DIR) + PATTERN; - String basePath = swagger.getBasePath(); - if (StringUtils.isNotEmpty(urlPrefix) && !basePath.startsWith(urlPrefix)) { - basePath = urlPrefix + basePath; - } - if (StringUtils.isNotEmpty(basePath)) { - BasePath basePathObj = new BasePath(); - basePathObj.setPath(basePath); - basePaths.put(basePath, basePathObj); + if (exportToFile) { + LOGGER.info("export microservice swagger file to path {}", filePath); + } + // register schema to microservice; + MicroserviceMeta microserviceMeta = event.getScbEngine().getProducerMicroserviceMeta(); + for (SchemaMeta schemaMeta : microserviceMeta.getSchemaMetas().values()) { + OpenAPI swagger = schemaMeta.getSwagger(); + String content = SwaggerUtils.swaggerToString(swagger); + if (exportToFile) { + exportToFile(String.format(filePath, + BootStrapProperties.readServiceName(environment), schemaMeta.getSchemaId()), content); + } else { + LOGGER.info("generate swagger for {}/{}/{}, swagger: {}", + microserviceMeta.getAppId(), + microserviceMeta.getMicroserviceName(), + schemaMeta.getSchemaId(), + content); } + this.registrationManager.addSchema(schemaMeta.getSchemaId(), content); } - - RegistrationManager.INSTANCE.addBasePath(basePaths.values()); } + // bug: can not close all thread for edge @Override public void onAfterClose(BootEvent event) { @@ -108,12 +99,12 @@ public void onAfterClose(BootEvent event) { } for (OperationMeta operationMeta : microserviceMeta.getOperations()) { - if (ExecutorService.class.isInstance(operationMeta.getExecutor())) { + if (operationMeta.getExecutor() instanceof ExecutorService) { ((ExecutorService) operationMeta.getExecutor()).shutdown(); continue; } - if (Closeable.class.isInstance(operationMeta.getExecutor())) { + if (operationMeta.getExecutor() instanceof Closeable) { IOUtils.closeQuietly((Closeable) operationMeta.getExecutor()); continue; } @@ -122,4 +113,24 @@ public void onAfterClose(BootEvent event) { operationMeta.getExecutor().getClass().getName()); } } + + private void exportToFile(String fileName, String content) { + File file = new File(fileName); + if (!file.getParentFile().exists()) { + if (!file.getParentFile().mkdirs()) { + LOGGER.error("create file directory failed"); + return; + } + } + if (file.exists()) { + file.delete(); + } + try { + file.createNewFile(); + FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8, false); + file.setReadOnly(); + } catch (IOException e) { + LOGGER.error("export swagger content to file failed, message: {}", e.getMessage()); + } + } } diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java index 5c489c7bf4c..391bc6a4723 100644 --- a/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java +++ b/core/src/main/java/org/apache/servicecomb/core/provider/producer/ProducerProviderManager.java @@ -23,6 +23,7 @@ import java.util.concurrent.Executor; import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.core.ProducerProvider; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.CoreMetaUtils; @@ -33,24 +34,23 @@ import org.apache.servicecomb.foundation.common.utils.ClassLoaderScopeContext; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.apache.servicecomb.swagger.SwaggerUtils; import org.apache.servicecomb.swagger.engine.SwaggerProducer; import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.config.DynamicPropertyFactory; - -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; public class ProducerProviderManager { private static final Logger LOGGER = LoggerFactory.getLogger(ProducerProviderManager.class); - private List producerProviderList = new ArrayList<>( + private final List producerProviderList = new ArrayList<>( SPIServiceUtils.getOrLoadSortedService(ProducerProvider.class)); - private SCBEngine scbEngine; + private final SCBEngine scbEngine; - private List producerMetas = new ArrayList<>(); + private final List producerMetas = new ArrayList<>(); public ProducerProviderManager(SCBEngine scbEngine) { this.scbEngine = scbEngine; @@ -94,15 +94,16 @@ public SchemaMeta registerSchema(String schemaId, Object instance) { public SchemaMeta registerSchema(String schemaId, Class schemaInterface, Object instance) { MicroserviceMeta producerMicroserviceMeta = scbEngine.getProducerMicroserviceMeta(); - Swagger swagger = scbEngine.getSwaggerLoader().loadLocalSwagger( - producerMicroserviceMeta.getAppId(), - producerMicroserviceMeta.getShortName(), - schemaId); SwaggerProducer swaggerProducer = scbEngine.getSwaggerEnvironment() - .createProducer(instance, schemaInterface, swagger); - swagger = swaggerProducer.getSwagger(); + .createProducer(instance, schemaInterface); + OpenAPI swagger = swaggerProducer.getSwagger(); registerUrlPrefixToSwagger(swagger); + // register self OpenAPI to registry + scbEngine.getOpenAPIRegistryManager() + .registerOpenAPI(BootStrapProperties.readApplication(scbEngine.getEnvironment()), + BootStrapProperties.readServiceName(scbEngine.getEnvironment()), schemaId, swagger); + SchemaMeta schemaMeta = producerMicroserviceMeta.registerSchemaMeta(schemaId, swagger); schemaMeta.putExtData(CoreMetaUtils.SWAGGER_PRODUCER, swaggerProducer); Executor reactiveExecutor = scbEngine.getExecutorManager().findExecutorById(ExecutorManager.EXECUTOR_REACTIVE); @@ -119,15 +120,14 @@ public SchemaMeta registerSchema(String schemaId, Class schemaInterface, Obje } // This is special requirement by users: When service deployed in tomcat,user want to use RestTemplate to - // call REST service by the full url. e.g. restTemplate.getForObejct("cse://serviceName/root/prefix/health") - // By default, user's do not need context prefix, e.g. restTemplate.getForObejct("cse://serviceName/health") - private void registerUrlPrefixToSwagger(Swagger swagger) { + // call REST service by the full url. e.g. restTemplate.getForObject("cse://serviceName/root/prefix/health") + // By default, user's do not need context prefix, e.g. restTemplate.getForObject("cse://serviceName/health") + private void registerUrlPrefixToSwagger(OpenAPI swagger) { String urlPrefix = ClassLoaderScopeContext.getClassLoaderScopeProperty(DefinitionConst.URL_PREFIX); - if (!StringUtils.isEmpty(urlPrefix) && !swagger.getBasePath().startsWith(urlPrefix) - && DynamicPropertyFactory.getInstance() - .getBooleanProperty(DefinitionConst.REGISTER_URL_PREFIX, false).get()) { - LOGGER.info("Add swagger base path prefix for {} with {}", swagger.getBasePath(), urlPrefix); - swagger.setBasePath(urlPrefix + swagger.getBasePath()); + if (!StringUtils.isEmpty(urlPrefix) && !SwaggerUtils.getBasePath(swagger).startsWith(urlPrefix) + && scbEngine.getEnvironment().getProperty(DefinitionConst.REGISTER_URL_PREFIX, boolean.class, false)) { + LOGGER.info("Add swagger base path prefix for {} with {}", SwaggerUtils.getBasePath(swagger), urlPrefix); + SwaggerUtils.setBasePath(swagger, urlPrefix + SwaggerUtils.getBasePath(swagger)); } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/servicecomb/core/registry/ThirdServiceRegister.java b/core/src/main/java/org/apache/servicecomb/core/registry/ThirdServiceRegister.java deleted file mode 100644 index 375d3e9830f..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/registry/ThirdServiceRegister.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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.core.registry; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.core.invocation.endpoint.EndpointUtils; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; -import org.apache.servicecomb.registry.consumer.StaticMicroserviceVersions; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.EnvironmentAware; -import org.springframework.core.env.Environment; -import org.springframework.util.CollectionUtils; - -/** - *
- * for declare a 3rd service as a servicecomb service
- * assume a 3rd service:
- *   1. named svc
- *   2. have 2 address: https://svc-1 and https://svc-2
- *   3. have 2 schemas: schema1 and schema2
- *
- * usage:
- *   1. define schema interface in JAX-RS or springMVC mode
- *     1) schema1
- *      {@code
- *        @Path("/v1/svc")
- *        public interface Schema1Client {
- *          @GET
- *          @Path("/add")
- *          int add(@QueryParam("q-x") int x, @QueryParam("q-y") int y);
- *
- *          @GET
- *          @Path("/minus")
- *          int minus(@QueryParam("q-x") int x, @QueryParam("q-y") int y);
- *        }
- *      }
- *     2) schema2
- *   2. add configuration to microservice.yaml
- *      {@code
- *        svc:
- *          urls:
- *            - https://svc-1
- *            - https://svc-2
- *      }
- *   3. declare the 3rd service
- *      {@code
- *        @Configuration
- *        public class Svc extends ThirdServiceRegister {
- *          public static final String NAME = "svc";
- *
- *          public Svc() {
- *            super(NAME);
- *
- *            addSchema("schema1", Schema1Client.class);
- *            addSchema("schema2", Schema2Client.class);
- *          }
- *        }
- *      }
- * 
- */ -public abstract class ThirdServiceRegister implements BootListener, EnvironmentAware { - private static final Logger LOGGER = LoggerFactory.getLogger(ThirdServiceRegister.class); - - public static final int ORDER = -1000; - - public static final String VERSION = "1.0"; - - public static final List DEFAULT_ADDRESSES = Collections.singletonList("http://127.0.0.1"); - - /** - * role: {@link EndpointUtils}
- * default to any address - */ - protected List urls = DEFAULT_ADDRESSES; - - protected String appId; - - protected final String microserviceName; - - // for 3rd service, schema interface is client interface too - protected final Map> schemaByIdMap = new HashMap<>(); - - public ThirdServiceRegister(String microserviceName) { - this.microserviceName = microserviceName; - } - - @Override - public int getOrder() { - return ORDER; - } - - public List getUrls() { - return urls; - } - - @Override - public void setEnvironment(Environment environment) { - String urlKey = microserviceName + ".urls"; - @SuppressWarnings("unchecked") - List urls = environment.getProperty(urlKey, List.class); - setUrls(urlKey, urls); - } - - public void setUrls(String urlKey, List urls) { - if (CollectionUtils.isEmpty(urls)) { - LOGGER.warn("missing configuration, key = {}", urlKey); - return; - } - - this.urls = urls; - } - - protected void addSchema(String schemaId, Class schemaCls) { - schemaByIdMap.put(schemaId, schemaCls); - } - - @Override - public void onBeforeRegistry(BootEvent event) { - appId = event.getScbEngine().getAppId(); - registerMicroserviceMapping(); - } - - protected void registerMicroserviceMapping() { - List endpoints = createEndpoints(); - List instances = createInstances(endpoints); - - DiscoveryManager.INSTANCE.getAppManager() - .getOrCreateMicroserviceManager(appId) - .getVersionsByName() - .computeIfAbsent(microserviceName, svcName -> createMicroserviceVersions(instances)); - - LOGGER.info("register third service, name={}, endpoints={}.", microserviceName, endpoints); - } - - protected List createEndpoints() { - return urls.stream() - .map(EndpointUtils::formatFromUri) - .collect(Collectors.toList()); - } - - protected List createInstances(List endpoints) { - return endpoints.stream() - .map(endpoint -> { - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setEndpoints(Collections.singletonList(endpoint)); - return instance; - }) - .collect(Collectors.toList()); - } - - protected MicroserviceVersions createMicroserviceVersions(List instances) { - return new StaticMicroserviceVersions( - DiscoveryManager.INSTANCE.getAppManager(), - appId, - microserviceName) - .init(schemaByIdMap, VERSION, instances); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/registry/discovery/EndpointDiscoveryFilter.java b/core/src/main/java/org/apache/servicecomb/core/registry/discovery/EndpointDiscoveryFilter.java index 80c060e65d8..666626b0697 100644 --- a/core/src/main/java/org/apache/servicecomb/core/registry/discovery/EndpointDiscoveryFilter.java +++ b/core/src/main/java/org/apache/servicecomb/core/registry/discovery/EndpointDiscoveryFilter.java @@ -21,16 +21,27 @@ import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; import org.apache.servicecomb.registry.discovery.AbstractEndpointDiscoveryFilter; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; public class EndpointDiscoveryFilter extends AbstractEndpointDiscoveryFilter { private static final Logger LOGGER = LoggerFactory.getLogger(EndpointDiscoveryFilter.class); + protected SCBEngine scbEngine; + + public EndpointDiscoveryFilter() { + } + + @Autowired + public void setScbEngine(SCBEngine scbEngine) { + this.scbEngine = scbEngine; + } + @Override public int getOrder() { return Short.MAX_VALUE; @@ -44,8 +55,8 @@ protected String findTransportName(DiscoveryContext context, DiscoveryTreeNode p @Override protected Object createEndpoint(DiscoveryContext context, String transportName, String endpoint, - MicroserviceInstance instance) { - Transport transport = SCBEngine.getInstance().getTransportManager().findTransport(transportName); + StatefulDiscoveryInstance instance) { + Transport transport = scbEngine.getTransportManager().findTransport(transportName); if (transport == null) { LOGGER.info("not deployed transport {}, ignore {}.", transportName, endpoint); return null; diff --git a/core/src/main/java/org/apache/servicecomb/core/registry/discovery/OperationInstancesDiscoveryFilter.java b/core/src/main/java/org/apache/servicecomb/core/registry/discovery/OperationInstancesDiscoveryFilter.java deleted file mode 100644 index a61b3535693..00000000000 --- a/core/src/main/java/org/apache/servicecomb/core/registry/discovery/OperationInstancesDiscoveryFilter.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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.core.registry.discovery; - -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.CoreMetaUtils; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.consumer.AppManager; -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; -import org.apache.servicecomb.registry.discovery.AbstractDiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.apache.servicecomb.registry.version.VersionRule; -import org.apache.servicecomb.registry.version.VersionRuleUtils; - -import com.netflix.config.DynamicPropertyFactory; - -/** - *
- *   create operation related instances
- *
- *   Preconditions:
- *     compatible is ensure by appManager.getOrCreateMicroserviceVersionRule
- *     instances in "DiscoveryTreeNode parent" are compatible:
- *       new version can only add operations, not delete operations
- *
- *   eg:
- *     microservice name is ms1
- *     2 instances are 1.0.0, instance id are i1/i2, schemaId is s1, operations are o1/o2
- *     3 instances are 1.0.1, instance id are i3/i4/i5, schemaId is s1, operations are o1/o2/o3
- *
- *     will create nodes:
- *     {
- *       "ms1.s1.o1": {
- *         {"i1": instance-i1}, {"i2": instance-i2}, {"i3": instance-i3}, {"i4": instance-i4}, {"i5": instance-i5}
- *       },
- *       "ms1.s1.o2": {
- *         {"i1": instance-i1}, {"i2": instance-i2}, {"i3": instance-i3}, {"i4": instance-i4}, {"i5": instance-i5}
- *       },
- *       "ms1.s1.o3": {
- *         {"i3": instance-i3}, {"i4": instance-i4}, {"i5": instance-i5}
- *       },
- *     }
- *
- *     that means, if invoke o1 or o2, can use 5 instances, but if invoke o3, can only use 3 instances
- *     by this filter, we can make sure that new operations will not route to old instances
- * 
- */ -public class OperationInstancesDiscoveryFilter extends AbstractDiscoveryFilter { - @Override - public int getOrder() { - return -20000; - } - - @Override - public boolean enabled() { - return DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.loadbalance.filter.operation.enabled", true).get(); - } - - @Override - public boolean isGroupingFilter() { - return true; - } - - @Override - protected String findChildName(DiscoveryContext context, DiscoveryTreeNode parent) { - Invocation invocation = context.getInputParameters(); - return invocation.getMicroserviceQualifiedName(); - } - - @Override - public void init(DiscoveryContext context, DiscoveryTreeNode parent) { - Invocation invocation = context.getInputParameters(); - // sort versions - List microserviceVersions = sortedMicroserviceVersion(invocation, parent.data()); - - Map operationNodes = new ConcurrentHashMapEx<>(); - for (MicroserviceVersion microserviceVersion : microserviceVersions) { - MicroserviceMeta microserviceMeta = CoreMetaUtils.getMicroserviceMeta(microserviceVersion); - for (OperationMeta operationMeta : microserviceMeta.getOperations()) { - DiscoveryTreeNode node = operationNodes.get(operationMeta.getMicroserviceQualifiedName()); - if (node == null) { - Map instanceMap = microserviceVersion.getInstances().stream() - .collect(Collectors.toMap(MicroserviceInstance::getInstanceId, Function.identity())); - DiscoveryTreeNode tempNode = createOperationNode(parent, microserviceVersion); - tempNode.data(instanceMap); - operationNodes.put(operationMeta.getMicroserviceQualifiedName(), tempNode); - continue; - } - - // exist, append instances - microserviceVersion.getInstances().forEach(microserviceInstance -> - node.mapData().put(microserviceInstance.getInstanceId(), microserviceInstance)); - } - } - - parent.children(operationNodes); - } - - protected List sortedMicroserviceVersion(Invocation invocation, - Map instances) { - OperationMeta latestOperationMeta = invocation.getOperationMeta(); - MicroserviceMeta latestMicroserviceMeta = latestOperationMeta.getSchemaMeta().getMicroserviceMeta(); - AppManager appManager = DiscoveryManager.INSTANCE.getAppManager(); - MicroserviceVersions microserviceVersions = - appManager.getOrCreateMicroserviceVersions(latestMicroserviceMeta.getAppId(), - latestMicroserviceMeta.getMicroserviceName()); - - Map uniqueMicroserviceVersion = new HashMap<>(); - for (MicroserviceInstance instance : instances.values()) { - MicroserviceVersion microserviceVersion = microserviceVersions.getVersion(instance.getServiceId()); - uniqueMicroserviceVersion.put(instance.getServiceId(), microserviceVersion); - } - return uniqueMicroserviceVersion.values().stream().sorted(Comparator.comparing(MicroserviceVersion::getVersion)) - .collect(Collectors.toList()); - } - - private DiscoveryTreeNode createOperationNode(DiscoveryTreeNode parent, MicroserviceVersion microserviceVersion) { - VersionRule versionRule = VersionRuleUtils.getOrCreate(microserviceVersion.getVersion().getVersion() + "+"); - return new DiscoveryTreeNode() - .subName(parent, versionRule.getVersionRule()) - .data(new HashMap<>()); - } -} diff --git a/core/src/main/java/org/apache/servicecomb/core/tracing/BraveTraceIdGenerator.java b/core/src/main/java/org/apache/servicecomb/core/tracing/BraveTraceIdGenerator.java index 7a2eee0ead0..6f888c813e7 100644 --- a/core/src/main/java/org/apache/servicecomb/core/tracing/BraveTraceIdGenerator.java +++ b/core/src/main/java/org/apache/servicecomb/core/tracing/BraveTraceIdGenerator.java @@ -17,14 +17,14 @@ package org.apache.servicecomb.core.tracing; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import brave.internal.Platform; public class BraveTraceIdGenerator implements TraceIdGenerator { @Override public String getTraceIdKeyName() { - return Const.TRACE_ID_NAME; + return CoreConst.TRACE_ID_NAME; } @Override diff --git a/core/src/main/java/org/apache/servicecomb/core/tracing/TraceIdLogger.java b/core/src/main/java/org/apache/servicecomb/core/tracing/TraceIdLogger.java index 72fd77a3909..3819bb90218 100644 --- a/core/src/main/java/org/apache/servicecomb/core/tracing/TraceIdLogger.java +++ b/core/src/main/java/org/apache/servicecomb/core/tracing/TraceIdLogger.java @@ -18,18 +18,19 @@ import org.apache.servicecomb.core.Invocation; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.slf4j.MDC; import org.slf4j.Marker; public class TraceIdLogger { + private static final Logger LOGGER = LoggerFactory.getLogger("scb-trace-id"); + private static final Marker MARKER = new ScbMarker(); - private static final String KEY_TRACE_ID = "SERVICECOMB_TRACE_ID"; + public static final String KEY_TRACE_ID = "SERVICECOMB_TRACE_ID"; private final Invocation invocation; - private String name; - public TraceIdLogger(Invocation invocation) { this.invocation = invocation; } @@ -38,34 +39,36 @@ public Invocation getInvocation() { return invocation; } + public static String constructSource(String source) { + return "[" + source + "(" + + Thread.currentThread().getStackTrace()[2].getLineNumber() + ")]"; + } + public final String getName() { - if (name == null) { - name = invocation.getTraceId() + "-" + invocation.getInvocationId(); - } - return name; + return invocation.getTraceId(); } - public void error(Logger logger, String format, Object... arguments) { + public void error(String format, Object... arguments) { MDC.put(KEY_TRACE_ID, getName()); - logger.error(MARKER, format, arguments); + LOGGER.error(MARKER, format, arguments); MDC.remove(KEY_TRACE_ID); } - public void warn(Logger logger, String format, Object... arguments) { + public void warn(String format, Object... arguments) { MDC.put(KEY_TRACE_ID, getName()); - logger.warn(MARKER, format, arguments); + LOGGER.warn(MARKER, format, arguments); MDC.remove(KEY_TRACE_ID); } - public void info(Logger logger, String format, Object... arguments) { + public void info(String format, Object... arguments) { MDC.put(KEY_TRACE_ID, getName()); - logger.info(MARKER, format, arguments); + LOGGER.info(MARKER, format, arguments); MDC.remove(KEY_TRACE_ID); } - public void debug(Logger logger, String format, Object... arguments) { + public void debug(String format, Object... arguments) { MDC.put(KEY_TRACE_ID, getName()); - logger.debug(MARKER, format, arguments); + LOGGER.debug(MARKER, format, arguments); MDC.remove(KEY_TRACE_ID); } } diff --git a/core/src/main/java/org/apache/servicecomb/core/transport/AbstractTransport.java b/core/src/main/java/org/apache/servicecomb/core/transport/AbstractTransport.java index 4013c298992..5c1ee3cc177 100644 --- a/core/src/main/java/org/apache/servicecomb/core/transport/AbstractTransport.java +++ b/core/src/main/java/org/apache/servicecomb/core/transport/AbstractTransport.java @@ -17,37 +17,49 @@ package org.apache.servicecomb.core.transport; +import java.net.Inet6Address; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.stream.Collectors; +import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.http.message.BasicNameValuePair; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.foundation.common.net.IpPort; import org.apache.servicecomb.foundation.common.net.NetUtils; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; import org.apache.servicecomb.foundation.vertx.SharedVertxFactory; -import org.apache.servicecomb.registry.RegistrationManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; import io.vertx.core.Vertx; public abstract class AbstractTransport implements Transport { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTransport.class); + public static final String PUBLISH_ADDRESS = "servicecomb.service.publishAddress"; + + private static final String PUBLISH_PORT = "servicecomb.{transport_name}.publishPort"; + /* * 用于参数传递:比如向RestServerVerticle传递endpoint地址。 */ public static final String ENDPOINT_KEY = "servicecomb.endpoint"; - protected Vertx transportVertx = SharedVertxFactory.getSharedVertx(); + protected Vertx transportVertx; protected Endpoint endpoint; protected Endpoint publishEndpoint; + protected Environment environment; + @Override public Endpoint getPublishEndpoint() { return publishEndpoint; @@ -58,6 +70,12 @@ public Endpoint getEndpoint() { return endpoint; } + @Override + public void setEnvironment(Environment environment) { + this.environment = environment; + this.transportVertx = SharedVertxFactory.getSharedVertx(environment); + } + protected void setListenAddressWithoutSchema(String addressWithoutSchema) { setListenAddressWithoutSchema(addressWithoutSchema, null); } @@ -72,7 +90,7 @@ protected void setListenAddressWithoutSchema(String addressWithoutSchema, this.endpoint = new Endpoint(this, NetUtils.getRealListenAddress(getName(), addressWithoutSchema)); if (this.endpoint.getEndpoint() != null) { - this.publishEndpoint = new Endpoint(this, RegistrationManager.getPublishAddress(getName(), + this.publishEndpoint = new Endpoint(this, getPublishAddress(getName(), addressWithoutSchema)); } else { this.publishEndpoint = null; @@ -91,9 +109,9 @@ private String genAddressWithoutSchema(String addressWithoutSchema, Map { - return new BasicNameValuePair(entry.getKey(), entry.getValue()); - }).collect(Collectors.toList()), StandardCharsets.UTF_8.name()); + String encodedQuery = URLEncodedUtils.format( + pairs.entrySet().stream().map(entry -> new BasicNameValuePair(entry.getKey(), entry.getValue())) + .collect(Collectors.toList()), StandardCharsets.UTF_8.name()); addressWithoutSchema += encodedQuery; @@ -107,4 +125,67 @@ public Object parseAddress(String address) { } return new URIEndpointObject(address); } + + /** + * In the case that listening address configured as 0.0.0.0, the publish address will be determined + * by the query result for the net interfaces. + * + * @return the publish address, or {@code null} if the param {@code address} is null. + */ + protected String getPublishAddress(String schema, String address) { + if (address == null) { + return address; + } + + try { + URI originalURI = new URI(schema + "://" + address); + IpPort ipPort = NetUtils.parseIpPort(originalURI); + if (ipPort == null) { + LOGGER.warn("address {} not valid.", address); + return null; + } + + IpPort publishIpPort = genPublishIpPort(schema, ipPort); + URIBuilder builder = new URIBuilder(originalURI); + return builder.setHost(publishIpPort.getHostOrIp()).setPort(publishIpPort.getPort()).build().toString(); + } catch (URISyntaxException e) { + LOGGER.warn("address {} not valid.", address); + return null; + } + } + + private IpPort genPublishIpPort(String schema, IpPort ipPort) { + String publicAddressSetting = environment.getProperty(PUBLISH_ADDRESS, ""); + publicAddressSetting = publicAddressSetting.trim(); + + String publishPortKey = PUBLISH_PORT.replace("{transport_name}", schema); + int publishPortSetting = environment.getProperty(publishPortKey, int.class, 0); + int publishPort = publishPortSetting == 0 ? ipPort.getPort() : publishPortSetting; + + if (publicAddressSetting.isEmpty()) { + InetSocketAddress socketAddress = ipPort.getSocketAddress(); + if (socketAddress.getAddress().isAnyLocalAddress()) { + String host = NetUtils.getHostAddress(); + if (Inet6Address.class.isInstance(socketAddress.getAddress())) { + host = NetUtils.getIpv6HostAddress(); + } + LOGGER.warn("address {}, auto select a host address to publish {}:{}, maybe not the correct one", + socketAddress, + host, + publishPort); + return new IpPort(host, publishPort); + } + + return ipPort; + } + + if (publicAddressSetting.startsWith("{") && publicAddressSetting.endsWith("}")) { + publicAddressSetting = NetUtils + .ensureGetInterfaceAddress( + publicAddressSetting.substring(1, publicAddressSetting.length() - 1)) + .getHostAddress(); + } + + return new IpPort(publicAddressSetting, publishPort); + } } diff --git a/core/src/main/java/org/apache/servicecomb/core/transport/TransportClassAnnotationProcessor.java b/core/src/main/java/org/apache/servicecomb/core/transport/TransportClassAnnotationProcessor.java new file mode 100644 index 00000000000..5af6705abc7 --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/transport/TransportClassAnnotationProcessor.java @@ -0,0 +1,43 @@ +/* + * 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.core.transport; + +import java.lang.reflect.Type; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.annotation.Transport; +import org.apache.servicecomb.swagger.generator.ClassAnnotationProcessor; +import org.apache.servicecomb.swagger.generator.SwaggerGenerator; + +import io.swagger.v3.oas.models.OpenAPI; + +public class TransportClassAnnotationProcessor implements ClassAnnotationProcessor { + @Override + public Type getProcessType() { + return Transport.class; + } + + @Override + public void process(SwaggerGenerator swaggerGenerator, Transport transport) { + OpenAPI swagger = swaggerGenerator.getOpenAPI(); + if (StringUtils.isNotEmpty(transport.name())) { + swagger.addExtension(CoreConst.TRANSPORT_NAME, transport.name()); + } + } +} diff --git a/core/src/main/java/org/apache/servicecomb/core/transport/TransportManager.java b/core/src/main/java/org/apache/servicecomb/core/transport/TransportManager.java index 850829783d3..64ed82a5c93 100644 --- a/core/src/main/java/org/apache/servicecomb/core/transport/TransportManager.java +++ b/core/src/main/java/org/apache/servicecomb/core/transport/TransportManager.java @@ -29,16 +29,28 @@ import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.registry.RegistrationManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; public class TransportManager { private static final Logger LOGGER = LoggerFactory.getLogger(TransportManager.class); - private List transports = new ArrayList<>(SPIServiceUtils.getOrLoadSortedService(Transport.class)); + private final List transports = new ArrayList<>(SPIServiceUtils.getOrLoadSortedService(Transport.class)); - private Map transportMap = new HashMap<>(); + private final Map transportMap = new HashMap<>(); + + public Map getTransportMap() { + return transportMap; + } + + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } public void clearTransportBeforeInit() { transports.clear(); @@ -53,6 +65,7 @@ public void addTransportsBeforeInit(List transports) { } public void init(SCBEngine scbEngine) throws Exception { + initEnvironment(); buildTransportMap(); for (Transport transport : transportMap.values()) { @@ -60,13 +73,19 @@ public void init(SCBEngine scbEngine) throws Exception { Endpoint endpoint = transport.getPublishEndpoint(); if (endpoint != null && endpoint.getEndpoint() != null) { LOGGER.info("endpoint to publish: {}", endpoint.getEndpoint()); - RegistrationManager.INSTANCE.addEndpoint(endpoint.getEndpoint()); + scbEngine.getRegistrationManager().addEndpoint(endpoint.getEndpoint()); } continue; } } } + private void initEnvironment() { + for (Transport transport : transports) { + transport.setEnvironment(environment); + } + } + protected void buildTransportMap() { Map> groups = groupByName(); diff --git a/core/src/main/java/org/apache/servicecomb/core/transport/TransportMethodAnnotationProcessor.java b/core/src/main/java/org/apache/servicecomb/core/transport/TransportMethodAnnotationProcessor.java new file mode 100644 index 00000000000..617f4b87d5e --- /dev/null +++ b/core/src/main/java/org/apache/servicecomb/core/transport/TransportMethodAnnotationProcessor.java @@ -0,0 +1,44 @@ +/* + * 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.core.transport; + +import java.lang.reflect.Type; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.annotation.Transport; +import org.apache.servicecomb.swagger.generator.MethodAnnotationProcessor; +import org.apache.servicecomb.swagger.generator.OperationGenerator; +import org.apache.servicecomb.swagger.generator.SwaggerGenerator; + +import io.swagger.v3.oas.models.Operation; + +public class TransportMethodAnnotationProcessor implements MethodAnnotationProcessor { + @Override + public Type getProcessType() { + return Transport.class; + } + + @Override + public void process(SwaggerGenerator swaggerGenerator, OperationGenerator operationGenerator, Transport transport) { + Operation operation = operationGenerator.getOperation(); + if (StringUtils.isNotEmpty(transport.name())) { + operation.addExtension(CoreConst.TRANSPORT_NAME, transport.name()); + } + } +} diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener deleted file mode 100644 index e6db84b3b38..00000000000 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.BootListener +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.core.provider.producer.ProducerBootListener \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector deleted file mode 100644 index c33b0de60b1..00000000000 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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.servicecomb.core.bootup.ServiceInformationCollector -org.apache.servicecomb.core.bootup.FilterChainCollector \ No newline at end of file diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter index 3417268543b..e170e610bf4 100644 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter @@ -20,4 +20,5 @@ org.apache.servicecomb.core.exception.converter.InvocationExceptionConverter org.apache.servicecomb.core.exception.converter.IllegalArgumentExceptionConverter org.apache.servicecomb.core.exception.converter.TimeoutExceptionConverter org.apache.servicecomb.core.exception.converter.ConnectTimeoutExceptionConverter -org.apache.servicecomb.core.exception.converter.DefaultExceptionConverter \ No newline at end of file +org.apache.servicecomb.core.exception.converter.DefaultExceptionConverter +org.apache.servicecomb.core.exception.converter.ServiceCombExceptionConverter diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider index 51f9e53fd2f..d21d7c1fe15 100644 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.core.filter.impl.DefaultFilterProvider \ No newline at end of file +org.apache.servicecomb.core.filter.impl.DefaultFilterProvider diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.tracing.TraceIdGenerator b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.tracing.TraceIdGenerator index 3a57a7db661..8e61e1f2b81 100644 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.tracing.TraceIdGenerator +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.core.tracing.TraceIdGenerator @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.core.tracing.BraveTraceIdGenerator \ No newline at end of file +org.apache.servicecomb.core.tracing.BraveTraceIdGenerator diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter b/core/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter deleted file mode 100644 index 9ff276f9a70..00000000000 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.core.registry.discovery.OperationInstancesDiscoveryFilter diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.ClassAnnotationProcessor b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.ClassAnnotationProcessor new file mode 100644 index 00000000000..57d906d8131 --- /dev/null +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.ClassAnnotationProcessor @@ -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.servicecomb.core.transport.TransportClassAnnotationProcessor diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.MethodAnnotationProcessor b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.MethodAnnotationProcessor new file mode 100644 index 00000000000..a003fcbd204 --- /dev/null +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.MethodAnnotationProcessor @@ -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.servicecomb.core.transport.TransportMethodAnnotationProcessor diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.SwaggerContextRegister b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.SwaggerContextRegister index 7fb23d9bc91..1356e33ecf8 100644 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.SwaggerContextRegister +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.generator.SwaggerContextRegister @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.core.invocation.endpoint.EndpointContextRegister \ No newline at end of file +org.apache.servicecomb.core.invocation.endpoint.EndpointContextRegister diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.arguments.consumer.ConsumerContextArgumentMapperFactory b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.arguments.consumer.ConsumerContextArgumentMapperFactory index 094ac2c2d11..6eb082fc473 100644 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.arguments.consumer.ConsumerContextArgumentMapperFactory +++ b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.arguments.consumer.ConsumerContextArgumentMapperFactory @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.core.invocation.endpoint.EndpointMapperFactory \ No newline at end of file +org.apache.servicecomb.core.invocation.endpoint.EndpointMapperFactory diff --git a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter b/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter deleted file mode 100644 index f703b9026fc..00000000000 --- a/core/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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.servicecomb.core.exception.IllegalArgumentExceptionToProducerResponseConverter -org.apache.servicecomb.core.exception.ThrowableExceptionToProducerResponseConverter \ No newline at end of file diff --git a/core/src/main/resources/META-INF/spring/cse.bean.xml b/core/src/main/resources/META-INF/spring/cse.bean.xml deleted file mode 100644 index 86568ecda72..00000000000 --- a/core/src/main/resources/META-INF/spring/cse.bean.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..74f863c2bda --- /dev/null +++ b/core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -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. +## --------------------------------------------------------------------------- + +org.apache.servicecomb.core.filter.CoreFilterConfiguration +org.apache.servicecomb.core.invocation.CoreInvocationConfiguration +org.apache.servicecomb.core.governance.CoreGovernanceConfiguration +org.apache.servicecomb.core.exception.CoreExceptionConfiguration +org.apache.servicecomb.core.ServiceCombCoreConfiguration diff --git a/core/src/main/resources/META-INF/spring/scb-core-bean.xml b/core/src/main/resources/META-INF/spring/scb-core-bean.xml deleted file mode 100644 index a37acb0cfaa..00000000000 --- a/core/src/main/resources/META-INF/spring/scb-core-bean.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - diff --git a/core/src/main/resources/config/cse.handler.xml b/core/src/main/resources/config/cse.handler.xml deleted file mode 100644 index 89510b4db65..00000000000 --- a/core/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/core/src/main/resources/microservice.yaml b/core/src/main/resources/microservice.yaml index 969e8ab1720..f77c5ce5601 100644 --- a/core/src/main/resources/microservice.yaml +++ b/core/src/main/resources/microservice.yaml @@ -16,32 +16,3 @@ ## --------------------------------------------------------------------------- servicecomb-config-order: -500 - -servicecomb: - exception: - invocation: - print-stack-trace: false - filter-chains: - enabled: false - transport: - scb-consumer-transport: - rest: rest-client-codec, rest-client-sender - scb-producer-transport: - rest: rest-server-codec - definition: - scb-consumer: simple-load-balance, scb-consumer-transport - scb-producer: scb-producer-transport, schedule, producer-operation - consumer: - framework: scb-consumer - # when there is no "default" chains, will read framework chains as "default" chains - #default: scb-consumer - # samples for customize microservice filter chain - #policies: - # ms-1: retry, load-balance, transport-client, ms-1-consumer-transport - producer: - framework: scb-producer - # when there is no "default" chains, will read framework chains as "default" chains - #default: scb-producer - # samples for customize microservice filter chain - #policies: - # ms-1: qps-limiter, ms-1-producer-transport, schedule, producer-operation \ No newline at end of file diff --git a/core/src/test/java/org/apache/servicecomb/core/TestConfig.java b/core/src/test/java/org/apache/servicecomb/core/TestConfig.java index 5162e893a42..a4584b1e64f 100644 --- a/core/src/test/java/org/apache/servicecomb/core/TestConfig.java +++ b/core/src/test/java/org/apache/servicecomb/core/TestConfig.java @@ -20,8 +20,8 @@ import java.util.HashMap; import java.util.Map; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.StatusType; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; @@ -29,17 +29,17 @@ import org.apache.servicecomb.swagger.invocation.context.HttpStatus; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestConfig { @Test public void testConstants() { - Assert.assertEquals("x-cse-context", Const.CSE_CONTEXT); - Assert.assertEquals("rest", Const.RESTFUL); - Assert.assertEquals("", Const.ANY_TRANSPORT); - Assert.assertEquals("latest", Const.VERSION_RULE_LATEST); - Assert.assertEquals("0.0.0.0+", Const.DEFAULT_VERSION_RULE); + Assertions.assertEquals("x-cse-context", CoreConst.CSE_CONTEXT); + Assertions.assertEquals("rest", CoreConst.RESTFUL); + Assertions.assertEquals("", CoreConst.ANY_TRANSPORT); + Assertions.assertEquals("latest", CoreConst.VERSION_RULE_LATEST); + Assertions.assertEquals("0.0.0.0+", CoreConst.DEFAULT_VERSION_RULE); } @Test @@ -47,69 +47,69 @@ public void testHttpResponse() { String objectString = new String("Unit Testing"); Response oResponse = Response.success(objectString, Status.OK); - Assert.assertEquals(true, oResponse.isSucceed()); + Assertions.assertTrue(oResponse.isSucceed()); oResponse = Response.succResp(objectString); - Assert.assertEquals(true, oResponse.isSucceed()); - Assert.assertEquals(200, oResponse.getStatusCode()); + Assertions.assertTrue(oResponse.isSucceed()); + Assertions.assertEquals(200, oResponse.getStatusCode()); Throwable oThrowable = new Throwable("Error"); oResponse = Response.consumerFailResp(oThrowable); - Assert.assertEquals(true, oResponse.isFailed()); + Assertions.assertTrue(oResponse.isFailed()); oResponse = Response.providerFailResp(oThrowable); - Assert.assertEquals(true, oResponse.isFailed()); + Assertions.assertTrue(oResponse.isFailed()); } @Test public void testHttpStatus() { StatusType oStatus = new HttpStatus(204, "InternalServerError"); - Assert.assertEquals("InternalServerError", oStatus.getReasonPhrase()); + Assertions.assertEquals("InternalServerError", oStatus.getReasonPhrase()); } @Test public void testContextUtils() { ThreadLocal contextMgr = new ThreadLocal<>(); - Assert.assertEquals(contextMgr.get(), ContextUtils.getInvocationContext()); + Assertions.assertEquals(contextMgr.get(), ContextUtils.getInvocationContext()); SwaggerInvocation invocation = new SwaggerInvocation(); invocation.addContext("test1", "testObject"); - Assert.assertEquals("testObject", invocation.getContext("test1")); + Assertions.assertEquals("testObject", invocation.getContext("test1")); Map context = new HashMap<>(); context.put("test2", new String("testObject")); invocation.setContext(context); - Assert.assertEquals(context, invocation.getContext()); + Assertions.assertEquals(context, invocation.getContext()); invocation.setStatus(Status.OK); - Assert.assertEquals(200, invocation.getStatus().getStatusCode()); + Assertions.assertEquals(200, invocation.getStatus().getStatusCode()); invocation.setStatus(204); - Assert.assertEquals(204, invocation.getStatus().getStatusCode()); + Assertions.assertEquals(204, invocation.getStatus().getStatusCode()); invocation.setStatus(Status.OK); - Assert.assertEquals((Status.OK).getStatusCode(), invocation.getStatus().getStatusCode()); + Assertions.assertEquals((Status.OK).getStatusCode(), invocation.getStatus().getStatusCode()); invocation.setStatus(203, "Done"); - Assert.assertEquals(203, invocation.getStatus().getStatusCode()); + Assertions.assertEquals(203, invocation.getStatus().getStatusCode()); ContextUtils.setInvocationContext(invocation); - Assert.assertEquals(invocation, ContextUtils.getInvocationContext()); + Assertions.assertEquals(invocation, ContextUtils.getInvocationContext()); ContextUtils.removeInvocationContext(); - Assert.assertEquals(null, ContextUtils.getInvocationContext()); + Assertions.assertNull(ContextUtils.getInvocationContext()); } @Test public void testResponse() { Response response = Response.create(400, "test", null); InvocationException exception = response.getResult(); - Assert.assertEquals(null, exception.getErrorData()); + Assertions.assertNull(exception.getErrorData()); response = Response.create(400, "test", "errorData"); exception = response.getResult(); - Assert.assertEquals("errorData", exception.getErrorData()); + Assertions.assertEquals("errorData", exception.getErrorData()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/TestConfigurationSpringInitializer.java b/core/src/test/java/org/apache/servicecomb/core/TestConfigurationSpringInitializer.java index 266274dd24f..27b38f60110 100644 --- a/core/src/test/java/org/apache/servicecomb/core/TestConfigurationSpringInitializer.java +++ b/core/src/test/java/org/apache/servicecomb/core/TestConfigurationSpringInitializer.java @@ -16,75 +16,35 @@ */ package org.apache.servicecomb.core; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.anyString; - import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Map.Entry; - -import org.apache.commons.configuration.Configuration; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Matchers; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; import org.mockito.Mockito; import org.mockito.stubbing.Answer; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.MutablePropertySources; -import org.springframework.core.env.PropertySource; -import org.springframework.core.env.StandardEnvironment; -import org.springframework.core.env.SystemEnvironmentPropertySource; import org.springframework.jndi.JndiPropertySource; -import com.netflix.config.ConfigurationManager; - -import mockit.Deencapsulation; - public class TestConfigurationSpringInitializer { - @Before + @BeforeEach public void beforeTest() { - Logger.getRootLogger().setLevel(Level.OFF); - - ConfigUtil.clearExtraConfig(); - ArchaiusUtils.resetConfig(); + Configurator.setRootLevel(Level.OFF); - Logger.getRootLogger().setLevel(Level.INFO); + Configurator.setRootLevel(Level.INFO); } - @After + @AfterEach public void afterTest() { - ConfigUtil.clearExtraConfig(); - ArchaiusUtils.resetConfig(); - } - @Test - public void testAll() { - ConfigurationSpringInitializer configurationSpringInitializer = new ConfigurationSpringInitializer(); - ConfigUtil.installDynamicConfig(); - - Object o = ConfigUtil.getProperty("zq"); - @SuppressWarnings("unchecked") - List> listO = (List>) o; - Assert.assertEquals(3, listO.size()); - Assert.assertNull(ConfigUtil.getProperty("notExist")); - - Configuration instance = ConfigurationManager.getConfigInstance(); - ConfigUtil.installDynamicConfig(); - // must not reinstall - Assert.assertEquals(instance, ConfigurationManager.getConfigInstance()); } @Test @@ -151,22 +111,10 @@ public void testSetEnvironment() { String value = propertyMap.get(propertyName); if (null == value) { - fail("get unexpected property name: " + propertyName); + Assertions.fail("get unexpected property name: " + propertyName); } return value; - }).when(environment).getProperty(anyString(), Matchers.eq(Object.class)); - - new ConfigurationSpringInitializer().setEnvironment(environment); - - Map> extraLocalConfig = getExtraConfigMapFromConfigUtil(); - assertFalse(extraLocalConfig.isEmpty()); - Map extraProperties = extraLocalConfig - .get(ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + environment.getClass().getName() + "@" - + environment.hashCode()); - assertNotNull(extraLocalConfig); - for (Entry entry : propertyMap.entrySet()) { - assertEquals(entry.getValue(), extraProperties.get(entry.getKey())); - } + }).when(environment).getProperty(ArgumentMatchers.anyString(), ArgumentMatchers.eq(Object.class)); } @Test @@ -200,52 +148,5 @@ public void testSetEnvironmentOnEnvironmentName() { propertySources2.addFirst(new MapPropertySource("mapPropertySource2", map2)); Mockito.when(environment2.getProperty("key2", Object.class)).thenReturn("value2"); Mockito.when(environment2.getProperty("key2")).thenReturn("value2"); - - ConfigurationSpringInitializer configurationSpringInitializer = new ConfigurationSpringInitializer(); - configurationSpringInitializer.setEnvironment(environment0); - configurationSpringInitializer.setEnvironment(environment1); - configurationSpringInitializer.setEnvironment(environment2); - - Map> extraConfig = getExtraConfigMapFromConfigUtil(); - assertEquals(3, extraConfig.size()); - - Map extraProperties = extraConfig - .get(ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + "application"); - assertEquals(1, extraProperties.size()); - assertEquals("application", extraProperties.get("spring.config.name")); - - extraProperties = extraConfig.get(ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + "bootstrap"); - assertEquals(1, extraProperties.size()); - assertEquals("bootstrap", extraProperties.get("spring.application.name")); - - extraProperties = extraConfig.get( - ConfigurationSpringInitializer.EXTRA_CONFIG_SOURCE_PREFIX + environment2.getClass().getName() + "@" - + environment2.hashCode()); - assertEquals(1, extraProperties.size()); - assertEquals("value2", extraProperties.get("key2")); - } - - @Test(expected = RuntimeException.class) - public void shoud_throw_exception_when_given_ignoreResolveFailure_false() { - StandardEnvironment environment = newStandardEnvironment(); - - ConfigurationSpringInitializer configurationSpringInitializer = new ConfigurationSpringInitializer(); - configurationSpringInitializer.setEnvironment(environment); - } - - private Map> getExtraConfigMapFromConfigUtil() { - return Deencapsulation - .getField(ConfigUtil.class, "EXTRA_CONFIG_MAP"); - } - - private StandardEnvironment newStandardEnvironment() { - Map envProperties = new HashMap<>(); - envProperties.put("IFS-X", "${IFS-X}"); - PropertySource> systemEnvironmentPropertySource = new SystemEnvironmentPropertySource("system-env", envProperties); - - StandardEnvironment environment = new StandardEnvironment(); - environment.getPropertySources() - .addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, systemEnvironmentPropertySource); - return environment; } } diff --git a/core/src/test/java/org/apache/servicecomb/core/TestConsumer.java b/core/src/test/java/org/apache/servicecomb/core/TestConsumer.java deleted file mode 100644 index 885e831b03a..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestConsumer.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.core; - -public class TestConsumer { -// -// @SuppressWarnings({"rawtypes", "unchecked"}) -// @Test -// public void testConsumerProviderManager() { -// ConsumerProviderManager oConsumerProviderManager = new ConsumerProviderManager(); -// RegisterManager oRegisterManager = new RegisterManager("cse consumer provider manager"); -// oRegisterManager.register("servicecomb.references.cse consumer provider manager", -// "cse consumer provider manager"); -// boolean validAssert = true; -// try { -// oConsumerProviderManager.getReferenceConfig("consumer provider manager"); -// } catch (Throwable ee) { -// Assert.assertNotEquals(null, ee); -// validAssert = false; -// } -// Assert.assertFalse(validAssert); -// } -// -// @Test -// public void testReferenceConfig() throws InterruptedException { -// Map oMap = new ConcurrentHashMap<>(); -// oMap.put("test1", "value1"); -// RegisterManager oManager = new RegisterManager<>("test"); -// oManager.register("test1", "value1"); -// -// SyncResponseExecutor oExecutor = new SyncResponseExecutor(); -// oExecutor.execute(new Runnable() { -// -// @Override -// public void run() { -// oExecutor.setResponse(Response.succResp("success")); -// } -// }); -// Assert.assertEquals(true, oExecutor.waitResponse().isSuccessed()); -// } -// -// @Test -// public void testInvocation() { -// OperationMeta oOperationMeta = Mockito.mock(OperationMeta.class); -// SchemaMeta oSchemaMeta = Mockito.mock(SchemaMeta.class); -// AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class); -// List oHandlerList = new ArrayList<>(); -// -// Mockito.when(oSchemaMeta.getProviderHandlerChain()).thenReturn(oHandlerList); -// Mockito.when(oSchemaMeta.getMicroserviceName()).thenReturn("TMK"); -// Mockito.when(oOperationMeta.getSchemaMeta()).thenReturn(oSchemaMeta); -// Endpoint oEndpoint = Mockito.mock(Endpoint.class); -// Transport oTransport = Mockito.mock(Transport.class); -// Mockito.when(oEndpoint.getTransport()).thenReturn(oTransport); -// Mockito.when(oOperationMeta.getOperationId()).thenReturn("TMK"); -// -// Invocation oInvocation = new Invocation(oEndpoint, oOperationMeta, null); -// Assert.assertNotNull(oInvocation.getTransport()); -// Assert.assertNotNull(oInvocation.getInvocationType()); -// oInvocation.setResponseExecutor(Mockito.mock(Executor.class)); -// Assert.assertNotNull(oInvocation.getResponseExecutor()); -// Assert.assertNotNull(oInvocation.getSchemaMeta()); -// Assert.assertNotNull(oInvocation.getOperationMeta()); -// Assert.assertNull(oInvocation.getArgs()); -// Assert.assertNotNull(oInvocation.getEndpoint()); -// oInvocation.setEndpoint(null); -// Map map = oInvocation.getContext(); -// Assert.assertNotNull(map); -// String str = oInvocation.getSchemaId(); -// Assert.assertEquals(null, str); -// String str1 = oInvocation.getMicroserviceName(); -// Assert.assertEquals("TMK", str1); -// Map mapp = oInvocation.getHandlerContext(); -// Assert.assertNotNull(mapp); -// Assert.assertEquals(true, oInvocation.getHandlerIndex() >= 0); -// oInvocation.setHandlerIndex(8); -// Assert.assertEquals("TMK", oInvocation.getOperationName()); -// Assert.assertEquals("TMK", oInvocation.getMicroserviceName()); -// -// boolean validAssert; -// -// try { -// -// validAssert = true; -// -// oInvocation.next(asyncResp); -// } catch (Exception e) { -// validAssert = false; -// } -// Assert.assertFalse(validAssert); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java b/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java deleted file mode 100644 index aac398c7c5c..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestCseApplicationListener.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.core; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.springframework.context.event.ContextClosedEvent; - -import mockit.Mocked; - -public class TestCseApplicationListener { - @Before - public void before() { - ConfigUtil.installDynamicConfig(); - } - - @AfterClass - public static void classTeardown() { - DiscoveryManager.renewInstance(); - ArchaiusUtils.resetConfig(); - } - - @Test - public void onApplicationEvent_close(@Mocked ContextClosedEvent contextClosedEvent) { - SCBEngine scbEngine = SCBBootstrap.createSCBEngineForTest(); - scbEngine.setStatus(SCBStatus.UP); - - CseApplicationListener listener = new CseApplicationListener(); - listener.onApplicationEvent(contextClosedEvent); - - Assert.assertEquals(SCBStatus.DOWN, scbEngine.getStatus()); - - scbEngine.destroy(); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/TestDefinition.java b/core/src/test/java/org/apache/servicecomb/core/TestDefinition.java deleted file mode 100644 index 3364e02c969..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestDefinition.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.core; - -public class TestDefinition { -// @Test -// public void testMicroServiceMeta() { -// MicroserviceMeta oMicroMeta = new MicroserviceMeta("app:micro1"); -// Assert.assertEquals(0, oMicroMeta.getSchemaMetas().size()); -// Assert.assertEquals(0, oMicroMeta.getOperations().size()); -// Assert.assertEquals("micro1", oMicroMeta.getShortName()); -// Assert.assertEquals("app:micro1", oMicroMeta.getName()); -// try { -// oMicroMeta.putExtData("key1", new String("value1")); -// Assert.assertNotEquals(null, oMicroMeta.getExtData("key1")); -// } catch (Exception e) { -// Assert.assertNotNull(e); -// } -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/TestEndpoint.java b/core/src/test/java/org/apache/servicecomb/core/TestEndpoint.java index 9be7e1bacc9..17e1ef0c5e1 100644 --- a/core/src/test/java/org/apache/servicecomb/core/TestEndpoint.java +++ b/core/src/test/java/org/apache/servicecomb/core/TestEndpoint.java @@ -17,35 +17,32 @@ package org.apache.servicecomb.core; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Mocked; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestEndpoint { @Test - public void testEndpoint(@Mocked Transport transport) { - new Expectations() { - { - transport.parseAddress("rest://123.6.6.6:8080"); - result = "rest://123.6.6.6:8080"; - } - }; + public void testEndpoint() { + Transport transport = Mockito.mock(Transport.class); + Mockito.when(transport.parseAddress("rest://123.6.6.6:8080")).thenReturn("rest://123.6.6.6:8080"); + Endpoint endpoint = new Endpoint(transport, "rest://123.6.6.6:8080"); - Assert.assertEquals(endpoint.getAddress(), "rest://123.6.6.6:8080"); - Assert.assertEquals(endpoint.getEndpoint(), "rest://123.6.6.6:8080"); - Assert.assertEquals(endpoint.getTransport(), transport); - Assert.assertEquals(endpoint.toString(), "rest://123.6.6.6:8080"); + Assertions.assertEquals(endpoint.getAddress(), "rest://123.6.6.6:8080"); + Assertions.assertEquals(endpoint.getEndpoint(), "rest://123.6.6.6:8080"); + Assertions.assertEquals(endpoint.getTransport(), transport); + Assertions.assertEquals(endpoint.toString(), "rest://123.6.6.6:8080"); } @Test - public void testEndpointAddressConstructor(@Mocked Transport transport, @Mocked MicroserviceInstance instance) { + public void testEndpointAddressConstructor() { + Transport transport = Mockito.mock(Transport.class); + StatefulDiscoveryInstance instance = Mockito.mock(StatefulDiscoveryInstance.class); Endpoint endpoint = new Endpoint(transport, "rest://123.6.6.6:8080", instance, "iot://123.6.6.6:8080"); - Assert.assertEquals(endpoint.getAddress(), "iot://123.6.6.6:8080"); - Assert.assertEquals(endpoint.getEndpoint(), "rest://123.6.6.6:8080"); - Assert.assertEquals(endpoint.getTransport(), transport); - Assert.assertEquals(endpoint.toString(), "rest://123.6.6.6:8080"); + Assertions.assertEquals(endpoint.getAddress(), "iot://123.6.6.6:8080"); + Assertions.assertEquals(endpoint.getEndpoint(), "rest://123.6.6.6:8080"); + Assertions.assertEquals(endpoint.getTransport(), transport); + Assertions.assertEquals(endpoint.toString(), "rest://123.6.6.6:8080"); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/TestException.java b/core/src/test/java/org/apache/servicecomb/core/TestException.java index e9646a1ff86..58bce6bce43 100644 --- a/core/src/test/java/org/apache/servicecomb/core/TestException.java +++ b/core/src/test/java/org/apache/servicecomb/core/TestException.java @@ -19,38 +19,38 @@ import org.apache.servicecomb.core.exception.CseException; import org.apache.servicecomb.core.exception.ExceptionUtils; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestException { @Test public void testCseException() { - CseException oExeception = new CseException("500", "InternalServerError"); - Assert.assertEquals("500", oExeception.getCode()); - Assert.assertEquals("ServiceDefinitionException Code:500, Message:InternalServerError", - oExeception.toString()); + CseException oException = new CseException("500", "InternalServerError"); + Assertions.assertEquals("500", oException.getCode()); + Assertions.assertEquals("ServiceDefinitionException Code:500, Message:InternalServerError", + oException.toString()); - oExeception = new CseException("503", "OwnException", new Throwable()); - Assert.assertEquals("503", oExeception.getCode()); + oException = new CseException("503", "OwnException", new Throwable()); + Assertions.assertEquals("503", oException.getCode()); } @Test public void testExceptionUtils() { - CseException oExeception = ExceptionUtils + CseException oException = ExceptionUtils .createCseException("servicecomb.handler.ref.not.exist", new String("test")); - Assert.assertEquals("servicecomb.handler.ref.not.exist", oExeception.getCode()); + Assertions.assertEquals("servicecomb.handler.ref.not.exist", oException.getCode()); - oExeception = + oException = ExceptionUtils.createCseException("servicecomb.handler.ref.not.exist", new Throwable(), new String("test")); - Assert.assertEquals("servicecomb.handler.ref.not.exist", oExeception.getCode()); + Assertions.assertEquals("servicecomb.handler.ref.not.exist", oException.getCode()); - oExeception = ExceptionUtils.producerOperationNotExist("servicecomb.error", "unit-testing"); - Assert.assertEquals("servicecomb.producer.operation.not.exist", oExeception.getCode()); + oException = ExceptionUtils.producerOperationNotExist("servicecomb.error", "unit-testing"); + Assertions.assertEquals("servicecomb.producer.operation.not.exist", oException.getCode()); - oExeception = ExceptionUtils.handlerRefNotExist("servicecomb.double.error"); - Assert.assertEquals("servicecomb.handler.ref.not.exist", oExeception.getCode()); + oException = ExceptionUtils.handlerRefNotExist("servicecomb.double.error"); + Assertions.assertEquals("servicecomb.handler.ref.not.exist", oException.getCode()); - oExeception = ExceptionUtils.lbAddressNotFound("microServiceName", "my rule my world", "transportChannel"); - Assert.assertEquals("servicecomb.lb.no.available.address", oExeception.getCode()); + oException = ExceptionUtils.lbAddressNotFound("microServiceName", "my rule my world", "transportChannel"); + Assertions.assertEquals("servicecomb.lb.no.available.address", oException.getCode()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/TestHandler.java b/core/src/test/java/org/apache/servicecomb/core/TestHandler.java deleted file mode 100644 index c9b67f45078..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestHandler.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.core; - -public class TestHandler { -// -// @Test -// public void testAbstractHandlerManager() throws Exception { -// HandlerConfigUtils.init(); -// Assert.assertNotEquals(null, ConsumerHandlerManager.INSTANCE.getOrCreate("test")); -// } -} 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 6bda0e039df..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,12 +17,10 @@ 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; import org.apache.servicecomb.core.event.InvocationBaseEvent; -import org.apache.servicecomb.core.event.InvocationBusinessMethodFinishEvent; import org.apache.servicecomb.core.event.InvocationBusinessMethodStartEvent; import org.apache.servicecomb.core.event.InvocationFinishEvent; import org.apache.servicecomb.core.event.InvocationStartEvent; @@ -34,11 +32,12 @@ import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.swagger.invocation.Response; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.AfterClass; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; @@ -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 @@ -86,8 +81,6 @@ public static void classTeardown() { @Test public void onStart() { - mockNonaTime(); - Holder result = new Holder<>(); Object subscriber = new Object() { @Subscribe @@ -97,25 +90,13 @@ public void onStart(InvocationStartEvent event) { }; EventManager.register(subscriber); - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); - invocation.onStart(nanoTime); - - Assert.assertSame(invocation, result.value); - Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStart()); + Invocation invocation = new Invocation(endpoint, operationMeta, null); + invocation.onStart(); + Assertions.assertSame(invocation, result.value); EventManager.unregister(subscriber); } - @Test - public void onStartExecute() { - mockNonaTime(); - - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); - invocation.onExecuteStart(); - - Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartExecution()); - } - @Test public void onFinish() { mockNonaTime(); @@ -129,54 +110,53 @@ public void onStart(InvocationFinishEvent event) { }; EventManager.register(subscriber); - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); - Assert.assertFalse(invocation.isFinished()); + Invocation invocation = new Invocation(endpoint, operationMeta, null); + Assertions.assertFalse(invocation.isFinished()); Response response = Response.succResp(null); invocation.onFinish(response); - Assert.assertEquals(nanoTime, result.value.getNanoCurrent()); - Assert.assertSame(invocation, result.value.getInvocation()); - Assert.assertSame(response, result.value.getResponse()); - Assert.assertTrue(invocation.isFinished()); + Assertions.assertSame(invocation, result.value.getInvocation()); + Assertions.assertSame(response, result.value.getResponse()); + Assertions.assertTrue(invocation.isFinished()); // should not post event again InvocationFinishEvent oldEvent = result.value; invocation.onFinish(null); - Assert.assertSame(oldEvent, result.value); + Assertions.assertSame(oldEvent, result.value); EventManager.unregister(subscriber); } @Test public void isConsumer_yes() { - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); - Assert.assertFalse(invocation.isConsumer()); + 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); - Assert.assertTrue(invocation.isConsumer()); + 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); - Assert.assertSame(invocation.getHandlerContext(), invocation.getLocalContext()); - Assert.assertEquals(1, (int) invocation.getLocalContext("k")); + Assertions.assertSame(invocation.getHandlerContext(), invocation.getLocalContext()); + Assertions.assertEquals(1, (int) invocation.getLocalContext("k")); } @Test public void traceId_fromContext(@Mocked ReferenceConfig referenceConfig) { - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments); - invocation.addContext(Const.TRACE_ID_NAME, "abc"); + Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null); + invocation.addContext(CoreConst.TRACE_ID_NAME, "abc"); - invocation.onStart(0); + invocation.onStart(); - Assert.assertEquals("abc", invocation.getTraceId()); - Assert.assertEquals("abc", invocation.getTraceId(Const.TRACE_ID_NAME)); + Assertions.assertEquals("abc", invocation.getTraceId()); + Assertions.assertEquals("abc", invocation.getTraceId(CoreConst.TRACE_ID_NAME)); } @Test @@ -188,32 +168,33 @@ 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(0); + invocation.onStart(); - Assert.assertEquals("abc", invocation.getTraceId()); - Assert.assertEquals("abc", invocation.getTraceId(Const.TRACE_ID_NAME)); + Assertions.assertEquals("abc", invocation.getTraceId()); + Assertions.assertEquals("abc", invocation.getTraceId(CoreConst.TRACE_ID_NAME)); } @Test public void traceId_fromRequest(@Mocked Endpoint endpoint, @Mocked HttpServletRequestEx requestEx) { new Expectations() { { - requestEx.getHeader(Const.TRACE_ID_NAME); + requestEx.getHeader(CoreConst.TRACE_ID_NAME); result = "abc"; } }; - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); + Invocation invocation = new Invocation(endpoint, operationMeta, null); - invocation.onStart(requestEx, 0); + invocation.onStart(requestEx); - Assert.assertEquals("abc", invocation.getTraceId()); - Assert.assertEquals("abc", invocation.getTraceId(Const.TRACE_ID_NAME)); + Assertions.assertEquals("abc", invocation.getTraceId()); + Assertions.assertEquals("abc", invocation.getTraceId(CoreConst.TRACE_ID_NAME)); } @Test public void traceId_producerCreateTraceId(@Mocked Endpoint endpoint, @Mocked HttpServletRequestEx requestEx) { + TraceIdGenerator generator = SPIServiceUtils.getTargetService(TraceIdGenerator.class, BraveTraceIdGenerator.class); new Expectations(generator) { { @@ -221,12 +202,12 @@ 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, 0); + invocation.onStart(requestEx); - Assert.assertEquals("abc", invocation.getTraceId()); - Assert.assertEquals("abc", invocation.getTraceId(Const.TRACE_ID_NAME)); + Assertions.assertEquals("abc", invocation.getTraceId()); + Assertions.assertEquals("abc", invocation.getTraceId(CoreConst.TRACE_ID_NAME)); } @Test @@ -251,13 +232,13 @@ public void traceIdGeneratorInit(@Mocked TraceIdGenerator gen1, @Mocked TraceIdG } }; - Assert.assertThat(Invocation.loadTraceIdGenerators(), Matchers.contains(gen1, gen3)); + MatcherAssert.assertThat(Invocation.loadTraceIdGenerators(), Matchers.containsInAnyOrder(gen1, gen3)); } InvocationBaseEvent invocationBaseEvent; @Test - public void onBusinessMethodStart() { + public void test_business_execute_time_correct() { Object listener = new Object() { @Subscribe public void onBusinessMethodStart(InvocationBusinessMethodStartEvent event) { @@ -265,66 +246,29 @@ 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); - Assert.assertSame(invocation, invocationBaseEvent.getInvocation()); - Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartBusinessMethod()); - } - - @Test - public void onBusinessMethodFinish() { - Object listener = new Object() { - @Subscribe - public void onBusinessMethodStart(InvocationBusinessMethodFinishEvent event) { - invocationBaseEvent = event; - } - }; - EventManager.getEventBus().register(listener); - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); - invocation.onBusinessMethodFinish(); - EventManager.getEventBus().unregister(listener); - - Assert.assertSame(invocation, invocationBaseEvent.getInvocation()); - } - - @Test - public void onBusinessFinish() { - Invocation invocation = new Invocation(endpoint, operationMeta, arguments); - mockNonaTime(); + Assertions.assertSame(invocation, invocationBaseEvent.getInvocation()); + nanoTime++; invocation.onBusinessFinish(); - - Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getFinishBusiness()); + Assertions.assertEquals(1, invocation.getInvocationStageTrace().calcBusinessExecute()); } @Test public void marker(@Mocked ReferenceConfig referenceConfig) { Invocation.INVOCATION_ID.set(0); - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments); - invocation.addContext(Const.TRACE_ID_NAME, "abc"); - invocation.onStart(0); - Assert.assertEquals("abc-0", invocation.getTraceIdLogger().getName()); - - invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments); - invocation.addContext(Const.TRACE_ID_NAME, "abc"); - invocation.onStart(0); - Assert.assertEquals("abc-1", invocation.getTraceIdLogger().getName()); - } - - @Test - public void isThirdPartyInvocation(@Mocked ReferenceConfig referenceConfig) { - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, arguments); - Assert.assertFalse(invocation.isThirdPartyInvocation()); + Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, null); + invocation.addContext(CoreConst.TRACE_ID_NAME, "abc"); + invocation.onStart(); + Assertions.assertEquals("abc", invocation.getTraceIdLogger().getName()); - new Expectations() { - { - referenceConfig.is3rdPartyService(); - result = true; - } - }; - Assert.assertTrue(invocation.isThirdPartyInvocation()); + 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/TestInvocationFactory.java b/core/src/test/java/org/apache/servicecomb/core/TestInvocationFactory.java deleted file mode 100644 index 0f4cf769d8e..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestInvocationFactory.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.core; - -public class TestInvocationFactory { -// @BeforeClass -// public static void setUp() { -// ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); -// serviceRegistry.init(); -// RegistryUtils.setServiceRegistry(serviceRegistry); -// SCBEngine.getInstance().setStatus(SCBStatus.UP); -// } -// -// @Test -// public void testInvocationFactoryforConsumer(@Injectable ReferenceConfig referenceConfig, -// @Injectable OperationMeta operationMeta) { -// Invocation invocation = -// InvocationFactory.forConsumer(referenceConfig, operationMeta, new String[] {"a", "b"}); -// Assert.assertEquals("perfClient", invocation.getContext(Const.SRC_MICROSERVICE)); -// } -// -// @Test -// public void testInvocationFactoryforConsumer(@Injectable ReferenceConfig referenceConfig, -// @Injectable SchemaMeta schemaMeta) { -// Invocation invocation = -// InvocationFactory.forConsumer(referenceConfig, schemaMeta, "test", new String[] {"a", "b"}); -// Assert.assertEquals("perfClient", invocation.getContext(Const.SRC_MICROSERVICE)); -// } -// -// @Test -// public void testInvocationFactoryforConsumer(@Injectable ReferenceConfig referenceConfig) { -// Invocation invocation = -// InvocationFactory.forConsumer(referenceConfig, "test", new String[] {"a", "b"}); -// Assert.assertEquals("perfClient", invocation.getContext(Const.SRC_MICROSERVICE)); -// } -// -// @Test -// public void testInvocationFactoryforProvider(@Injectable Endpoint endpoint, -// @Injectable OperationMeta operationMeta) { -// Invocation invocation = -// InvocationFactory.forProvider(endpoint, operationMeta, new String[] {"a", "b"}); -// Assert.assertEquals(invocation.getEndpoint(), endpoint); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/TestSCBApplicationListener.java b/core/src/test/java/org/apache/servicecomb/core/TestSCBApplicationListener.java new file mode 100644 index 00000000000..99690c3c310 --- /dev/null +++ b/core/src/test/java/org/apache/servicecomb/core/TestSCBApplicationListener.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.core; + +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; + +import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.core.env.Environment; + +public class TestSCBApplicationListener { + @BeforeEach + public void before() { + } + + @AfterAll + public static void classTeardown() { + } + + @Test + public void onApplicationEvent_close() { + ContextClosedEvent contextClosedEvent = Mockito.mock(ContextClosedEvent.class); + Environment environment = Mockito.mock(Environment.class); + SCBEngine scbEngine = SCBBootstrap.createSCBEngineForTest(environment); + scbEngine.setEnvironment(environment); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + scbEngine.setStatus(SCBStatus.UP); + + SCBApplicationListener listener = new SCBApplicationListener(scbEngine); + listener.onApplicationEvent(contextClosedEvent); + + Assertions.assertEquals(SCBStatus.DOWN, scbEngine.getStatus()); + + scbEngine.destroy(); + } +} diff --git a/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java b/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java deleted file mode 100644 index b1e965b19df..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/TestSCBEngine.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.core; - -public class TestSCBEngine { -// @Rule -// public ExpectedException expectedException = ExpectedException.none(); -// -// @Test -// public void test(@Injectable ProducerProviderManager producerProviderManager, -// @Injectable ConsumerProviderManager consumerProviderManager, -// @Injectable TransportManager transportManager, -// @Injectable AppManager appManager) { -// new Expectations(RegistryUtils.class) { -// { -// RegistryUtils.getServiceRegistry().getAppManager(); -// RegistryUtils.getInstanceCacheManager(); -// RegistryUtils.run(); -// RegistryUtils.destroy(); -// } -// }; -// AtomicBoolean configDestroy = new AtomicBoolean(); -// new MockUp() { -// @Mock -// void destroyConfigCenterConfigurationSource() { -// configDestroy.set(true); -// } -// }; -// -// SchemaListenerManager schemaListenerManager = Mockito.mock(SchemaListenerManager.class); -// -// VertxUtils.getOrCreateVertxByName("transport", null); -// -// SCBEngine engine = new SCBEngine(); -// engine.setBootListenerList(new ArrayList<>()); -// engine.setConsumerProviderManager(consumerProviderManager); -// engine.setProducerProviderManager(producerProviderManager); -// engine.setTransportManager(transportManager); -// engine.setSchemaListenerManager(schemaListenerManager); -// -// ArchaiusUtils.setProperty(SCBEngine.CFG_KEY_WAIT_UP_TIMEOUT, 0); -// engine.init(); -// ArchaiusUtils.updateProperty(SCBEngine.CFG_KEY_WAIT_UP_TIMEOUT, null); -// -// Assert.assertEquals(SCBStatus.STARTING, engine.getStatus()); -// -// engine.destroy(); -// -// Assert.assertEquals(SCBStatus.DOWN, engine.getStatus()); -// Assert.assertTrue(configDestroy.get()); -// } -// -// @Test -// public void createReferenceConfigForInvoke_up(@Mocked ConsumerProviderManager consumerProviderManager) { -// SCBEngine engine = new SCBEngine(); -// engine.setStatus(SCBStatus.UP); -// engine.setConsumerProviderManager(consumerProviderManager); -// -// ReferenceConfig referenceConfig = engine.createReferenceConfigForInvoke(null, null, null); -// Assert.assertTrue(ReferenceConfig.class.isInstance(referenceConfig)); -// } -// -// @Test -// public void createReferenceConfigForInvoke_down(@Mocked ConsumerProviderManager consumerProviderManager) { -// SCBEngine engine = new SCBEngine(); -// engine.setStatus(SCBStatus.DOWN); -// engine.setConsumerProviderManager(consumerProviderManager); -// -// expectedException.expect(InvocationException.class); -// expectedException.expectMessage( -// Matchers -// .is("InvocationException: code=503;msg=CommonExceptionData [message=The request is rejected. Cannot process the request due to STATUS = DOWN]")); -// engine.createReferenceConfigForInvoke(null, null, null); -// } -// -// @Test -// public void getReferenceConfigForInvoke_up(@Mocked ConsumerProviderManager consumerProviderManager) { -// SCBEngine engine = new SCBEngine(); -// engine.setStatus(SCBStatus.UP); -// engine.setConsumerProviderManager(consumerProviderManager); -// -// ReferenceConfig referenceConfig = engine.getReferenceConfigForInvoke(null); -// Assert.assertTrue(ReferenceConfig.class.isInstance(referenceConfig)); -// } -// -// @Test -// public void getReferenceConfigForInvoke_down(@Mocked ConsumerProviderManager consumerProviderManager) { -// SCBEngine engine = new SCBEngine(); -// engine.setStatus(SCBStatus.DOWN); -// engine.setConsumerProviderManager(consumerProviderManager); -// -// expectedException.expect(InvocationException.class); -// expectedException.expectMessage( -// Matchers -// .is("InvocationException: code=503;msg=CommonExceptionData [message=The request is rejected. Cannot process the request due to STATUS = DOWN]")); -// engine.getReferenceConfigForInvoke(null); -// } -// -// @Test -// public void setBootListenerList(@Mocked BootListener beanListener, @Mocked BootListener spiListener) { -// new Expectations(SPIServiceUtils.class) { -// { -// beanListener.getOrder(); -// result = 1; -// spiListener.getOrder(); -// result = 0; -// SPIServiceUtils.getOrLoadSortedService(BootListener.class); -// result = Arrays.asList(spiListener); -// } -// }; -// -// SCBEngine engine = new SCBEngine(); -// engine.setBootListenerList(Arrays.asList(beanListener)); -// -// Assert.assertThat(engine.getBootListeners(), Matchers.contains(spiListener, beanListener)); -// } -// -// @Test -// public void bootEvent_refEngine() { -// Holder eventEngine = new Holder<>(); -// SCBEngine engine = new SCBEngine(); -// engine.setBootListenerList(Arrays.asList(event -> eventEngine.value = event.getScbEngine())); -// engine.triggerEvent(EventType.AFTER_REGISTRY); -// -// Assert.assertNotNull(eventEngine.value); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/TestTransport.java b/core/src/test/java/org/apache/servicecomb/core/TestTransport.java index 065e411e508..4ab2f99ff80 100644 --- a/core/src/test/java/org/apache/servicecomb/core/TestTransport.java +++ b/core/src/test/java/org/apache/servicecomb/core/TestTransport.java @@ -17,36 +17,34 @@ package org.apache.servicecomb.core; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.core.env.Environment; public class TestTransport { - @BeforeClass + @BeforeAll public static void classSetup() { } - @AfterClass + @AfterAll public static void classTeardown() { - SCBEngine.getInstance().destroy(); } @Test public void testEndpoint() throws Exception { Endpoint oEndpoint = new Endpoint(new Transport() { - @Override - public void send(Invocation invocation, AsyncResponse asyncResp) { - } - @Override public Object parseAddress(String address) { return "127.0.0.1"; } + @Override + public void setEnvironment(Environment environment) { + + } @Override public boolean init() { return true; @@ -68,9 +66,9 @@ public Endpoint getPublishEndpoint() { } }, "rest://127.0.0.1:8080"); oEndpoint.getTransport().init(); - Assert.assertEquals("rest://127.0.0.1:8080", oEndpoint.getEndpoint()); - Assert.assertEquals("127.0.0.1", oEndpoint.getAddress()); - Assert.assertEquals("test", oEndpoint.getTransport().getName()); - Assert.assertEquals("rest://127.0.0.1:8080", oEndpoint.getEndpoint()); + Assertions.assertEquals("rest://127.0.0.1:8080", oEndpoint.getEndpoint()); + Assertions.assertEquals("127.0.0.1", oEndpoint.getAddress()); + Assertions.assertEquals("test", oEndpoint.getTransport().getName()); + Assertions.assertEquals("rest://127.0.0.1:8080", oEndpoint.getEndpoint()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/Utils.java b/core/src/test/java/org/apache/servicecomb/core/Utils.java deleted file mode 100644 index 998a8ca4be8..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/Utils.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.core; - -import java.lang.reflect.Method; - -import org.springframework.util.ReflectionUtils; - -import com.netflix.config.DynamicProperty; - -public class Utils { - private static Method updatePropertyMethod = - ReflectionUtils.findMethod(DynamicProperty.class, "updateProperty", String.class, Object.class); - - static { - updatePropertyMethod.setAccessible(true); - } - - public static void updateProperty(String key, Object value) { - ReflectionUtils.invokeMethod(updatePropertyMethod, null, key, value); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/consumer/TestReactiveResponseExecutor.java b/core/src/test/java/org/apache/servicecomb/core/consumer/TestReactiveResponseExecutor.java index 48269827b7d..0e2b33b9012 100644 --- a/core/src/test/java/org/apache/servicecomb/core/consumer/TestReactiveResponseExecutor.java +++ b/core/src/test/java/org/apache/servicecomb/core/consumer/TestReactiveResponseExecutor.java @@ -18,8 +18,8 @@ package org.apache.servicecomb.core.consumer; import org.apache.servicecomb.core.provider.consumer.ReactiveResponseExecutor; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class TestReactiveResponseExecutor { @@ -33,6 +33,6 @@ public void testReactiveResponseExecutor() { } catch (Exception e) { validAssert = false; } - Assert.assertTrue(validAssert); + Assertions.assertTrue(validAssert); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/consumer/TestSyncResponseExecutor.java b/core/src/test/java/org/apache/servicecomb/core/consumer/TestSyncResponseExecutor.java index 438e959c054..750203072b7 100644 --- a/core/src/test/java/org/apache/servicecomb/core/consumer/TestSyncResponseExecutor.java +++ b/core/src/test/java/org/apache/servicecomb/core/consumer/TestSyncResponseExecutor.java @@ -20,8 +20,8 @@ import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.provider.consumer.SyncResponseExecutor; import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class TestSyncResponseExecutor { @@ -36,9 +36,9 @@ public void testSyncResponseExecutor() { try { Response responseValue = executor.waitResponse(invocation); - Assert.assertNotNull(responseValue); + Assertions.assertNotNull(responseValue); } catch (Exception e) { - Assert.assertNotNull(e); + Assertions.assertNotNull(e); } } } diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java b/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java index dc8076befe4..ad664261980 100644 --- a/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java @@ -21,7 +21,7 @@ import java.util.concurrent.TimeUnit; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -37,7 +37,7 @@ void should_get_rest_value() { long nano = TimeUnit.MILLISECONDS.toNanos(2); assertThat(config.getNanoRestRequestWaitInPoolTimeout()).isEqualTo(nano); - assertThat(config.getNanoRequestWaitInPoolTimeout(Const.RESTFUL)).isEqualTo(nano); + assertThat(config.getNanoRequestWaitInPoolTimeout(CoreConst.RESTFUL)).isEqualTo(nano); } @Test @@ -47,7 +47,7 @@ void should_get_highway_value() { long nano = TimeUnit.MILLISECONDS.toNanos(2); assertThat(config.getNanoHighwayRequestWaitInPoolTimeout()).isEqualTo(nano); - assertThat(config.getNanoRequestWaitInPoolTimeout(Const.HIGHWAY)).isEqualTo(nano); + assertThat(config.getNanoRequestWaitInPoolTimeout(CoreConst.HIGHWAY)).isEqualTo(nano); } @Test @@ -68,4 +68,4 @@ void should_get_invocation_timeout_value() { assertThat(config.getMsInvocationTimeout()).isEqualTo(1); } } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java b/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java deleted file mode 100644 index 145d057513d..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/StaticMicroserviceVersionMetaTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.core.definition; - -public class StaticMicroserviceVersionMetaTest { -// -// private static final String APP_ID_FROM_REGISTRY_UTIL = "appIdFromRegistryUtil"; -// -// @BeforeClass -// public static void beforeClass() { -// new MockUp() { -// @Mock -// String getAppId() { -// return APP_ID_FROM_REGISTRY_UTIL; -// } -// }; -// } -// -// @Test -// public void testConstruct() { -// StaticMicroservice staticMicroservice = new StaticMicroservice(); -// String appId = "testAppId"; -// String serviceName = "testServiceName"; -// String version = "1.2.1"; -// staticMicroservice.setAppId(appId); -// staticMicroservice.setServiceName(serviceName); -// staticMicroservice.setVersion(version); -// -// Holder schemaLoaded = new Holder<>(false); -// SCBEngine.getInstance().setStaticSchemaFactory(new MockUp() { -// @Mock -// void loadSchema(MicroserviceMeta microserviceMeta, StaticMicroservice microservice) { -// Assert.assertSame(APP_ID_FROM_REGISTRY_UTIL, microserviceMeta.getAppId()); -// Assert.assertSame(serviceName, microserviceMeta.getName()); -// Assert.assertSame(serviceName, microserviceMeta.getShortName()); -// Assert.assertSame(staticMicroservice, microservice); -// schemaLoaded.value = true; -// } -// }.getMockInstance()); -// Holder listenerNotified = new Holder<>(false); -// CseContext.getInstance().setSchemaListenerManager(new MockUp() { -// @Mock -// void notifySchemaListener(MicroserviceMeta... microserviceMetas) { -// Assert.assertEquals(1, microserviceMetas.length); -// MicroserviceMeta microserviceMeta = microserviceMetas[0]; -// Assert.assertEquals(serviceName, microserviceMeta.getShortName()); -// listenerNotified.value = true; -// } -// }.getMockInstance()); -// -// StaticMicroserviceVersionMeta staticMicroserviceVersionMeta = new StaticMicroserviceVersionMeta(staticMicroservice); -// -// Assert.assertTrue(schemaLoaded.value); -// Assert.assertTrue(listenerNotified.value); -// Assert.assertSame(staticMicroservice, staticMicroserviceVersionMeta.getMicroservice()); -// Assert.assertEquals(serviceName, staticMicroserviceVersionMeta.getMicroserviceMeta().getName()); -// } -} \ No newline at end of file diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMeta.java b/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMeta.java deleted file mode 100644 index 74fc0e9bb4e..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMeta.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * 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.core.definition; - -public class TestMicroserviceMeta { -// MicroserviceMeta microserviceMeta = new MicroserviceMeta("app:microservice"); -// -// @Test -// public void isConsumer() { -// Assert.assertTrue(microserviceMeta.isConsumer()); -// } -// -// @Test -// public void testGetSchemaMetas() { -// Collection schemaMetas = microserviceMeta.getSchemaMetas(); -// Assert.assertNotNull(schemaMetas); -// } -// -// @Test -// public void testGetExtData() { -// Object data = new Object(); -// microserviceMeta.putExtData("pruthi", data); -// Object response = microserviceMeta.getExtData("pruthi"); -// Assert.assertNotNull(response); -// } -// -// @Test -// public void testIntf(@Mocked SchemaMeta sm1, @Mocked SchemaMeta sm2) { -// Class intf = Object.class; -// new Expectations() { -// { -// sm1.getSchemaId(); -// result = "a"; -// sm2.getSchemaId(); -// result = "b"; -// sm1.getSwaggerIntf(); -// result = intf; -// sm2.getSwaggerIntf(); -// result = intf; -// } -// }; -// -// try { -// microserviceMeta.ensureFindSchemaMeta(intf); -// Assert.assertEquals(1, 2); -// } catch (Throwable e) { -// Assert.assertEquals( -// "No schema interface is java.lang.Object.", -// e.getMessage()); -// } -// microserviceMeta.regSchemaMeta(sm1); -// Assert.assertEquals(sm1, microserviceMeta.findSchemaMeta(intf)); -// Assert.assertEquals(sm1, microserviceMeta.ensureFindSchemaMeta(intf)); -// -// microserviceMeta.regSchemaMeta(sm2); -// Assert.assertEquals(sm1, microserviceMeta.ensureFindSchemaMeta("a")); -// Assert.assertEquals(sm2, microserviceMeta.ensureFindSchemaMeta("b")); -// try { -// microserviceMeta.findSchemaMeta(intf); -// Assert.assertEquals(1, 2); -// } catch (Throwable e) { -// Assert.assertEquals( -// "More than one schema interface is java.lang.Object, please use schemaId to choose a schema.", -// e.getMessage()); -// } -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMetaManager.java b/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMetaManager.java index 55ea9b76b57..8d89a10a285 100644 --- a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMetaManager.java +++ b/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceMetaManager.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.core.definition; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class TestMicroserviceMetaManager { @@ -28,6 +28,6 @@ public void testEnsureFindSchemaMeta() { SchemaMeta meta = Mockito.mock(SchemaMeta.class); MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); Mockito.when(microserviceMeta.ensureFindSchemaMeta("yhfghj")).thenReturn(meta); - Assert.assertEquals(meta, microserviceMeta.ensureFindSchemaMeta("yhfghj")); + Assertions.assertEquals(meta, microserviceMeta.ensureFindSchemaMeta("yhfghj")); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceVersionMeta.java b/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceVersionMeta.java deleted file mode 100644 index b31862b4ff2..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceVersionMeta.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.core.definition; - -public class TestMicroserviceVersionMeta { -// @AfterClass -// public static void teardown() { -// CseContext.getInstance().setConsumerSchemaFactory(null); -// CseContext.getInstance().setSchemaListenerManager(null); -// } -// -// @Test -// public void construct(@Mocked ServiceRegistry serviceRegistry) { -// String microserviceName = "app:ms"; -// String microserviceId = "id"; -// Microservice microservice = new Microservice(); -// microservice.setVersion("1.0.0"); -// -// new Expectations(RegistryUtils.class) { -// { -// RegistryUtils.getServiceRegistry(); -// result = serviceRegistry; -// serviceRegistry.getAggregatedRemoteMicroservice(microserviceId); -// result = microservice; -// } -// }; -// -// List logs = new ArrayList<>(); -// CseContext.getInstance().setConsumerSchemaFactory(new MockUp() { -// @Mock -// void createConsumerSchema(MicroserviceMeta microserviceMeta, Microservice microservice) { -// logs.add("createConsumerSchema"); -// } -// }.getMockInstance()); -// CseContext.getInstance().setSchemaListenerManager(new MockUp() { -// @Mock -// void notifySchemaListener(MicroserviceMeta... microserviceMetas) { -// logs.add("notifySchemaListener"); -// } -// }.getMockInstance()); -// -// MicroserviceVersionMeta microserviceVersionMeta = new MicroserviceVersionMeta(microserviceName, microserviceId); -// -// Assert.assertThat(logs, Matchers.contains("createConsumerSchema", "notifySchemaListener")); -// Assert.assertEquals(microserviceName, microserviceVersionMeta.getMicroserviceMeta().getName()); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceVersionMetaFactory.java b/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceVersionMetaFactory.java deleted file mode 100644 index 61111924d5b..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/TestMicroserviceVersionMetaFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.core.definition; - -public class TestMicroserviceVersionMetaFactory { -// @AfterClass -// public static void teardown() { -// CseContext.getInstance().setConsumerSchemaFactory(null); -// CseContext.getInstance().setSchemaListenerManager(null); -// } -// -// @Test -// public void create(@Mocked ConsumerSchemaFactory consumerSchemaFactory, -// @Mocked SchemaListenerManager schemaListenerManager, @Mocked ServiceRegistry serviceRegistry) { -// String microserviceName = "app:ms"; -// String microserviceId = "id"; -// Microservice microservice = new Microservice(); -// microservice.setVersion("1.0.0"); -// -// new Expectations(RegistryUtils.class) { -// { -// RegistryUtils.getServiceRegistry(); -// result = serviceRegistry; -// serviceRegistry.getAggregatedRemoteMicroservice(microserviceId); -// result = microservice; -// } -// }; -// CseContext.getInstance().setConsumerSchemaFactory(consumerSchemaFactory); -// CseContext.getInstance().setSchemaListenerManager(schemaListenerManager); -// -// MicroserviceVersionMetaFactory factory = new MicroserviceVersionMetaFactory(); -// MicroserviceVersion microserviceVersion = factory.create(microserviceName, microserviceId); -// Assert.assertThat(microserviceVersion, Matchers.instanceOf(MicroserviceVersionMeta.class)); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/TestOperationMeta.java b/core/src/test/java/org/apache/servicecomb/core/definition/TestOperationMeta.java deleted file mode 100644 index f768d18150a..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/TestOperationMeta.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * 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.core.definition; - -public class TestOperationMeta { -// class Impl { -// @ApiResponse( -// code = 300, -// response = String.class, -// message = "", -// responseHeaders = {@ResponseHeader(name = "h3", response = int.class)}) -// @ResponseHeaders({@ResponseHeader(name = "h1", response = int.class), -// @ResponseHeader(name = "h2", response = String.class, responseContainer = "List")}) -// public int test(int x) { -// return 100; -// } -// } -// -// @BeforeClass -// public static void setup() { -// ArchaiusUtils.resetConfig(); -// } -// -// @AfterClass -// public static void teardown() { -// ArchaiusUtils.resetConfig(); -// } -// -// @Test -// public void testOperationMeta() { -// UnitTestMeta meta = new UnitTestMeta(); -// SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(Impl.class); -// OperationMeta operationMeta = schemaMeta.findOperation("test"); -// -// Assert.assertEquals("POST", operationMeta.getHttpMethod()); -// Assert.assertEquals("/test", operationMeta.getOperationPath()); -// Assert.assertEquals(schemaMeta, operationMeta.getSchemaMeta()); -// Assert.assertEquals(Impl.class.getName() + ".test", -// operationMeta.getSchemaQualifiedName()); -// Assert.assertEquals("perfClient." + Impl.class.getName() + ".test", -// operationMeta.getMicroserviceQualifiedName()); -// Assert.assertEquals("perfClient", operationMeta.getMicroserviceName()); -// Assert.assertEquals("test", operationMeta.getOperationId()); -// Assert.assertEquals("x", operationMeta.getParamName(0)); -// -// operationMeta.putExtData("ext", 1); -// Assert.assertEquals(1, (int) operationMeta.getExtData("ext")); -// -// ResponseMeta responseMeta = operationMeta.findResponseType(200); -// Assert.assertEquals("Ljava/lang/Integer;", responseMeta.getJavaType().getGenericSignature()); -// Assert.assertEquals("Ljava/lang/Integer;", responseMeta.getHeaders().get("h1").getGenericSignature()); -// Assert.assertEquals("Ljava/util/List;", -// responseMeta.getHeaders().get("h2").getGenericSignature()); -// Assert.assertEquals(null, responseMeta.getHeaders().get("h3")); -// -// responseMeta = operationMeta.findResponseType(300); -// Assert.assertEquals("Ljava/lang/String;", responseMeta.getJavaType().getGenericSignature()); -// Assert.assertEquals("Ljava/lang/Integer;", responseMeta.getHeaders().get("h1").getGenericSignature()); -// Assert.assertEquals("Ljava/util/List;", -// responseMeta.getHeaders().get("h2").getGenericSignature()); -// Assert.assertEquals("Ljava/lang/Integer;", responseMeta.getHeaders().get("h3").getGenericSignature()); -// } -// -// @Test -// public void opConfig() { -// UnitTestMeta meta = new UnitTestMeta(); -// SchemaMeta schemaMeta = meta.getOrCreateSchemaMeta(Impl.class); -// OperationMeta operationMeta = schemaMeta.findOperation("test"); -// -// OperationConfig config = operationMeta.getConfig(); -// -// // slow invocation -// slowInvocation(config); -// -// // consumer request timeout -// consumerRequestTimeout(config); -// -// // highway wait in thread pool timeout -// highwayWaitInPool(config); -// -// // rest wait in thread pool timeout -// restWaitInPool(config); -// } -// -// private void restWaitInPool(OperationConfig config) { -// ArchaiusUtils.updateProperty("servicecomb.Provider.requestWaitInPoolTimeout", null); -// ArchaiusUtils.updateProperty("servicecomb.Provider.requestWaitInPoolTimeout.perfClient", null); -// ArchaiusUtils.updateProperty( -// "servicecomb.Provider.requestWaitInPoolTimeout.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl", -// null); -// ArchaiusUtils.updateProperty( -// "servicecomb.Provider.requestWaitInPoolTimeout.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl.test", -// null); -// -// Assert.assertEquals(30000, config.getMsRestRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(30000), config.getNanoRestRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty("servicecomb.Provider.requestWaitInPoolTimeout", 1); -// Assert.assertEquals(1, config.getMsRestRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(1), config.getNanoRestRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty("servicecomb.Provider.requestWaitInPoolTimeout.perfClient", 2); -// Assert.assertEquals(2, config.getMsRestRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(2), config.getNanoRestRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty( -// "servicecomb.Provider.requestWaitInPoolTimeout.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl", -// 3); -// Assert.assertEquals(3, config.getMsRestRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(3), config.getNanoRestRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty( -// "servicecomb.Provider.requestWaitInPoolTimeout.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl.test", -// 4); -// Assert.assertEquals(4, config.getMsRestRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(4), config.getNanoRestRequestWaitInPoolTimeout()); -// } -// -// private void highwayWaitInPool(OperationConfig config) { -// Assert.assertEquals(30000, config.getMsHighwayRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(30000), config.getNanoHighwayRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty("servicecomb.Provider.requestWaitInPoolTimeout", 1); -// Assert.assertEquals(1, config.getMsHighwayRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(1), config.getNanoHighwayRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty("servicecomb.Provider.requestWaitInPoolTimeout.perfClient", 2); -// Assert.assertEquals(2, config.getMsHighwayRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(2), config.getNanoHighwayRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty( -// "servicecomb.Provider.requestWaitInPoolTimeout.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl", -// 3); -// Assert.assertEquals(3, config.getMsHighwayRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(3), config.getNanoHighwayRequestWaitInPoolTimeout()); -// -// ArchaiusUtils.setProperty( -// "servicecomb.Provider.requestWaitInPoolTimeout.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl.test", -// 4); -// Assert.assertEquals(4, config.getMsHighwayRequestWaitInPoolTimeout()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(4), config.getNanoHighwayRequestWaitInPoolTimeout()); -// } -// -// private void consumerRequestTimeout(OperationConfig config) { -// Assert.assertEquals(30000, config.getMsRequestTimeout()); -// -// ArchaiusUtils.setProperty("servicecomb.request.perfClient.timeout", 2); -// Assert.assertEquals(2, config.getMsRequestTimeout()); -// ArchaiusUtils.setProperty( -// "servicecomb.request.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl.timeout", 3); -// Assert.assertEquals(3, config.getMsRequestTimeout()); -// ArchaiusUtils.setProperty( -// "servicecomb.request.perfClient.org.apache.servicecomb.core.definition.TestOperationMeta$Impl.test.timeout", 4); -// Assert.assertEquals(4, config.getMsRequestTimeout()); -// } -// -// private void slowInvocation(OperationConfig config) { -// Assert.assertFalse(config.isSlowInvocationEnabled()); -// Assert.assertEquals(1000, config.getMsSlowInvocation()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(1000), config.getNanoSlowInvocation()); -// -// ArchaiusUtils.setProperty("servicecomb.Consumer.invocation.slow.enabled.perfClient", true); -// ArchaiusUtils.setProperty("servicecomb.Consumer.invocation.slow.msTime.perfClient", 2000); -// Assert.assertTrue(config.isSlowInvocationEnabled()); -// Assert.assertEquals(2000, config.getMsSlowInvocation()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(2000), config.getNanoSlowInvocation()); -// -// // new configuration key, has high priority -// ArchaiusUtils.setProperty("servicecomb.metrics.Consumer.invocation.slow.enabled", false); -// ArchaiusUtils.setProperty("servicecomb.metrics.Consumer.invocation.slow.msTime", 3000); -// Assert.assertFalse(config.isSlowInvocationEnabled()); -// Assert.assertEquals(3000, config.getMsSlowInvocation()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(3000), config.getNanoSlowInvocation()); -// -// ArchaiusUtils.setProperty("servicecomb.metrics.Consumer.invocation.slow.enabled.perfClient", true); -// ArchaiusUtils.setProperty("servicecomb.metrics.Consumer.invocation.slow.msTime.perfClient", 4000); -// Assert.assertTrue(config.isSlowInvocationEnabled()); -// Assert.assertEquals(4000, config.getMsSlowInvocation()); -// Assert.assertEquals(TimeUnit.MILLISECONDS.toNanos(4000), config.getNanoSlowInvocation()); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/TestSchemaMeta.java b/core/src/test/java/org/apache/servicecomb/core/definition/TestSchemaMeta.java deleted file mode 100644 index 8e7214cdfbc..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/TestSchemaMeta.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.core.definition; - -public class TestSchemaMeta { -// interface V1 { -// void a(); -// } -// -// interface V2 extends V1 { -// void b(); -// } -// -// @Test -// public void testMethodNotExist(@Mocked OperationMeta operationMeta) { -// Swagger swagger = SwaggerGenerator.generate(V2.class); -// // make swagger have more operations than interface -// swagger.getInfo().setVendorExtension(SwaggerConst.EXT_JAVA_INTF, V1.class.getName()); -// -// MicroserviceMeta microserviceMeta = new MicroserviceMeta("app:ms"); -// SchemaMeta schemaMeta = new SchemaMeta(swagger, microserviceMeta, "schemaId"); -// Assert.assertEquals(1, schemaMeta.getOperations().size()); -// Assert.assertNotNull(schemaMeta.findOperation("a")); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/loader/TestDynamicSchemaLoader.java b/core/src/test/java/org/apache/servicecomb/core/definition/loader/TestDynamicSchemaLoader.java deleted file mode 100644 index 7538aee6704..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/loader/TestDynamicSchemaLoader.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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.core.definition.loader; - -public class TestDynamicSchemaLoader { -// -// private static SchemaLoader loader = new SchemaLoader(); -// -// private static Microservice microservice; -// -// @BeforeClass -// public static void init() { -// new UnitTestMeta(); -// -// SchemaListenerManager schemaListenerManager = new SchemaListenerManager(); -// schemaListenerManager.setSchemaListenerList(Collections.emptyList()); -// -// CseContext context = CseContext.getInstance(); -// context.setSchemaLoader(loader); -// context.setSchemaListenerManager(schemaListenerManager); -// -// ServiceRegistry serviceRegistry = ServiceRegistryFactory.createLocal(); -// serviceRegistry.init(); -// -// microservice = serviceRegistry.getMicroservice(); -// RegistryUtils.setServiceRegistry(serviceRegistry); -// } -// -// @AfterClass -// public static void teardown() { -// RegistryUtils.setServiceRegistry(null); -// } -// -// @SuppressWarnings("deprecation") -// @Test -// public void testRegisterSchemas() { -// DynamicSchemaLoader.INSTANCE.registerSchemas("classpath*:test/test/schema.yaml"); -// SchemaMeta schemaMeta = SCBEngine.getInstance().getProducerMicroserviceMeta().ensureFindSchemaMeta("schema"); -// Assert.assertNotNull(schemaMeta); -// } -// -// @SuppressWarnings("deprecation") -// @Test -// public void testRegisterShemasAcrossApp() { -// //we can not register repeat data -// init(); -// //as we can not set microserviceName any more, hence we should use the default name -// DynamicSchemaLoader.INSTANCE -// .registerSchemas(RegistryUtils.getMicroservice().getServiceName(), "classpath*:test/test/schema.yaml"); -// SchemaMeta schemaMeta = -// SCBEngine.getInstance().getProducerMicroserviceMeta().ensureFindSchemaMeta("schema"); -// Assert.assertNotNull(schemaMeta); -// } -// -// @Test -// public void testPutSelfBasePathIfAbsent_noUrlPrefix() { -// System.clearProperty(Const.URL_PREFIX); -// microservice.setPaths(new ArrayList<>()); -// -// loader.putSelfBasePathIfAbsent("perfClient", "/test"); -// -// Assert.assertThat(microservice.getPaths().size(), Matchers.is(1)); -// Assert.assertThat(microservice.getPaths().get(0).getPath(), Matchers.is("/test")); -// } -// -// @Test -// public void testPutSelfBasePathIfAbsent_WithUrlPrefix() { -// System.setProperty(Const.URL_PREFIX, "/root/rest"); -// microservice.setPaths(new ArrayList<>()); -// -// loader.putSelfBasePathIfAbsent("perfClient", "/test"); -// -// Assert.assertThat(microservice.getPaths().size(), Matchers.is(1)); -// Assert.assertThat(microservice.getPaths().get(0).getPath(), Matchers.is("/root/rest/test")); -// -// System.clearProperty(Const.URL_PREFIX); -// } -// -// @Test -// public void testPutSelfBasePathIfAbsent_WithUrlPrefix_StartWithUrlPrefix() { -// System.setProperty(Const.URL_PREFIX, "/root/rest"); -// microservice.setPaths(new ArrayList<>()); -// -// loader.putSelfBasePathIfAbsent("perfClient", "/root/rest/test"); -// -// Assert.assertThat(microservice.getPaths().size(), Matchers.is(1)); -// Assert.assertThat(microservice.getPaths().get(0).getPath(), Matchers.is("/root/rest/test")); -// -// System.clearProperty(Const.URL_PREFIX); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/loader/TestSchemaListenerManager.java b/core/src/test/java/org/apache/servicecomb/core/definition/loader/TestSchemaListenerManager.java deleted file mode 100644 index 764aa9950fb..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/definition/loader/TestSchemaListenerManager.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.core.definition.loader; - -public class TestSchemaListenerManager { -// -// SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); -// -// @Before -// public void setUp() { -// Mockito.when(schemaMeta.getSchemaId()).thenReturn("test"); -// } -// -// @Test -// public void testInitializationListener() { -// SchemaListener listener = new SchemaListener() { -// @Override -// public void onSchemaLoaded(SchemaMeta... schemaMetas) { -// Assert.assertEquals(1, schemaMetas.length); -// Assert.assertEquals("test", schemaMetas[0].getSchemaId()); -// } -// }; -// -// SchemaListenerManager mgr = new SchemaListenerManager(); -// mgr.setSchemaListenerList(Arrays.asList(listener)); -// -// mgr.notifySchemaListener(schemaMeta); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationFinishEvent.java b/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationFinishEvent.java deleted file mode 100644 index daae2d6357d..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationFinishEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.core.event; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.invocation.InvocationStageTrace; -import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestInvocationFinishEvent { - InvocationFinishEvent event; - - @Test - public void construct(@Mocked Invocation invocation, @Mocked Response response) { - InvocationStageTrace stageTrace = new InvocationStageTrace(invocation); - long time = 123; - new MockUp() { - @Mock - long nanoTime() { - return time; - } - }; - new Expectations() { - { - invocation.getInvocationStageTrace(); - result = stageTrace; - } - }; - stageTrace.finish(); - - event = new InvocationFinishEvent(invocation, response); - - Assert.assertEquals(time, event.getNanoCurrent()); - Assert.assertSame(invocation, event.getInvocation()); - Assert.assertSame(response, event.getResponse()); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationStartEvent.java b/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationStartEvent.java index 9181520bc46..6e0649d4aa1 100644 --- a/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationStartEvent.java +++ b/core/src/test/java/org/apache/servicecomb/core/event/TestInvocationStartEvent.java @@ -17,18 +17,18 @@ package org.apache.servicecomb.core.event; import org.apache.servicecomb.core.Invocation; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Mocked; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestInvocationStartEvent { InvocationStartEvent event; @Test - public void construct(@Mocked Invocation invocation) { + public void construct() { + Invocation invocation = Mockito.mock(Invocation.class); event = new InvocationStartEvent(invocation); - Assert.assertSame(invocation, event.getInvocation()); + Assertions.assertSame(invocation, event.getInvocation()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java b/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java index c0cd78a9592..0594084e30c 100644 --- a/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/exception/ExceptionsTest.java @@ -17,15 +17,13 @@ package org.apache.servicecomb.core.exception; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static org.assertj.core.api.Assertions.assertThat; +import com.fasterxml.jackson.databind.ObjectMapper; import java.util.Collections; -import javax.annotation.Nullable; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; @@ -34,8 +32,12 @@ import org.junit.jupiter.api.Test; import io.vertx.core.json.Json; +import jakarta.ws.rs.core.Response.StatusType; class ExceptionsTest { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + @Test void should_not_convert_invocation_exception() { InvocationException exception = Exceptions.genericConsumer("msg"); @@ -53,8 +55,13 @@ void should_convert_unknown_client_exception_to_invocation_exception() { assertThat(invocationException).hasCause(exception); assertThat(invocationException.getStatus()).isEqualTo(BAD_REQUEST); assertThat(invocationException.getErrorData()).isInstanceOf(CommonExceptionData.class); - assertThat(Json.encode(invocationException.getErrorData())) - .isEqualTo("{\"code\":\"SCB.00000000\",\"message\":\"msg\"}"); + + try { + assertThat(objectMapper.readTree(Json.encode(invocationException.getErrorData()))) + .isEqualTo(objectMapper.readTree("{\"code\":\"SCB.00000000\",\"message\":\"Unexpected exception when processing none. msg\"}")); + } catch (Exception e) { + throw new AssertionError("Error during JSON comparison: " + e.getMessage(), e); + } } @Test @@ -66,8 +73,13 @@ void should_convert_unknown_server_exception_to_invocation_exception() { assertThat(invocationException).hasCause(exception); assertThat(invocationException.getStatus()).isEqualTo(INTERNAL_SERVER_ERROR); assertThat(invocationException.getErrorData()).isInstanceOf(CommonExceptionData.class); - assertThat(Json.encode(invocationException.getErrorData())) - .isEqualTo("{\"code\":\"SCB.50000000\",\"message\":\"msg\"}"); + + try { + assertThat(objectMapper.readTree(Json.encode(invocationException.getErrorData()))) + .isEqualTo(objectMapper.readTree("{\"code\":\"SCB.50000000\",\"message\":\"Unexpected exception when processing none. msg\"}")); + } catch (Exception e) { + throw new AssertionError("Error during JSON comparison: " + e.getMessage(), e); + } } static class ThrowExceptionWhenConvert implements ExceptionConverter { @@ -82,7 +94,7 @@ public boolean canConvert(Throwable throwable) { } @Override - public InvocationException convert(@Nullable Invocation invocation, Throwable throwable, StatusType genericStatus) { + public InvocationException convert(Invocation invocation, Throwable throwable, StatusType genericStatus) { throw new RuntimeExceptionWithoutStackTrace("mock exception when convert"); } } @@ -100,10 +112,10 @@ void should_protect_when_converter_throw_exception() { .isSameAs(INTERNAL_SERVER_ERROR); assertThat(exception.getErrorData().toString()) .isEqualTo("CommonExceptionData{code='SCB.50000000', message='Internal Server Error', dynamic={}}"); - assertThat(logCollector.getLastEvents().getRenderedMessage().replace("\r\n", "\n")) + assertThat(logCollector.getLastEvents().getMessage().getFormattedMessage().replace("\r\n", "\n")) .isEqualTo("BUG: ExceptionConverter.convert MUST not throw exception, please fix it.\n" + "original exception :org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace: exception need convert\n" + "converter exception:org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace: mock exception when convert\n"); } } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverterTest.java b/core/src/test/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverterTest.java index 6527bd5f67b..3a1b69908bb 100644 --- a/core/src/test/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverterTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/exception/converter/TimeoutExceptionConverterTest.java @@ -21,7 +21,7 @@ import java.util.concurrent.TimeoutException; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; @@ -33,8 +33,7 @@ private InvocationException convert() { TimeoutException timeoutException = new TimeoutException( "The timeout period of 30000ms has been exceeded while executing GET /xxx for server 1.1.1.1:8080"); - InvocationException exception = Exceptions.convert(null, timeoutException, Status.BAD_REQUEST); - return exception; + return Exceptions.convert(null, timeoutException, Status.BAD_REQUEST); } @Test @@ -51,9 +50,9 @@ void should_log_detail() { try (LogCollector logCollector = new LogCollector()) { convert(); - assertThat(logCollector.getLastEvents().getRenderedMessage()) + assertThat(logCollector.getLastEvents().getMessage().getFormattedMessage()) .isEqualTo( "Request timeout, Details: The timeout period of 30000ms has been exceeded while executing GET /xxx for server 1.1.1.1:8080."); } } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/executor/TestExecutorManager.java b/core/src/test/java/org/apache/servicecomb/core/executor/TestExecutorManager.java index 3165d45b100..2fc689efb05 100644 --- a/core/src/test/java/org/apache/servicecomb/core/executor/TestExecutorManager.java +++ b/core/src/test/java/org/apache/servicecomb/core/executor/TestExecutorManager.java @@ -21,11 +21,12 @@ import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import mockit.Expectations; import mockit.Mocked; @@ -34,14 +35,17 @@ public class TestExecutorManager { @Mocked Executor defaultExecutor; + ExecutorManager executorManager = new ExecutorManager(); + + Environment environment = Mockito.mock(Environment.class); + @Before public void setup() { - ArchaiusUtils.resetConfig(); + executorManager.setEnvironment(environment); } @After public void teardown() { - ArchaiusUtils.resetConfig(); } @Test @@ -53,7 +57,7 @@ public void findExecutor_oneParam(@Mocked Executor executor, @Mocked OperationMe } }; - Assert.assertSame(executor, new ExecutorManager().findExecutor(operationMeta)); + Assertions.assertSame(executor, executorManager.findExecutor(operationMeta)); } @Test @@ -62,7 +66,8 @@ public void findExecutor_twoParam_opCfg_withoutOpDef(@Mocked Executor executor, // String schemaQualifiedName = "schemaId.opId"; String microserviceQualifiedName = "microserviceName.schemaId.opId"; String opBeanId = "opBeanId"; - ArchaiusUtils.setProperty(ExecutorManager.KEY_EXECUTORS_PREFIX + microserviceQualifiedName, opBeanId); + Mockito.when(environment.getProperty( + ExecutorManager.KEY_EXECUTORS_PREFIX + microserviceQualifiedName)).thenReturn(opBeanId); new Expectations(BeanUtils.class) { { operationMeta.getMicroserviceQualifiedName(); @@ -72,7 +77,7 @@ public void findExecutor_twoParam_opCfg_withoutOpDef(@Mocked Executor executor, } }; - Assert.assertSame(executor, new ExecutorManager().findExecutor(operationMeta, null)); + Assertions.assertSame(executor, executorManager.findExecutor(operationMeta, null)); } @Test @@ -81,7 +86,8 @@ public void findExecutor_twoParam_opCfg_withOpDef(@Mocked Executor executor, @Mocked OperationMeta operationMeta) { String microserviceQualifiedName = "microserviceName.schemaId.opId"; String opBeanId = "opBeanId"; - ArchaiusUtils.setProperty(ExecutorManager.KEY_EXECUTORS_PREFIX + microserviceQualifiedName, opBeanId); + Mockito.when(environment.getProperty( + ExecutorManager.KEY_EXECUTORS_PREFIX + microserviceQualifiedName)).thenReturn(opBeanId); new Expectations(BeanUtils.class) { { operationMeta.getMicroserviceQualifiedName(); @@ -91,13 +97,13 @@ public void findExecutor_twoParam_opCfg_withOpDef(@Mocked Executor executor, } }; - Assert.assertSame(executor, new ExecutorManager().findExecutor(operationMeta, defExecutor)); + Assertions.assertSame(executor, executorManager.findExecutor(operationMeta, defExecutor)); } @Test public void findExecutor_twoParam_schemaCfg_withOpDef(@Mocked OperationMeta operationMeta, @Mocked Executor defExecutor) { - Assert.assertSame(defExecutor, new ExecutorManager().findExecutor(operationMeta, defExecutor)); + Assertions.assertSame(defExecutor, executorManager.findExecutor(operationMeta, defExecutor)); } @Test @@ -106,7 +112,8 @@ public void findExecutor_twoParam_schemaCfg_withoutOpDef(@Mocked Executor execut String microserviceName = "serviceName"; String schemaName = "schemaId"; String opBeanId = "opBeanId"; - ArchaiusUtils.setProperty(ExecutorManager.KEY_EXECUTORS_PREFIX + microserviceName + "." + schemaName, opBeanId); + Mockito.when(environment.getProperty(ExecutorManager.KEY_EXECUTORS_PREFIX + microserviceName + "." + schemaName)) + .thenReturn(opBeanId); new Expectations(BeanUtils.class) { { operationMeta.getSchemaId(); @@ -117,7 +124,7 @@ public void findExecutor_twoParam_schemaCfg_withoutOpDef(@Mocked Executor execut result = executor; } }; - Assert.assertSame(executor, new ExecutorManager().findExecutor(operationMeta, null)); + Assertions.assertSame(executor, executorManager.findExecutor(operationMeta, null)); } @Test @@ -125,7 +132,7 @@ public void findExecutor_twoParam_defaultCfg(@Mocked Executor executor, @Mocked SchemaMeta schemaMeta, @Mocked OperationMeta operationMeta) { String beanId = "beanId"; - ArchaiusUtils.setProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, beanId); + Mockito.when(environment.getProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT)).thenReturn(beanId); new Expectations(BeanUtils.class) { { BeanUtils.getBean(beanId); @@ -133,6 +140,6 @@ public void findExecutor_twoParam_defaultCfg(@Mocked Executor executor, } }; - Assert.assertSame(executor, new ExecutorManager().findExecutor(operationMeta, null)); + Assertions.assertSame(executor, executorManager.findExecutor(operationMeta, null)); } } 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 f65693deaaa..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 @@ -17,104 +17,117 @@ package org.apache.servicecomb.core.executor; +import static org.apache.servicecomb.core.executor.GroupExecutor.KEY_CORE_THREADS; +import static org.apache.servicecomb.core.executor.GroupExecutor.KEY_GROUP; +import static org.apache.servicecomb.core.executor.GroupExecutor.KEY_MAX_IDLE_SECOND; +import static org.apache.servicecomb.core.executor.GroupExecutor.KEY_MAX_QUEUE_SIZE; +import static org.apache.servicecomb.core.executor.GroupExecutor.KEY_MAX_THREADS; +import static org.apache.servicecomb.core.executor.GroupExecutor.KEY_OLD_MAX_THREAD; + import java.util.List; import java.util.Map; import java.util.concurrent.Executor; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import mockit.Deencapsulation; public class TestGroupExecutor { String strThreadTest = "default"; - @Before + @BeforeEach public void setup() { - ArchaiusUtils.resetConfig(); + Mockito.when(environment.getProperty(KEY_GROUP, int.class, 2)).thenReturn(2); + Mockito.when(environment.getProperty(KEY_CORE_THREADS, int.class, 25)).thenReturn(25); + Mockito.when(environment.getProperty(KEY_MAX_IDLE_SECOND, int.class, 60)).thenReturn(60); + Mockito.when(environment.getProperty(KEY_MAX_THREADS, int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty(KEY_OLD_MAX_THREAD, int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty(KEY_MAX_QUEUE_SIZE, int.class, Integer.MAX_VALUE)) + .thenReturn(Integer.MAX_VALUE); } - @AfterClass + @AfterAll public static void teardown() { - ArchaiusUtils.resetConfig(); } - GroupExecutor groupExecutor = new GroupExecutor(); + Environment environment = Mockito.mock(Environment.class); + + GroupExecutor groupExecutor = new GroupExecutor(environment); @Test public void groupCount() { groupExecutor.initConfig(); - Assert.assertEquals(2, groupExecutor.groupCount); + Assertions.assertEquals(2, groupExecutor.groupCount); - ArchaiusUtils.setProperty(GroupExecutor.KEY_GROUP, 4); + Mockito.when(environment.getProperty(KEY_GROUP, int.class, 2)).thenReturn(4); groupExecutor.initConfig(); - Assert.assertEquals(4, groupExecutor.groupCount); + Assertions.assertEquals(4, groupExecutor.groupCount); } @Test public void coreThreads() { groupExecutor.initConfig(); - Assert.assertEquals(25, groupExecutor.coreThreads); + Assertions.assertEquals(25, groupExecutor.coreThreads); - ArchaiusUtils.setProperty(GroupExecutor.KEY_CORE_THREADS, 100); + Mockito.when(environment.getProperty(KEY_CORE_THREADS, int.class, 25)).thenReturn(100); groupExecutor.initConfig(); - Assert.assertEquals(100, groupExecutor.coreThreads); + Assertions.assertEquals(100, groupExecutor.coreThreads); } @Test public void maxIdleInSecond() { groupExecutor.initConfig(); - Assert.assertEquals(60, groupExecutor.maxIdleInSecond); + Assertions.assertEquals(60, groupExecutor.maxIdleInSecond); - ArchaiusUtils.setProperty(GroupExecutor.KEY_MAX_IDLE_SECOND, 100); + Mockito.when(environment.getProperty(KEY_MAX_IDLE_SECOND, int.class, 60)).thenReturn(100); groupExecutor.initConfig(); - Assert.assertEquals(100, groupExecutor.maxIdleInSecond); + Assertions.assertEquals(100, groupExecutor.maxIdleInSecond); } @Test public void maxQueueSize() { groupExecutor.initConfig(); - Assert.assertEquals(Integer.MAX_VALUE, groupExecutor.maxQueueSize); - - ArchaiusUtils.setProperty(GroupExecutor.KEY_MAX_QUEUE_SIZE, 100); + Assertions.assertEquals(Integer.MAX_VALUE, groupExecutor.maxQueueSize); + Mockito.when(environment.getProperty(KEY_MAX_QUEUE_SIZE, int.class, Integer.MAX_VALUE)).thenReturn(100); groupExecutor.initConfig(); - Assert.assertEquals(100, groupExecutor.maxQueueSize); + Assertions.assertEquals(100, groupExecutor.maxQueueSize); } @Test public void maxThreads() { groupExecutor.initConfig(); - Assert.assertEquals(100, groupExecutor.maxThreads); + Assertions.assertEquals(100, groupExecutor.maxThreads); LogCollector collector = new LogCollector(); - ArchaiusUtils.setProperty(GroupExecutor.KEY_OLD_MAX_THREAD, 200); + Mockito.when(environment.getProperty(KEY_OLD_MAX_THREAD, int.class, -1)).thenReturn(200); groupExecutor.initConfig(); - Assert.assertEquals(200, groupExecutor.maxThreads); - Assert.assertEquals( + Assertions.assertEquals(200, groupExecutor.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()); - collector.teardown(); + collector.getEvents().get(collector.getEvents().size() - 2).getMessage().getFormattedMessage()); + collector.tearDown(); - ArchaiusUtils.setProperty(GroupExecutor.KEY_MAX_THREADS, 300); + Mockito.when(environment.getProperty(KEY_MAX_THREADS, int.class, -1)).thenReturn(300); groupExecutor.initConfig(); - Assert.assertEquals(300, groupExecutor.maxThreads); + Assertions.assertEquals(300, groupExecutor.maxThreads); } @Test public void adjustCoreThreads() { - ArchaiusUtils.setProperty(GroupExecutor.KEY_MAX_THREADS, 10); - + Mockito.when(environment.getProperty(KEY_MAX_THREADS, int.class, -1)).thenReturn(10); LogCollector collector = new LogCollector(); groupExecutor.initConfig(); - Assert.assertEquals(10, groupExecutor.maxThreads); - Assert.assertEquals( + Assertions.assertEquals(10, groupExecutor.maxThreads); + Assertions.assertEquals( "coreThreads is bigger than maxThreads, change from 25 to 10.", - collector.getEvents().get(collector.getEvents().size() - 2).getMessage()); - collector.teardown(); + collector.getEvents().get(collector.getEvents().size() - 2).getMessage().getFormattedMessage()); + collector.tearDown(); } @Test @@ -123,14 +136,14 @@ public void testGroupExecutor() { groupExecutor.execute(() -> { }); Map threadExecutorMap = Deencapsulation.getField(groupExecutor, "threadExecutorMap"); - Assert.assertEquals(true, (threadExecutorMap.size() > 0)); + Assertions.assertTrue((threadExecutorMap.size() > 0)); List executorList = Deencapsulation.getField(groupExecutor, "executorList"); - Assert.assertEquals(true, (executorList.size() > 1)); + Assertions.assertTrue((executorList.size() > 1)); ReactiveExecutor oReactiveExecutor = new ReactiveExecutor(); oReactiveExecutor.execute(() -> strThreadTest = "thread Ran"); oReactiveExecutor.close(); - Assert.assertEquals("thread Ran", strThreadTest); + Assertions.assertEquals("thread Ran", strThreadTest); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/executor/TestThreadPoolExecutorEx.java b/core/src/test/java/org/apache/servicecomb/core/executor/TestThreadPoolExecutorEx.java index eaf4133eb17..7382d3793a4 100644 --- a/core/src/test/java/org/apache/servicecomb/core/executor/TestThreadPoolExecutorEx.java +++ b/core/src/test/java/org/apache/servicecomb/core/executor/TestThreadPoolExecutorEx.java @@ -24,8 +24,8 @@ import java.util.concurrent.TimeUnit; import java.util.function.IntSupplier; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,49 +64,49 @@ public TestTask submitTask() { @Test public void schedule() throws ExecutionException, InterruptedException { // init - Assert.assertEquals(0, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(0, executorEx.getNotFinished()); - Assert.assertEquals(0, executorEx.getQueue().size()); + Assertions.assertEquals(0, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(0, executorEx.getNotFinished()); + Assertions.assertEquals(0, executorEx.getQueue().size()); // use core threads TestTask t1 = submitTask(); - Assert.assertEquals(1, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(1, executorEx.getNotFinished()); - Assert.assertEquals(0, executorEx.getQueue().size()); + Assertions.assertEquals(1, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(1, executorEx.getNotFinished()); + Assertions.assertEquals(0, executorEx.getQueue().size()); TestTask t2 = submitTask(); - Assert.assertEquals(2, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(2, executorEx.getNotFinished()); - Assert.assertEquals(0, executorEx.getQueue().size()); + Assertions.assertEquals(2, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(2, executorEx.getNotFinished()); + Assertions.assertEquals(0, executorEx.getQueue().size()); // extend threads TestTask t3 = submitTask(); - Assert.assertEquals(3, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(3, executorEx.getNotFinished()); - Assert.assertEquals(0, executorEx.getQueue().size()); + Assertions.assertEquals(3, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(3, executorEx.getNotFinished()); + Assertions.assertEquals(0, executorEx.getQueue().size()); TestTask t4 = submitTask(); - Assert.assertEquals(4, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(4, executorEx.getNotFinished()); - Assert.assertEquals(0, executorEx.getQueue().size()); + Assertions.assertEquals(4, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(4, executorEx.getNotFinished()); + Assertions.assertEquals(0, executorEx.getQueue().size()); // queue the tasks TestTask t5 = submitTask(); - Assert.assertEquals(4, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(5, executorEx.getNotFinished()); - Assert.assertEquals(1, executorEx.getQueue().size()); + Assertions.assertEquals(4, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(5, executorEx.getNotFinished()); + Assertions.assertEquals(1, executorEx.getQueue().size()); TestTask t6 = submitTask(); - Assert.assertEquals(4, executorEx.getPoolSize()); - Assert.assertEquals(0, executorEx.getRejectedCount()); - Assert.assertEquals(6, executorEx.getNotFinished()); - Assert.assertEquals(2, executorEx.getQueue().size()); + Assertions.assertEquals(4, executorEx.getPoolSize()); + Assertions.assertEquals(0, executorEx.getRejectedCount()); + Assertions.assertEquals(6, executorEx.getNotFinished()); + Assertions.assertEquals(2, executorEx.getQueue().size()); // reject the task try { @@ -114,24 +114,24 @@ public void schedule() throws ExecutionException, InterruptedException { } catch (RejectedExecutionException e) { } - Assert.assertEquals(4, executorEx.getPoolSize()); - Assert.assertEquals(1, executorEx.getRejectedCount()); - Assert.assertEquals(6, executorEx.getNotFinished()); - Assert.assertEquals(2, executorEx.getQueue().size()); + Assertions.assertEquals(4, executorEx.getPoolSize()); + Assertions.assertEquals(1, executorEx.getRejectedCount()); + Assertions.assertEquals(6, executorEx.getNotFinished()); + Assertions.assertEquals(2, executorEx.getQueue().size()); // t1/t2/t3 finish t1.quit(); t2.quit(); t3.quit(); - Assert.assertEquals(4, executorEx.getPoolSize()); - Assert.assertEquals(1, executorEx.getRejectedCount()); + Assertions.assertEquals(4, executorEx.getPoolSize()); + Assertions.assertEquals(1, executorEx.getRejectedCount()); waitForResult(3, executorEx::getNotFinished); waitForResult(0, executorEx.getQueue()::size); // reuse thread t3 = submitTask(); - Assert.assertEquals(4, executorEx.getPoolSize()); - Assert.assertEquals(1, executorEx.getRejectedCount()); + Assertions.assertEquals(4, executorEx.getPoolSize()); + Assertions.assertEquals(1, executorEx.getRejectedCount()); waitForResult(4, executorEx::getNotFinished); waitForResult(0, executorEx.getQueue()::size); diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java b/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java index 85b805c0bcf..5a5dc1cb05e 100644 --- a/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java @@ -17,27 +17,21 @@ package org.apache.servicecomb.core.filter; -import static org.apache.servicecomb.core.Const.HIGHWAY; -import static org.apache.servicecomb.core.Const.RESTFUL; import static org.apache.servicecomb.core.filter.FilterNode.buildChain; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; -import java.io.IOException; import java.util.List; import java.util.Vector; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.core.definition.OperationConfig; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.filter.impl.ScheduleFilter; -import org.apache.servicecomb.core.filter.impl.TransportFilters; import org.apache.servicecomb.swagger.invocation.Response; import org.junit.BeforeClass; import org.junit.Test; @@ -61,19 +55,35 @@ public class FilterChainTest { List msg = new Vector<>(); - Filter recordThreadFilter = (invocation, nextNode) -> { - msg.add(Thread.currentThread().getName()); - if (nextNode == null) { - return CompletableFuture.completedFuture(Response.ok(null)); + Filter recordThreadFilter = new AbstractFilter() { + @Override + public String getName() { + return "f2"; } - return nextNode.onFilter(invocation); + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + msg.add(Thread.currentThread().getName()); + if (nextNode == null) { + return CompletableFuture.completedFuture(Response.ok(null)); + } + + return nextNode.onFilter(invocation); + } }; Filter scheduler = new ScheduleFilter(); - Filter exceptionFilter = (invocation, nextNode) -> { - throw new IllegalStateException("e1"); + Filter exceptionFilter = new AbstractFilter() { + @Override + public String getName() { + return "f1"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + throw new IllegalStateException("e1"); + } }; @BeforeClass @@ -136,84 +146,4 @@ public void should_stop_chain_when_middle_filter_throw_exception() { .isInstanceOf(IllegalStateException.class) .hasMessage("e1"); } - - @Test - public void should_support_retry_logic() { - Filter exceptionFilter = (invocation, nextNode) -> { - throw new CompletionException(new IOException("net error")); - }; - SimpleRetryFilter retryFilter = new SimpleRetryFilter().setMaxRetry(3); - - CompletableFuture future = buildChain(retryFilter, recordThreadFilter, exceptionFilter) - .onFilter(invocation); - - assertThat(msg).containsExactly("main", "main", "main"); - assertThat(future) - .hasFailedWithThrowableThat() - .isExactlyInstanceOf(IOException.class) - .hasMessage("net error"); - } - - @Test - public void should_build_chain_with_TransportFilters(@Mocked Transport transport) - throws ExecutionException, InterruptedException { - mockInvocation(); - new Expectations() { - { - invocation.getTransport(); - result = transport; - } - }; - TransportFilters transportFilters = new TransportFilters(); - transportFilters.getChainByTransport().put(RESTFUL, buildChain(recordThreadFilter)); - transportFilters.getChainByTransport().put(HIGHWAY, buildChain(recordThreadFilter, scheduler, recordThreadFilter)); - - FilterNode chain = buildChain(transportFilters, recordThreadFilter); - - checkRestChain(transport, chain); - checkHighwayChain(transport, chain); - checkUnknownTransportChain(transport, chain); - } - - private void checkUnknownTransportChain(Transport transport, FilterNode chain) - throws ExecutionException, InterruptedException { - msg.clear(); - new Expectations() { - { - transport.getName(); - result = "abc"; - } - }; - chain.onFilter(invocation) - .get(); - assertThat(msg).containsExactly("main"); - } - - private void checkRestChain(Transport transport, FilterNode chain) - throws InterruptedException, ExecutionException { - msg.clear(); - new Expectations() { - { - transport.getName(); - result = RESTFUL; - } - }; - chain.onFilter(invocation) - .get(); - assertThat(msg).containsExactly("main", "main"); - } - - private void checkHighwayChain(Transport transport, FilterNode chain) - throws InterruptedException, ExecutionException { - msg.clear(); - new Expectations() { - { - transport.getName(); - result = HIGHWAY; - } - }; - chain.onFilter(invocation) - .get(); - assertThat(msg).containsExactly("main", THREAD_NAME, THREAD_NAME); - } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java b/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java deleted file mode 100644 index ce54faf12c3..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.core.filter; - -import java.io.IOException; -import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.Exceptions; -import org.apache.servicecomb.swagger.invocation.Response; - -public class SimpleRetryFilter implements ConsumerFilter { - protected int maxRetry = 3; - - @Nonnull - @Override - public String getName() { - return "simple-retry"; - } - - public SimpleRetryFilter setMaxRetry(int maxRetry) { - this.maxRetry = maxRetry; - return this; - } - - @Override - public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { - return new RetrySession(invocation, nextNode).run(); - } - - protected Throwable unwrapException(Throwable throwable) { - return Exceptions.unwrapIncludeInvocationException(throwable); - } - - protected boolean isRetryException(Throwable throwable) { - return !(throwable instanceof IOException); - } - - class RetrySession { - Invocation invocation; - - FilterNode nextNode; - - int retryCount; - - CompletableFuture future = new CompletableFuture<>(); - - RetrySession(Invocation invocation, FilterNode nextNode) { - this.invocation = invocation; - this.nextNode = nextNode; - } - - CompletableFuture run() { - nextNode.onFilter(invocation) - .whenComplete(this::whenNextComplete); - return future; - } - - private void whenNextComplete(Response response, Throwable throwable) { - if (throwable == null) { - future.complete(response); - return; - } - - Throwable unwrapped = unwrapException(throwable); - if (isRetryException(unwrapped)) { - future.completeExceptionally(throwable); - return; - } - - retryCount++; - if (retryCount >= maxRetry) { - future.completeExceptionally(throwable); - return; - } - - run(); - } - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilterTest.java b/core/src/test/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilterTest.java index d21e9a991f4..4afed2d7dde 100644 --- a/core/src/test/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilterTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilterTest.java @@ -17,36 +17,39 @@ package org.apache.servicecomb.core.filter.impl; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static jakarta.ws.rs.core.Response.Status.BAD_REQUEST; import static org.apache.servicecomb.core.exception.ExceptionCodes.DEFAULT_VALIDATE; import static org.apache.servicecomb.core.exception.converter.ConstraintViolationExceptionConverter.KEY_CODE; +import static org.apache.servicecomb.core.filter.impl.ParameterValidatorFilter.ENABLE_EL; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import java.util.List; -import javax.validation.Valid; -import javax.validation.constraints.NotBlank; -import javax.validation.constraints.NotNull; - import org.apache.commons.lang3.reflect.MethodUtils; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.bootstrap.SCBBootstrap; import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.core.exception.Exceptions; import org.apache.servicecomb.core.exception.converter.ConstraintViolationExceptionConverter; import org.apache.servicecomb.core.exception.converter.ValidateDetail; import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation; import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MutablePropertySources; import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import mockit.Expectations; import mockit.Mocked; @@ -86,7 +89,7 @@ public void op(@NotNull(message = "not null") String query, @Valid Model model) } } - static ParameterValidatorFilter filter = new ParameterValidatorFilter(); + ParameterValidatorFilter filter = new ParameterValidatorFilter(); @Mocked Invocation invocation; @@ -94,13 +97,19 @@ public void op(@NotNull(message = "not null") String query, @Valid Model model) @Mocked SwaggerProducerOperation operation; - @BeforeClass - public static void beforeClass() throws Exception { - filter.afterPropertiesSet(); - } + ConfigurableEnvironment environment; @Before public void setUp() throws Exception { + environment = Mockito.mock(ConfigurableEnvironment.class); + SCBEngine engine = SCBBootstrap.createSCBEngineForTest(environment); + MutablePropertySources sources = new MutablePropertySources(); + + Mockito.when(environment.getProperty(ENABLE_EL, boolean.class, false)).thenReturn(false); + Mockito.when(environment.getPropertySources()).thenReturn(sources); + filter.setEnvironment(environment); + filter.afterPropertiesSet(); + engine.setEnvironment(environment); new Expectations() { { operation.getProducerInstance(); @@ -134,7 +143,7 @@ public void status_code_should_be_bad_request() { @Test public void error_code_and_message_should_be_build_in_value() { - ArchaiusUtils.setProperty(KEY_CODE, null); + Mockito.when(environment.getProperty(KEY_CODE, String.class, DEFAULT_VALIDATE)).thenReturn(DEFAULT_VALIDATE); CommonExceptionData errorData = getExceptionData(); assertThat(errorData.getCode()).isEqualTo(DEFAULT_VALIDATE); @@ -143,13 +152,11 @@ public void error_code_and_message_should_be_build_in_value() { @Test public void should_allow_customize_error_code_by_configuration() { - ArchaiusUtils.setProperty(KEY_CODE, "test.0001"); - SPIServiceUtils.getTargetService(ExceptionConverter.class, ConstraintViolationExceptionConverter.class) - .refreshCode(); + Mockito.when(environment.getProperty(KEY_CODE, String.class, DEFAULT_VALIDATE)).thenReturn("test.0001"); + SPIServiceUtils.getTargetService(ExceptionConverter.class, ConstraintViolationExceptionConverter.class); CommonExceptionData errorData = getExceptionData(); assertThat(errorData.getCode()).isEqualTo("test.0001"); - ArchaiusUtils.setProperty(KEY_CODE, null); } @Test @@ -171,4 +178,4 @@ public void should_include_all_validate_detail() { assertThat(details.stream().map(ValidateDetail::getMessage)) .contains("not null", "can not be null", "can not be blank"); } -} \ No newline at end of file +} 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 fd932f1b9b8..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 @@ -17,12 +17,14 @@ package org.apache.servicecomb.core.filter.impl; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; +import static jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import java.lang.reflect.Method; +import java.time.Duration; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.exception.Exceptions; @@ -42,7 +44,7 @@ import mockit.Verifications; public class ProducerOperationFilterTest { - ProducerOperationFilter filter = new ProducerOperationFilter(); + ProviderOperationFilter filter = new ProviderOperationFilter(); @Injectable Invocation invocation; @@ -81,9 +83,6 @@ public void should_record_invocation_trace_time() throws NoSuchMethodException { invocation.onBusinessMethodStart(); times = 1; - invocation.onBusinessMethodFinish(); - times = 1; - invocation.onBusinessFinish(); times = 1; } @@ -136,9 +135,12 @@ public void should_catch_sync_business_exception() throws NoSuchMethodException CompletableFuture future = filter.onFilter(invocation, FilterNode.EMPTY); - assertThat(future).hasFailedWithThrowableThat() - .isInstanceOf(RuntimeExceptionWithoutStackTrace.class) - .hasMessage("syncException"); + assertThat(future) + .failsWithin(Duration.ofSeconds(1)) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(RuntimeExceptionWithoutStackTrace.class) + .withMessage("org.apache.servicecomb.foundation.test.scaffolding.exception" + + ".RuntimeExceptionWithoutStackTrace: syncException"); } @Test @@ -165,9 +167,12 @@ public void should_catch_async_business_exception() throws NoSuchMethodException CompletableFuture future = filter.onFilter(invocation, FilterNode.EMPTY); - assertThat(future).hasFailedWithThrowableThat() - .isInstanceOf(RuntimeExceptionWithoutStackTrace.class) - .hasMessage("asyncException"); + assertThat(future) + .failsWithin(Duration.ofSeconds(1)) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(RuntimeExceptionWithoutStackTrace.class) + .withMessage("org.apache.servicecomb.foundation.test.scaffolding" + + ".exception.RuntimeExceptionWithoutStackTrace: asyncException"); } @Test @@ -179,16 +184,17 @@ public void should_unify_IllegalArgumentException_message_when_convert_exception result = new Object[] {1}; } }; - CompletableFuture future = filter.onFilter(invocation, FilterNode.EMPTY); - assertThat(future).hasFailedWithThrowableThat() - .isInstanceOf(IllegalArgumentException.class) - .hasMessage("wrong number of arguments"); + + assertThat(future) + .failsWithin(Duration.ofSeconds(1)) + .withThrowableOfType(ExecutionException.class) + .withCauseExactlyInstanceOf(IllegalArgumentException.class); InvocationException throwable = Exceptions - .convert(invocation, catchThrowable(() -> future.get()), INTERNAL_SERVER_ERROR); + .convert(invocation, catchThrowable(future::get), INTERNAL_SERVER_ERROR); assertThat(throwable).hasCauseInstanceOf(IllegalArgumentException.class); CommonExceptionData data = (CommonExceptionData) throwable.getErrorData(); assertThat(data.getMessage()).isEqualTo("Parameters not valid or types not match."); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilterTest.java b/core/src/test/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilterTest.java deleted file mode 100644 index 589df771ce4..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilterTest.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.core.filter.impl; - -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mocked; -import mockit.Verifications; - -public class SimpleLoadBalanceFilterTest { - SimpleLoadBalanceFilter filter = new SimpleLoadBalanceFilter(); - - @Injectable - Invocation invocation; - - @Injectable - Endpoint endpoint; - - @Mocked - DiscoveryContext discoveryContext; - - @Injectable - FilterNode nextNode; - - @Test - public void should_invoke_next_directly_when_invocation_already_has_endpoint() - throws ExecutionException, InterruptedException { - Response response = Response.ok("ok"); - new Expectations() { - { - invocation.getEndpoint(); - result = endpoint; - - nextNode.onFilter(invocation); - result = CompletableFuture.completedFuture(response); - } - }; - - Response result = filter.onFilter(invocation, nextNode).get(); - - assertThat(result).isSameAs(response); - new Verifications() { - { - discoveryContext.setInputParameters(invocation); - times = 0; - } - }; - } -} \ No newline at end of file diff --git a/core/src/test/java/org/apache/servicecomb/core/handler/impl/ErrorToProducerResponseConverter.java b/core/src/test/java/org/apache/servicecomb/core/handler/impl/ErrorToProducerResponseConverter.java deleted file mode 100644 index 373d7d82282..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/handler/impl/ErrorToProducerResponseConverter.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.core.handler.impl; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter; - -public class ErrorToProducerResponseConverter implements ExceptionToProducerResponseConverter { - @Override - public Class getExceptionClass() { - return Error.class; - } - - @Override - public Response convert(SwaggerInvocation swaggerInvocation, Error e) { - return Response.create(Status.OK, "response from error: " + e.getMessage()); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestProducerOperationHandler.java b/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestProducerOperationHandler.java deleted file mode 100644 index 104f57c6638..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestProducerOperationHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.core.handler.impl; - -import java.lang.reflect.InvocationTargetException; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Mocked; - -// test cases copied from delete class, this test case tests ExceptionToProducerResponseConverter -public class TestProducerOperationHandler { - ProducerOperationHandler handler = new ProducerOperationHandler(); - - @Test - public void processException_normal(@Mocked SwaggerInvocation invocation) { - Error error = new Error("abc"); - - Response response = handler.processException(invocation, error); - Assert.assertSame(Status.OK, response.getStatus()); - Assert.assertEquals("response from error: abc", response.getResult()); - } - - @Test - public void processException_InvocationTargetException(@Mocked SwaggerInvocation invocation) { - Error error = new Error("abc"); - InvocationTargetException targetException = new InvocationTargetException(error); - - Response response = handler.processException(invocation, error); - Assert.assertSame(Status.OK, response.getStatus()); - Assert.assertEquals("response from error: abc", response.getResult()); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestServiceProviderHandler.java b/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestServiceProviderHandler.java deleted file mode 100644 index 26cbf547052..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestServiceProviderHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.core.handler.impl; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -public class TestServiceProviderHandler { - - ProducerOperationHandler serviceProviderHandler = null; - - Invocation invocation = null; - - AsyncResponse asyncResp = null; - - OperationMeta OperationMeta = null; - - @Before - public void setUp() throws Exception { - serviceProviderHandler = new ProducerOperationHandler(); - invocation = Mockito.mock(Invocation.class); - asyncResp = Mockito.mock(AsyncResponse.class); - OperationMeta = Mockito.mock(OperationMeta.class); - } - - @After - public void tearDown() { - serviceProviderHandler = null; - invocation = null; - asyncResp = null; - OperationMeta = null; - } - - @Test - public void testHandle() { - boolean status = false; - try { - Assert.assertNotNull(serviceProviderHandler); - Mockito.when(invocation.getOperationMeta()).thenReturn(OperationMeta); - serviceProviderHandler.handle(invocation, asyncResp); - } catch (Exception e) { - e.printStackTrace(); - status = true; - } - Assert.assertFalse(status); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestSimpleLoadBalanceHandler.java b/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestSimpleLoadBalanceHandler.java deleted file mode 100644 index bcd2eec807b..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestSimpleLoadBalanceHandler.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * 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.core.handler.impl; - -import java.util.Collections; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mocked; - -public class TestSimpleLoadBalanceHandler { - SimpleLoadBalanceHandler handler; - - Map indexMap; - - @Mocked - Invocation invocation; - - VersionedCache instanceVersionedCache = new VersionedCache().data(Collections.emptyMap()).name("parent"); - - Response response; - - AsyncResponse ar = resp -> response = resp; - - SCBEngine scbEngine = SCBBootstrap.createSCBEngineForTest(); - - @Before - public void setUp() throws Exception { - ConfigUtil.installDynamicConfig(); - new Expectations(SPIServiceUtils.class) { - { - SPIServiceUtils.getSortedService(DiscoveryFilter.class); - result = Collections.emptyList(); - invocation.getConfigTransportName(); - result = ""; - invocation.getEndpoint(); - result = null; - } - }; - - new Expectations(DiscoveryManager.INSTANCE.getInstanceCacheManager()) { - { - DiscoveryManager.INSTANCE.getInstanceCacheManager() - .getOrCreateVersionedCache(anyString, anyString, anyString); - result = instanceVersionedCache; - } - }; - - handler = new SimpleLoadBalanceHandler(); - indexMap = Deencapsulation.getField(handler, "indexMap"); - } - - @After - public void teardown() { - scbEngine.destroy(); - ArchaiusUtils.resetConfig(); - } - - @Test - public void handle_emptyEndPoint() throws Exception { - handler.handle(invocation, ar); - - Throwable result = response.getResult(); - Assert.assertEquals( - "InvocationException: code=490;msg=CommonExceptionData [message=Unexpected consumer error, please check logs for details]", - result.getMessage()); - Assert.assertEquals("No available address found. microserviceName=null, version=null, discoveryGroupName=parent/", - result.getCause().getMessage()); - } - - @Test - public void handle(@Mocked Transport transport) throws Exception { - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("id"); - instance.getEndpoints().add("rest://localhost:8080"); - instance.getEndpoints().add("highway://localhost:8081"); - instanceVersionedCache.data(Collections.singletonMap("id", instance)).autoCacheVersion().name("vr"); - - new Expectations(scbEngine.getTransportManager()) { - { - SCBEngine.getInstance().getTransportManager().findTransport(anyString); - result = transport; - invocation.getConfigTransportName(); - result = ""; - } - }; - - handler.handle(invocation, ar); - AtomicInteger idx = indexMap.values().iterator().next(); - Assert.assertEquals(1, idx.get()); - - handler.handle(invocation, ar); - Assert.assertEquals(2, idx.get()); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestTransportClientHandler.java b/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestTransportClientHandler.java deleted file mode 100644 index 60209679996..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/handler/impl/TestTransportClientHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.core.handler.impl; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.Before; -import org.junit.Test; - -public class TestTransportClientHandler { - - private final Endpoint endpoint = mock(Endpoint.class); - - private final TransportClientHandler transportClientHandler = TransportClientHandler.INSTANCE; - - private final Invocation invocation = mock(Invocation.class); - - private final AsyncResponse asyncResp = mock(AsyncResponse.class); - - private final Transport transport = mock(Transport.class); - - @Before - public void setUp() throws Exception { - when(transport.getEndpoint()).thenReturn(endpoint); - when(endpoint.getEndpoint()).thenReturn("rest://localhost:8080"); - } - - @Test - public void test() throws Exception { - when(invocation.getTransport()).thenReturn(transport); - when(invocation.getEndpoint()).thenReturn(endpoint); - transportClientHandler.handle(invocation, asyncResp); - - verify(transport).send(invocation, asyncResp); - } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java b/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java index f1d3ef76d72..e2e3b2c421d 100644 --- a/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/invocation/ProducerInvocationFlowTest.java @@ -20,9 +20,12 @@ import static java.util.concurrent.CompletableFuture.completedFuture; import static org.assertj.core.api.Assertions.assertThat; +import java.util.concurrent.CompletableFuture; + import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.exception.Exceptions; +import org.apache.servicecomb.core.filter.AbstractFilter; import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; @@ -47,7 +50,7 @@ protected Invocation sendCreateInvocationException(Throwable throwable) { } @Override - protected void sendResponse(Invocation invocation, Response response) { + protected void endResponse(Invocation invocation, Response response) { sendInvocation = invocation; } } @@ -79,7 +82,7 @@ public void should_send_exception_response_when_failed_to_create_invocation() { private void mockFilterChain() { new Expectations() { { - microserviceMeta.getFilterChain(); + microserviceMeta.getProviderFilterChain(); result = filterNode; } }; @@ -94,7 +97,7 @@ public void should_start_invocation_when_succeed_to_create_invocation() { new Verifications() { { - invocation.onStart((HttpServletRequestEx) any, anyLong); + invocation.onStart((HttpServletRequestEx) any); times = 1; } }; @@ -126,8 +129,16 @@ public void should_finish_invocation_when_invocation_success() { } private void mockInvocationFailed() { - filterNode = new FilterNode((_invocation, _node) -> { - throw new RuntimeExceptionWithoutStackTrace(); + filterNode = new FilterNode(new AbstractFilter() { + @Override + public String getName() { + return "test"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + throw new RuntimeExceptionWithoutStackTrace(); + } }); mockFilterChain(); } @@ -156,4 +167,4 @@ public void should_finish_invocation_when_invocation_fail() { } }; } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/invocation/TestInvocationStageTrace.java b/core/src/test/java/org/apache/servicecomb/core/invocation/TestInvocationStageTrace.java index 91c7dd9c2e5..5b9c7040caa 100644 --- a/core/src/test/java/org/apache/servicecomb/core/invocation/TestInvocationStageTrace.java +++ b/core/src/test/java/org/apache/servicecomb/core/invocation/TestInvocationStageTrace.java @@ -24,9 +24,9 @@ import org.apache.servicecomb.core.definition.InvocationRuntimeType; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import mockit.Mock; import mockit.MockUp; @@ -68,51 +68,34 @@ public void consumer() { invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, args); stageTrace = new InvocationStageTrace(invocation); - stageTrace.start(1); + stageTrace.startCreateInvocation(1); nanoTime = 2; - stageTrace.startHandlersRequest(); + stageTrace.finishCreateInvocation(); + stageTrace.startConsumerConnection(); nanoTime = 3; - stageTrace.startClientFiltersRequest(); + stageTrace.finishConsumerConnection(); + stageTrace.startConsumerEncodeRequest(); nanoTime = 4; - stageTrace.startGetConnection(); - stageTrace.startSend(); + stageTrace.finishConsumerEncodeRequest(); + stageTrace.startConsumerSendRequest(); nanoTime = 5; - stageTrace.finishGetConnection(); - stageTrace.finishWriteToBuffer(6); + stageTrace.finishConsumerSendRequest(); + stageTrace.startWaitResponse(); + nanoTime = 6; + stageTrace.finishWaitResponse(); + stageTrace.startConsumerDecodeResponse(); nanoTime = 7; - stageTrace.finishReceiveResponse(); - nanoTime = 8; - stageTrace.startClientFiltersResponse(); - nanoTime = 9; - stageTrace.finishClientFiltersResponse(); - nanoTime = 10; - stageTrace.finishHandlersResponse(); - nanoTime = 11; + stageTrace.finishConsumerDecodeResponse(); + stageTrace.finish(); - Assert.assertEquals(1, stageTrace.getStart()); - Assert.assertEquals(2, stageTrace.getStartHandlersRequest()); - Assert.assertEquals(3, stageTrace.getStartClientFiltersRequest()); - Assert.assertEquals(4, stageTrace.getStartSend()); - Assert.assertEquals(5, stageTrace.getFinishGetConnection()); - Assert.assertEquals(6, stageTrace.getFinishWriteToBuffer()); - Assert.assertEquals(7, stageTrace.getFinishReceiveResponse()); - Assert.assertEquals(8, stageTrace.getStartClientFiltersResponse()); - Assert.assertEquals(9, stageTrace.getFinishClientFiltersResponse()); - Assert.assertEquals(10, stageTrace.getFinishHandlersResponse()); - Assert.assertEquals(11, stageTrace.getFinish()); - - Assert.assertEquals(1f, stageTrace.calcInvocationPrepareTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcHandlersRequestTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcClientFiltersRequestTime(), 0.1f); - Assert.assertEquals(2f, stageTrace.calcSendRequestTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcGetConnectionTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcWriteToBufferTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcReceiveResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcWakeConsumer(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcClientFiltersResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcHandlersResponseTime(), 0.1f); - Assert.assertEquals(10f, stageTrace.calcTotalTime(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcPrepare(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConnection(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConsumerEncodeRequest(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConsumerSendRequest(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcWait(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConsumerDecodeResponse(), 0.1f); + Assertions.assertEquals(6f, stageTrace.calcTotal(), 0.1f); } @Test @@ -120,116 +103,81 @@ public void producer() { invocation = new Invocation(endpoint, operationMeta, args); stageTrace = new InvocationStageTrace(invocation); - stageTrace.start(1); + stageTrace.startCreateInvocation(1); nanoTime = 2; - stageTrace.startSchedule(); + stageTrace.finishCreateInvocation(); + stageTrace.startProviderDecodeRequest(); nanoTime = 3; - stageTrace.startExecution(); + stageTrace.finishProviderDecodeRequest(); + stageTrace.startProviderQueue(); nanoTime = 4; - stageTrace.startServerFiltersRequest(); + stageTrace.finishProviderQueue(); + stageTrace.startBusinessExecute(); nanoTime = 5; - stageTrace.startHandlersRequest(); + stageTrace.finishBusinessExecute(); + stageTrace.startProviderEncodeResponse(); nanoTime = 6; - stageTrace.startBusinessMethod(); + stageTrace.finishProviderEncodeResponse(); + stageTrace.startProviderSendResponse(); nanoTime = 7; - stageTrace.finishBusiness(); - nanoTime = 8; - stageTrace.finishHandlersResponse(); - nanoTime = 9; - stageTrace.finishServerFiltersResponse(); - nanoTime = 10; + stageTrace.finishProviderSendResponse(); + stageTrace.finish(); - Assert.assertEquals(1, stageTrace.getStart()); - Assert.assertEquals(2, stageTrace.getStartSchedule()); - Assert.assertEquals(3, stageTrace.getStartExecution()); - Assert.assertEquals(4, stageTrace.getStartServerFiltersRequest()); - Assert.assertEquals(5, stageTrace.getStartHandlersRequest()); - Assert.assertEquals(6, stageTrace.getStartBusinessMethod()); - Assert.assertEquals(7, stageTrace.getFinishBusiness()); - Assert.assertEquals(8, stageTrace.getFinishHandlersResponse()); - Assert.assertEquals(9, stageTrace.getFinishServerFiltersResponse()); - Assert.assertEquals(10, stageTrace.getFinish()); - - Assert.assertEquals(1f, stageTrace.calcInvocationPrepareTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcThreadPoolQueueTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcServerFiltersRequestTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcHandlersRequestTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcBusinessTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcHandlersResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcServerFiltersResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcSendResponseTime(), 0.1f); - Assert.assertEquals(9f, stageTrace.calcTotalTime(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcPrepare(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcQueue(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcProviderDecodeRequest(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcProviderEncodeResponse(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcBusinessExecute(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcProviderSendResponse(), 0.1f); + Assertions.assertEquals(6f, stageTrace.calcTotal(), 0.1f); } @Test public void edge() { invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, args); stageTrace = new InvocationStageTrace(invocation); - invocation.setEdge(true); + invocation.setEdge(); - stageTrace.start(1); + stageTrace.startCreateInvocation(1); nanoTime = 2; - stageTrace.startSchedule(); + stageTrace.finishCreateInvocation(); + stageTrace.startProviderDecodeRequest(); nanoTime = 3; - stageTrace.startExecution(); + stageTrace.finishProviderDecodeRequest(); + stageTrace.startConsumerConnection(); nanoTime = 4; - stageTrace.startServerFiltersRequest(); + stageTrace.finishConsumerConnection(); + stageTrace.startConsumerEncodeRequest(); nanoTime = 5; - stageTrace.startHandlersRequest(); + stageTrace.finishConsumerEncodeRequest(); + stageTrace.startConsumerSendRequest(); nanoTime = 6; - stageTrace.startClientFiltersRequest(); + stageTrace.finishConsumerSendRequest(); + stageTrace.startWaitResponse(); nanoTime = 7; - stageTrace.startGetConnection(); - stageTrace.startSend(); + stageTrace.finishWaitResponse(); + stageTrace.startConsumerDecodeResponse(); nanoTime = 8; - stageTrace.finishGetConnection(); - stageTrace.finishWriteToBuffer(9); + stageTrace.finishConsumerDecodeResponse(); + stageTrace.startProviderEncodeResponse(); nanoTime = 10; - stageTrace.finishReceiveResponse(); + stageTrace.finishProviderEncodeResponse(); + stageTrace.startProviderSendResponse(); nanoTime = 11; - stageTrace.startClientFiltersResponse(); - nanoTime = 12; - stageTrace.finishClientFiltersResponse(); - nanoTime = 13; - stageTrace.finishHandlersResponse(); - nanoTime = 14; - stageTrace.finishServerFiltersResponse(); - nanoTime = 15; + stageTrace.finishProviderSendResponse(); stageTrace.finish(); - Assert.assertEquals(1, stageTrace.getStart()); - Assert.assertEquals(2, stageTrace.getStartSchedule()); - Assert.assertEquals(3, stageTrace.getStartExecution()); - Assert.assertEquals(4, stageTrace.getStartServerFiltersRequest()); - Assert.assertEquals(5, stageTrace.getStartHandlersRequest()); - Assert.assertEquals(6, stageTrace.getStartClientFiltersRequest()); - Assert.assertEquals(7, stageTrace.getStartSend()); - Assert.assertEquals(8, stageTrace.getFinishGetConnection()); - Assert.assertEquals(9, stageTrace.getFinishWriteToBuffer()); - Assert.assertEquals(10, stageTrace.getFinishReceiveResponse()); - Assert.assertEquals(11, stageTrace.getStartClientFiltersResponse()); - Assert.assertEquals(12, stageTrace.getFinishClientFiltersResponse()); - Assert.assertEquals(13, stageTrace.getFinishHandlersResponse()); - Assert.assertEquals(14, stageTrace.getFinishServerFiltersResponse()); - Assert.assertEquals(15, stageTrace.getFinish()); - - Assert.assertEquals(1f, stageTrace.calcInvocationPrepareTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcThreadPoolQueueTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcServerFiltersRequestTime(), 0.1f); - - Assert.assertEquals(1f, stageTrace.calcHandlersRequestTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcClientFiltersRequestTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcGetConnectionTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcWriteToBufferTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcReceiveResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcWakeConsumer(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcClientFiltersResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcHandlersResponseTime(), 0.1f); - - Assert.assertEquals(1f, stageTrace.calcServerFiltersResponseTime(), 0.1f); - Assert.assertEquals(1f, stageTrace.calcSendResponseTime(), 0.1f); - - Assert.assertEquals(14f, stageTrace.calcTotalTime(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcPrepare(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConnection(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConsumerEncodeRequest(), 0.1f); + + Assertions.assertEquals(1f, stageTrace.calcConsumerSendRequest(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcWait(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcConsumerDecodeResponse(), 0.1f); + Assertions.assertEquals(2f, stageTrace.calcProviderEncodeResponse(), 0.1f); + Assertions.assertEquals(1f, stageTrace.calcProviderSendResponse(), 0.1f); + + Assertions.assertEquals(10f, stageTrace.calcTotal(), 0.1f); } } 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 aa9c3a8c672..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; @@ -34,7 +33,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mockito; -import io.swagger.models.Swagger; +import io.swagger.v3.oas.models.OpenAPI; public class EndpointTest { public interface TestSchema { @@ -44,30 +43,12 @@ public interface TestSchema { @Test void should_ignore_endpoint_when_generate_swagger() { SwaggerGenerator generator = SwaggerGenerator.create(TestSchema.class); - generator.getSwaggerGeneratorFeature() - .setExtJavaInterfaceInVendor(false) - .setExtJavaClassInVendor(false); - Swagger swagger = generator.generate(); + OpenAPI swagger = generator.generate(); - assertThat(SwaggerUtils.swaggerToString(swagger)) - .isEqualTo("---\n" - + "swagger: \"2.0\"\n" - + "info:\n" - + " version: \"1.0.0\"\n" - + " title: \"swagger definition for org.apache.servicecomb.core.invocation.endpoint.EndpointTest$TestSchema\"\n" - + "basePath: \"/TestSchema\"\n" - + "consumes:\n" - + "- \"application/json\"\n" - + "produces:\n" - + "- \"application/json\"\n" - + "paths:\n" - + " /say:\n" - + " post:\n" - + " operationId: \"say\"\n" - + " parameters: []\n" - + " responses:\n" - + " \"200\":\n" - + " description: \"response of 200\"\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 @@ -93,4 +74,4 @@ void should_set_endpoint_to_invocation_when_map_arguments() { assertThat(holder.value).isSameAs(endpoint); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtilsTest.java b/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtilsTest.java index 2338cca0c09..43cc21ba478 100644 --- a/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtilsTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/invocation/endpoint/EndpointUtilsTest.java @@ -117,4 +117,4 @@ void should_not_change() { assertThat(formatFromUri("abc://host:123?q1=v1")).isEqualTo("abc://host:123?q1=v1"); } } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategyTest.java b/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategyTest.java index 5aa99147388..58de7e9d2a0 100644 --- a/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategyTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/PassingTimeStrategyTest.java @@ -32,17 +32,6 @@ class PassingTimeStrategyTest { PassingTimeStrategy strategy = new PassingTimeStrategy(); - @Test - void should_init_when_start_as_first_chain_node() { - Invocation invocation = new Invocation(); - invocation.getInvocationStageTrace().setStartTimeMillis(10); - - strategy.start(invocation); - - assertThat(invocation.getContext(CHAIN_START_TIME)).isEqualTo("10"); - assertThat(invocation.getLocalContext(CHAIN_START_TIME)).isEqualTo(10L); - } - @Test void should_init_when_start_as_first_node_of_a_process_but_not_first_of_a_chain() { Invocation invocation = new Invocation(); @@ -75,4 +64,4 @@ void should_calc_elapsed_time_as_passing_time() { assertThat(elapsedNanoTime).isEqualTo(TimeUnit.MILLISECONDS.toNanos(90)); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategyTest.java b/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategyTest.java index e348f10670c..05d744e15db 100644 --- a/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategyTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/invocation/timeout/ProcessingTimeStrategyTest.java @@ -31,17 +31,6 @@ class ProcessingTimeStrategyTest { ProcessingTimeStrategy strategy = new ProcessingTimeStrategy(); - @Test - void should_init_when_start_as_first_chain_node() { - Invocation invocation = new Invocation(); - invocation.getInvocationStageTrace().start(10); - - strategy.start(invocation); - - assertThat(invocation.getLocalContext(CHAIN_START_TIME)).isEqualTo(10L); - assertThat(invocation.getLocalContext(CHAIN_PROCESSING)).isEqualTo(0L); - } - @Test void should_do_nothing_when_not_first_node_of_a_process() { Invocation invocation = new Invocation(); @@ -86,4 +75,4 @@ public void checkTimeout(Invocation invocation) { assertThat(invocation.getContext(CHAIN_PROCESSING)).isEqualTo("60"); } -} \ No newline at end of file +} diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestConsumerProviderManager.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestConsumerProviderManager.java deleted file mode 100644 index 2d877a647aa..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestConsumerProviderManager.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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.core.provider.consumer; - -public class TestConsumerProviderManager { -// @Before -// public void setUp() throws Exception { -// ArchaiusUtils.resetConfig(); -// } -// -// @After -// public void tearDown() throws Exception { -// ArchaiusUtils.resetConfig(); -// } -// -// @Test -// public void allowedNoProvider(@Mocked ConsumerSchemaFactory consumerSchemaFactory) { -// AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); -// context.getBeanFactory().registerSingleton(consumerSchemaFactory.getClass().getName(), consumerSchemaFactory); -// context.register(ConsumerProviderManager.class); -// // must not throw exception -// context.refresh(); -// -// context.close(); -// } -// -// private ReferenceConfig mockCreateReferenceConfig() { -// EventBus eventBus = new EventBus(); -// AppManager appManager = new AppManager(eventBus); -// -// ConsumerProviderManager consumerProviderManager = new ConsumerProviderManager(); -// consumerProviderManager.setAppManager(appManager); -// -// new Expectations(RegistryUtils.class) { -// { -// RegistryUtils.findServiceInstances(anyString, anyString, DefinitionConst.VERSION_RULE_ALL, null); -// result = Collections.emptyList(); -// } -// }; -// -// new MockUp() { -// @Mock -// MicroserviceVersion getLatestMicroserviceVersion() { -// return Mockito.mock(MicroserviceVersion.class); -// } -// }; -// return consumerProviderManager.createReferenceConfig("app:ms"); -// } -// -// @Test -// public void createReferenceConfig_default() { -// ReferenceConfig referenceConfig = mockCreateReferenceConfig(); -// -// Assert.assertEquals("app", referenceConfig.getMicroserviceVersionRule().getAppId()); -// Assert.assertEquals("app:ms", referenceConfig.getMicroserviceVersionRule().getMicroserviceName()); -// Assert.assertEquals("0.0.0.0+", referenceConfig.getMicroserviceVersionRule().getVersionRule().getVersionRule()); -// Assert.assertEquals(Const.ANY_TRANSPORT, referenceConfig.getTransport()); -// } -// -// @Test -// public void createReferenceConfig_config() { -// ArchaiusUtils.setProperty("servicecomb.references.app:ms.version-rule", "1.0.0+"); -// ArchaiusUtils.setProperty("servicecomb.references.app:ms.transport", Const.RESTFUL); -// -// ReferenceConfig referenceConfig = mockCreateReferenceConfig(); -// -// Assert.assertEquals("app", referenceConfig.getMicroserviceVersionRule().getAppId()); -// Assert.assertEquals("app:ms", referenceConfig.getMicroserviceVersionRule().getMicroserviceName()); -// Assert.assertEquals("1.0.0.0+", referenceConfig.getMicroserviceVersionRule().getVersionRule().getVersionRule()); -// Assert.assertEquals(Const.RESTFUL, referenceConfig.getTransport()); -// } -// -// @Test -// public void createReferenceConfig_ProviderNotFound() { -// EventBus eventBus = new EventBus(); -// AppManager appManager = new AppManager(eventBus); -// -// ConsumerProviderManager consumerProviderManager = new ConsumerProviderManager(); -// consumerProviderManager.setAppManager(appManager); -// -// new Expectations(RegistryUtils.class) { -// { -// RegistryUtils.findServiceInstances(anyString, anyString, DefinitionConst.VERSION_RULE_ALL, null); -// result = Collections.emptyList(); -// } -// }; -// -// new MockUp() { -// @Mock -// String getAppId() { -// return "aId"; -// } -// -// @Mock -// String getMicroserviceName() { -// return "ms"; -// } -// }; -// -// try { -// consumerProviderManager.createReferenceConfig("app:ms"); -// fail("an IllegalStateException is expected!"); -// } catch (Exception e) { -// Assert.assertEquals(IllegalStateException.class, e.getClass()); -// Assert.assertEquals( -// "Probably invoke a service before it is registered, or no instance found for it, appId=aId, name=ms", -// e.getMessage()); -// e.printStackTrace(); -// } -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java index 10c56e161d9..3b3e56092c3 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestInvokerUtils.java @@ -17,197 +17,11 @@ package org.apache.servicecomb.core.provider.consumer; +import org.junit.jupiter.api.Test; + public class TestInvokerUtils { -// @Rule -// public ExpectedException expectedException = ExpectedException.none(); -// -// @Mocked -// ReferenceConfig referenceConfig; -// -// @Mocked -// SchemaMeta schemaMeta; -// -// @Mocked -// OperationMeta operationMeta; -// -// Invocation invocation; -// -// static Object invokeResult; -// -// SCBEngine scbEngine = new SCBEngine(); -// -// static long nanoTime = 1; -// -// @BeforeClass -// public static void classSetup() { -// new MockUp() { -// @Mock -// long nanoTime() { -// return nanoTime; -// } -// }; -// } -// -// @Before -// public void setup() { -// new MockUp() { -// @Mock -// SCBEngine getInstance() { -// return scbEngine; -// } -// }; -// scbEngine.setStatus(SCBStatus.UP); -// -// new Expectations() { -// { -// operationMeta.getSchemaMeta(); -// result = schemaMeta; -// schemaMeta.getConsumerHandlerChain(); -// result = Arrays.asList((Handler) (i, ar) -> { -// System.out.println(invokeResult); -// ar.success(invokeResult); -// }); -// } -// }; -// invocation = new Invocation(referenceConfig, operationMeta, new Object[] {}); -// } -// -// @Test -// public void testSyncInvokeInvocationWithException() { -// Invocation invocation = Mockito.mock(Invocation.class); -// InvocationStageTrace stageTrace = new InvocationStageTrace(invocation); -// Mockito.when(invocation.getInvocationStageTrace()).thenReturn(stageTrace); -// -// Response response = Mockito.mock(Response.class); -// new MockUp() { -// @Mock -// public Response waitResponse() { -// return response; -// } -// }; -// Mockito.when(response.isSuccessed()).thenReturn(false); -// OperationMeta operationMeta = Mockito.mock(OperationMeta.class); -// Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); -// Mockito.when(operationMeta.getMicroserviceQualifiedName()).thenReturn("test"); -// -// expectedException.expect(InvocationException.class); -// expectedException.expect(Matchers.hasProperty("statusCode", Matchers.is(490))); -// InvokerUtils.syncInvoke(invocation); -// } -// -// @Test -// public void testSyncInvokeNormal() { -// invokeResult = 1; -// Assert.assertEquals(1, (int) InvokerUtils.syncInvoke(invocation)); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getStart()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getStartHandlersRequest()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getFinishHandlersResponse()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getFinish()); -// } -// -// @Test -// public void testReactiveInvoke(@Mocked InvocationContext parentContext, @Mocked Response response) { -// new MockUp(invocation) { -// @Mock -// InvocationContext getParentContext() { -// return parentContext; -// } -// -// @Mock -// void next(AsyncResponse asyncResp) { -// asyncResp.handle(response); -// } -// }; -// -// Holder holder = new Holder<>(); -// InvokerUtils.reactiveInvoke(invocation, ar -> holder.value = ContextUtils.getInvocationContext()); -// -// Assert.assertNull(ContextUtils.getInvocationContext()); -// Assert.assertSame(parentContext, holder.value); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getStart()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getStartHandlersRequest()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getFinishHandlersResponse()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getFinish()); -// } -// -// @Test -// public void reactiveInvokeException() { -// new MockUp(invocation) { -// @Mock -// void next(AsyncResponse asyncResp) { -// throw new RuntimeExceptionWithoutStackTrace(); -// } -// }; -// -// Holder holder = new Holder<>(); -// InvokerUtils.reactiveInvoke(invocation, ar -> holder.value = ar); -// -// Assert.assertFalse(holder.value.isSuccessed()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getStart()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getStartHandlersRequest()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getFinishHandlersResponse()); -// Assert.assertEquals(1, invocation.getInvocationStageTrace().getFinish()); -// } -// -// @SuppressWarnings("deprecation") -// @Test -// public void invoke() { -// new MockUp() { -// @Mock -// Object syncInvoke(Invocation invocation) { -// return 1; -// } -// }; -// -// Assert.assertEquals(1, InvokerUtils.invoke(null)); -// } -// -// @Test -// public void testSyncInvoke_4param_NotReady() { -// scbEngine.setStatus(SCBStatus.DOWN); -// -// expectedException.expect(InvocationException.class); -// expectedException.expectMessage( -// Matchers -// .is("InvocationException: code=503;msg=CommonExceptionData [message=The request is rejected. Cannot process the request due to STATUS = DOWN]")); -// InvokerUtils.syncInvoke("ms", "schemaId", "opName", null); -// } -// -// @Test -// public void testSyncInvoke_6param_NotReady() { -// scbEngine.setStatus(SCBStatus.DOWN); -// -// expectedException.expect(InvocationException.class); -// expectedException.expectMessage( -// Matchers -// .is("InvocationException: code=503;msg=CommonExceptionData [message=The request is rejected. Cannot process the request due to STATUS = DOWN]")); -// -// InvokerUtils.syncInvoke("ms", "latest", "rest", "schemaId", "opName", null); -// } -// -// @Test -// public void testSyncInvokeReady(@Injectable ConsumerProviderManager consumerProviderManager, -// @Injectable Invocation invocation) { -// scbEngine.setConsumerProviderManager(consumerProviderManager); -// -// new Expectations(InvocationFactory.class) { -// { -// InvocationFactory.forConsumer((ReferenceConfig) any, (SchemaMeta) any, (String) any, (Object[]) any); -// result = invocation; -// } -// }; -// new Expectations(InvokerUtils.class) { -// { -// InvokerUtils.syncInvoke(invocation); -// result = "ok"; -// } -// }; -// Object result1 = InvokerUtils.syncInvoke("ms", "schemaId", "opName", null); -// Assert.assertEquals("ok", result1); -// -// Object result2 = InvokerUtils.syncInvoke("ms", "latest", "rest", "schemaId", "opName", null); -// Assert.assertEquals("ok", result2); -// -// CseContext.getInstance().setConsumerProviderManager(null); -// } + @Test + public void testRetryInvocation503() { + + } } diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfig.java b/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfig.java deleted file mode 100644 index 2504228cabf..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/provider/consumer/TestReferenceConfig.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.core.provider.consumer; - -public class TestReferenceConfig { -// @Test -// public void constructNoParam(@Mocked MicroserviceMeta microserviceMeta, -// @Mocked MicroserviceVersionMeta microserviceVersionMeta, -// @Mocked MicroserviceVersionRule microserviceVersionRule) { -// new Expectations() { -// { -// microserviceVersionMeta.getMicroserviceMeta(); -// result = microserviceMeta; -// microserviceVersionRule.getLatestMicroserviceVersion(); -// result = microserviceVersionMeta; -// } -// }; -// String transport = Const.ANY_TRANSPORT; -// -// ReferenceConfig referenceConfig = new ReferenceConfig(); -// referenceConfig.setMicroserviceVersionRule(microserviceVersionRule); -// referenceConfig.setTransport(transport); -// -// Assert.assertSame(microserviceMeta, referenceConfig.getMicroserviceMeta()); -// Assert.assertSame(microserviceVersionRule, referenceConfig.getMicroserviceVersionRule()); -// Assert.assertSame(transport, referenceConfig.getTransport()); -// } -// -// @Test -// public void constructWithParam(@Mocked AppManager appManager, -// @Mocked MicroserviceMeta microserviceMeta, -// @Mocked MicroserviceVersionRule microserviceVersionRule, -// @Mocked MicroserviceVersionMeta microserviceVersionMeta) { -// String microserviceName = "ms"; -// String transport = Const.ANY_TRANSPORT; -// new Expectations() { -// { -// appManager.getOrCreateMicroserviceVersionRule(anyString, anyString, anyString); -// result = microserviceVersionRule; -// microserviceVersionMeta.getMicroserviceMeta(); -// result = microserviceMeta; -// microserviceVersionRule.getLatestMicroserviceVersion(); -// result = microserviceVersionMeta; -// } -// }; -// -// ReferenceConfig referenceConfig = new ReferenceConfig(appManager, microserviceName, -// DefinitionConst.VERSION_RULE_LATEST, -// transport); -// Assert.assertSame(microserviceMeta, referenceConfig.getMicroserviceMeta()); -// Assert.assertSame(microserviceVersionRule, referenceConfig.getMicroserviceVersionRule()); -// Assert.assertSame(transport, referenceConfig.getTransport()); -// } -// -// @Test -// public void unifyVersionRule(@Mocked MicroserviceVersionMeta microserviceVersionMeta) { -// String microserviceName = "app:ms"; -// String transport = Const.ANY_TRANSPORT; -// -// new Expectations(RegistryUtils.class) { -// { -// RegistryUtils.findServiceInstances(anyString, anyString, anyString, anyString); -// result = Collections.emptyList(); -// } -// }; -// AppManager appManager = new AppManager(new EventBus()); -// -// ReferenceConfig referenceConfig = new ReferenceConfig(appManager, microserviceName, -// "0+", -// transport); -// Assert.assertEquals("0.0.0.0+", referenceConfig.getVersionRule()); -// -// referenceConfig = new ReferenceConfig(appManager, microserviceName, -// "1.0.0+", -// transport); -// Assert.assertEquals("1.0.0.0+", referenceConfig.getVersionRule()); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerBootListener.java b/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerBootListener.java index a61b6f40829..e327759eff2 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerBootListener.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerBootListener.java @@ -17,26 +17,18 @@ package org.apache.servicecomb.core.provider.producer; -import java.io.Closeable; import java.util.Arrays; import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.core.BootListener.BootEvent; import org.apache.servicecomb.core.BootListener.EventType; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.MicroserviceMeta; import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.core.executor.GroupExecutor; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestProducerBootListener { ProducerBootListener producerBootListener = new ProducerBootListener(); @@ -51,57 +43,15 @@ public void onBootEvent_notClose() { } @Test - public void onBootEvent_close(@Mocked SCBEngine scbEngine, @Mocked MicroserviceMeta microserviceMeta, - @Mocked OperationMeta op1, - @Mocked OperationMeta op2, @Mocked GroupExecutor closeable) { - AtomicInteger count = new AtomicInteger(); - ExecutorService executorService = new MockUp() { - @Mock - void shutdown() { - count.incrementAndGet(); - } - }.getMockInstance(); - new MockUp(closeable) { - @Mock - void close() { - count.incrementAndGet(); - } - }; - new Expectations() { - { - scbEngine.getProducerMicroserviceMeta(); - result = microserviceMeta; - microserviceMeta.getOperations(); - result = Arrays.asList(op1, op2); - op1.getExecutor(); - result = executorService; - op2.getExecutor(); - result = closeable; - } - }; - BootEvent event = new BootEvent(); - event.setScbEngine(scbEngine); - event.setEventType(EventType.AFTER_CLOSE); - - producerBootListener.onBootEvent(event); + public void onBootEvent_close_unknown() { + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); + OperationMeta op = Mockito.mock(OperationMeta.class); - Assert.assertEquals(2, count.get()); - } - - @Test - public void onBootEvent_close_unknown(@Mocked SCBEngine scbEngine, @Mocked MicroserviceMeta microserviceMeta, - @Mocked OperationMeta op1) { Executor executor = new UnCloseableExecutor(); - new Expectations() { - { - scbEngine.getProducerMicroserviceMeta(); - result = microserviceMeta; - microserviceMeta.getOperations(); - result = Arrays.asList(op1); - op1.getExecutor(); - result = executor; - } - }; + Mockito.when(scbEngine.getProducerMicroserviceMeta()).thenReturn(microserviceMeta); + Mockito.when(microserviceMeta.getOperations()).thenReturn(Arrays.asList(op)); + Mockito.when(op.getExecutor()).thenReturn(executor); try (LogCollector logCollector = new LogCollector()) { BootEvent event = new BootEvent(); @@ -110,10 +60,10 @@ public void onBootEvent_close_unknown(@Mocked SCBEngine scbEngine, @Mocked Micro producerBootListener.onBootEvent(event); - Assert.assertEquals( + Assertions.assertEquals( "Executor org.apache.servicecomb.core.provider.producer.TestProducerBootListener$UnCloseableExecutor " + "do not support close or shutdown, it may block service shutdown.", - logCollector.getLastEvents().getMessage()); + logCollector.getLastEvents().getMessage().getFormattedMessage()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerMeta.java b/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerMeta.java index 3d4587178eb..1c481c7189b 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerMeta.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerMeta.java @@ -16,25 +16,25 @@ */ package org.apache.servicecomb.core.provider.producer; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestProducerMeta { @Test public void test1() { Object instance = new Object(); ProducerMeta meta = new ProducerMeta("id", instance); - Assert.assertEquals("id", meta.getSchemaId()); - Assert.assertEquals(instance, meta.getInstance()); + Assertions.assertEquals("id", meta.getSchemaId()); + Assertions.assertEquals(instance, meta.getInstance()); } @Test public void test2() { ProducerMeta meta = new ProducerMeta(); meta.setSchemaId("id1"); - Assert.assertEquals("id1", meta.getSchemaId()); + Assertions.assertEquals("id1", meta.getSchemaId()); meta.setInstance(1); - Assert.assertEquals(1, meta.getInstance()); + Assertions.assertEquals(1, meta.getInstance()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerProviderManager.java b/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerProviderManager.java index 6025b3a9b1c..f36229b0eea 100644 --- a/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerProviderManager.java +++ b/core/src/test/java/org/apache/servicecomb/core/provider/producer/TestProducerProviderManager.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.core.provider.producer; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class TestProducerProviderManager { @Test diff --git a/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestEndpointDiscoveryFilter.java b/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestEndpointDiscoveryFilter.java index 9afa69056d0..cc79ba2f684 100644 --- a/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestEndpointDiscoveryFilter.java +++ b/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestEndpointDiscoveryFilter.java @@ -17,88 +17,78 @@ package org.apache.servicecomb.core.registry.discovery; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.core.transport.TransportManager; import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Mocked; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestEndpointDiscoveryFilter { EndpointDiscoveryFilter filter = new EndpointDiscoveryFilter(); DiscoveryContext context = new DiscoveryContext(); - @Mocked Invocation invocation; - SCBEngine scbEngine; - - @Before + @BeforeEach public void setup() { - ArchaiusUtils.resetConfig(); - ConfigUtil.installDynamicConfig(); - context.setInputParameters(invocation); - scbEngine = SCBBootstrap.createSCBEngineForTest(); + } - @After + @AfterEach public void teardown() { - scbEngine.destroy(); - ArchaiusUtils.resetConfig(); } @Test public void getOrder() { - Assert.assertEquals(Short.MAX_VALUE, filter.getOrder()); + Assertions.assertEquals(Short.MAX_VALUE, filter.getOrder()); } @Test public void getTransportName() { - new Expectations() { - { - invocation.getConfigTransportName(); - result = Const.RESTFUL; - } - }; - - Assert.assertEquals(Const.RESTFUL, filter.findTransportName(context, null)); + invocation = Mockito.mock(Invocation.class); + Mockito.when(invocation.getConfigTransportName()).thenReturn(CoreConst.RESTFUL); + context.setInputParameters(invocation); + Assertions.assertEquals(CoreConst.RESTFUL, filter.findTransportName(context, null)); } @Test public void createEndpointNullTransport() { - Assert.assertNull(filter.createEndpoint(null, Const.RESTFUL, "", null)); + TransportManager transportManager = Mockito.mock(TransportManager.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + Mockito.when(transportManager.findTransport(CoreConst.RESTFUL)).thenReturn(null); + filter.setScbEngine(scbEngine); + Assertions.assertNull(filter.createEndpoint(null, CoreConst.RESTFUL, "", null)); } @Test - public void createEndpointNormal(@Mocked Transport transport, @Mocked MicroserviceInstance instance) { + public void createEndpointNormal() { + Transport transport = Mockito.mock(Transport.class); + StatefulDiscoveryInstance instance = Mockito.mock(StatefulDiscoveryInstance.class); + TransportManager transportManager = Mockito.mock(TransportManager.class); + String endpoint = "rest://ip:port"; Object address = new Object(); - new Expectations(scbEngine.getTransportManager()) { - { - scbEngine.getTransportManager().findTransport(Const.RESTFUL); - result = transport; - transport.parseAddress(endpoint); - result = address; - } - }; - - Endpoint ep = (Endpoint) filter.createEndpoint(null, Const.RESTFUL, endpoint, instance); - Assert.assertSame(transport, ep.getTransport()); - Assert.assertSame(address, ep.getAddress()); - Assert.assertSame(instance, ep.getMicroserviceInstance()); - Assert.assertEquals(endpoint, ep.getEndpoint()); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + Mockito.when(transportManager.findTransport(CoreConst.RESTFUL)).thenReturn(transport); + Mockito.when(transport.parseAddress(endpoint)).thenReturn(address); + filter.setScbEngine(scbEngine); + + Endpoint ep = (Endpoint) filter.createEndpoint(null, CoreConst.RESTFUL, endpoint, instance); + Assertions.assertSame(transport, ep.getTransport()); + Assertions.assertSame(address, ep.getAddress()); + Assertions.assertSame(instance, ep.getMicroserviceInstance()); + Assertions.assertEquals(endpoint, ep.getEndpoint()); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestOperationInstancesDiscoveryFilter.java b/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestOperationInstancesDiscoveryFilter.java deleted file mode 100644 index 54cd21eae70..00000000000 --- a/core/src/test/java/org/apache/servicecomb/core/registry/discovery/TestOperationInstancesDiscoveryFilter.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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.core.registry.discovery; - -public class TestOperationInstancesDiscoveryFilter { -// @SwaggerDefinition(basePath = "/v1") -// private static class V1_0_0 { -// @ApiOperation(value = "", httpMethod = "GET") -// public void add() { -// } -// } -// -// @SwaggerDefinition(basePath = "/v1") -// private static class V1_1_0 { -// @ApiOperation(value = "", httpMethod = "GET") -// public void add() { -// } -// -// @ApiOperation(value = "", httpMethod = "GET") -// public void dec() { -// } -// } -// -// OperationInstancesDiscoveryFilter filter = new OperationInstancesDiscoveryFilter(); -// -// DiscoveryContext context = new DiscoveryContext(); -// -// EventBus eventBus = new EventBus(); -// -// String appId = "app"; -// -// String microserviceName = "ms"; -// -// ServiceRegistry serviceRegistry = -// new LocalServiceRegistry(eventBus, ServiceRegistryConfig.INSTANCE, -// MicroserviceDefinition.create(appId, "self")); -// -// @Mocked -// ApplicationContext applicationContext; -// -// @Mocked -// Invocation invocation; -// -// OperationMeta latestOperationMeta; -// -// ConsumerSchemaFactory consumerSchemaFactory = new ConsumerSchemaFactory(); -// -// DiscoveryTreeNode result; -// -// @Before -// public void setup() { -// serviceRegistry.init(); -// BeanUtils.setContext(applicationContext); -// -// RegistryUtils.setServiceRegistry(serviceRegistry); -// } -// -// private void setupOnChange() { -// new Expectations(RegistryUtils.class) { -// { -// invocation.getOperationMeta(); -// result = latestOperationMeta; -// invocation.getMicroserviceQualifiedName(); -// result = latestOperationMeta.getMicroserviceQualifiedName(); -// } -// }; -// -// context.setInputParameters(invocation); -// } -// -// @After -// public void teardown() { -// RegistryUtils.setServiceRegistry(null); -// BeanUtils.setContext(null); -// CseContext.getInstance().setConsumerSchemaFactory(null); -// CseContext.getInstance().setSchemaListenerManager(null); -// } -// -// private MicroserviceInstance createInstance(String serviceId) { -// MicroserviceInstance instance = new MicroserviceInstance(); -// instance.setInstanceId(UUID.randomUUID().toString()); -// instance.setServiceId(serviceId); -// return instance; -// } -// -// private Microservice regMicroservice(String serviceId, String version, Class schemaCls, int instanceCount) { -// String schemaId = "sid"; -// -// Microservice microservice = new Microservice(); -// microservice.setServiceId(serviceId); -// microservice.setAppId(appId); -// microservice.setServiceName(microserviceName); -// microservice.setVersion(version); -// microservice.setSchemas(Arrays.asList(schemaId)); -// serviceRegistry.getServiceRegistryClient().registerMicroservice(microservice); -// -// String schemaContent = SwaggerUtils.swaggerToString(SwaggerGenerator.generate(schemaCls)); -// serviceRegistry.getServiceRegistryClient().registerSchema(serviceId, schemaId, schemaContent); -// -// for (int idx = 0; idx < instanceCount; idx++) { -// MicroserviceInstance instance = createInstance(serviceId); -// serviceRegistry.getServiceRegistryClient().registerMicroserviceInstance(instance); -// } -// -// return microservice; -// } -// -// @Test -// public void getOrder() { -// Assert.assertEquals(-10000, filter.getOrder()); -// } -// -// @Test -// public void isGroupingFilterAndEnabled() { -// Assert.assertTrue(filter.isGroupingFilter()); -// Assert.assertTrue(filter.enabled()); -// } -// -// @Test -// public void discovery_v1_0_0() { -// regMicroservice("1", "1.0.0", V1_0_0.class, 2); -// -// MicroserviceVersions MicroserviceVersions = -// serviceRegistry.getAppManager().getOrCreateMicroserviceVersions(appId, microserviceName); -// MicroserviceVersions.submitPull(); -// MicroserviceVersionRule microserviceVersionRule = -// MicroserviceVersions.getOrCreateMicroserviceVersionRule(DefinitionConst.VERSION_RULE_ALL); -// MicroserviceVersionMeta latestMicroserviceVersionMeta = microserviceVersionRule.getLatestMicroserviceVersion(); -// latestOperationMeta = latestMicroserviceVersionMeta.getMicroserviceMeta().ensureFindOperation("sid.add"); -// DiscoveryTreeNode parent = new DiscoveryTreeNode().fromCache(microserviceVersionRule.getVersionedCache()); -// -// setupOnChange(); -// -// result = filter.discovery(context, parent); -// -// Assert.assertEquals(2, result.mapData().size()); -// result.mapData().values().forEach(instance -> { -// Assert.assertEquals("1", ((MicroserviceInstance) instance).getServiceId()); -// }); -// } -// -// @Test -// public void discovery_v1_1_0_add() { -// regMicroservice("1", "1.0.0", V1_0_0.class, 2); -// regMicroservice("2", "1.1.0", V1_1_0.class, 2); -// -// MicroserviceVersions MicroserviceVersions = -// serviceRegistry.getAppManager().getOrCreateMicroserviceVersions(appId, microserviceName); -// MicroserviceVersions.submitPull(); -// MicroserviceVersionRule microserviceVersionRule = -// MicroserviceVersions.getOrCreateMicroserviceVersionRule(DefinitionConst.VERSION_RULE_ALL); -// MicroserviceVersionMeta latestMicroserviceVersionMeta = microserviceVersionRule.getLatestMicroserviceVersion(); -// latestOperationMeta = latestMicroserviceVersionMeta.getMicroserviceMeta().ensureFindOperation("sid.add"); -// DiscoveryTreeNode parent = new DiscoveryTreeNode().fromCache(microserviceVersionRule.getVersionedCache()); -// -// setupOnChange(); -// -// result = filter.discovery(context, parent); -// -// Assert.assertEquals(4, result.mapData().size()); -// Set ids = new HashSet<>(); -// result.mapData().values().forEach(instance -> { -// ids.add(((MicroserviceInstance) instance).getServiceId()); -// }); -// Assert.assertThat(ids, Matchers.containsInAnyOrder("1", "2")); -// } -// -// @Test -// public void discovery_v1_1_0_dec() { -// regMicroservice("1", "1.0.0", V1_0_0.class, 2); -// regMicroservice("2", "1.1.0", V1_1_0.class, 2); -// -// MicroserviceVersions MicroserviceVersions = -// serviceRegistry.getAppManager().getOrCreateMicroserviceVersions(appId, microserviceName); -// MicroserviceVersions.submitPull(); -// MicroserviceVersionRule microserviceVersionRule = -// MicroserviceVersions.getOrCreateMicroserviceVersionRule(DefinitionConst.VERSION_RULE_ALL); -// MicroserviceVersionMeta latestMicroserviceVersionMeta = microserviceVersionRule.getLatestMicroserviceVersion(); -// latestOperationMeta = latestMicroserviceVersionMeta.getMicroserviceMeta().ensureFindOperation("sid.dec"); -// DiscoveryTreeNode parent = new DiscoveryTreeNode().fromCache(microserviceVersionRule.getVersionedCache()); -// -// setupOnChange(); -// -// result = filter.discovery(context, parent); -// -// Assert.assertEquals(2, result.mapData().size()); -// Set ids = new HashSet<>(); -// result.mapData().values().forEach(instance -> { -// ids.add(((MicroserviceInstance) instance).getServiceId()); -// }); -// Assert.assertThat(ids, Matchers.containsInAnyOrder("2")); -// } -} diff --git a/core/src/test/java/org/apache/servicecomb/core/tracing/BraveTraceIdGeneratorTest.java b/core/src/test/java/org/apache/servicecomb/core/tracing/BraveTraceIdGeneratorTest.java index 8963cd292b3..e858dd954c5 100644 --- a/core/src/test/java/org/apache/servicecomb/core/tracing/BraveTraceIdGeneratorTest.java +++ b/core/src/test/java/org/apache/servicecomb/core/tracing/BraveTraceIdGeneratorTest.java @@ -17,23 +17,21 @@ package org.apache.servicecomb.core.tracing; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.fail; - -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class BraveTraceIdGeneratorTest { @Test public void generateStringId() { TraceIdGenerator traceIdGenerator = new BraveTraceIdGenerator(); - assertNotEquals(traceIdGenerator.generate(), traceIdGenerator.generate()); + Assertions.assertNotEquals(traceIdGenerator.generate(), traceIdGenerator.generate()); String traceId = traceIdGenerator.generate(); try { Long.parseLong(traceId, 16); } catch (NumberFormatException e) { - fail("wrong traceId format: " + traceId); + Assertions.fail("wrong traceId format: " + traceId); } } } 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 8ebde26ecde..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 @@ -17,37 +17,27 @@ package org.apache.servicecomb.core.transport; +import static org.apache.servicecomb.core.transport.AbstractTransport.PUBLISH_ADDRESS; + import java.io.UnsupportedEncodingException; -import java.lang.reflect.Method; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Collections; -import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.net.IpPort; -import org.apache.servicecomb.foundation.vertx.VertxUtils; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.util.ReflectionUtils; - -import com.netflix.config.DynamicProperty; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import mockit.Expectations; -import mockit.Mocked; +import io.vertx.core.impl.SysProps; public class TestAbstractTransport { - private Method updatePropertyMethod = - ReflectionUtils.findMethod(DynamicProperty.class, "updateProperty", String.class, Object.class); + Environment environment = Mockito.mock(Environment.class); - private void updateProperty(String key, Object value) { - updatePropertyMethod.setAccessible(true); - ReflectionUtils.invokeMethod(updatePropertyMethod, null, key, value); - } - - class MyAbstractTransport extends AbstractTransport { + static class MyAbstractTransport extends AbstractTransport { @Override public String getName() { @@ -58,64 +48,65 @@ public String getName() { public boolean init() { return true; } - - @Override - public void send(Invocation invocation, AsyncResponse asyncResp) { - } } - @AfterClass - public static void classTeardown() { - VertxUtils.blockCloseVertxByName("transport"); + @BeforeEach + public void setUp() { + Mockito.when(environment.getProperty(PUBLISH_ADDRESS, "")).thenReturn(""); + 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(SysProps.DISABLE_FILE_CP_RESOLVING.name, boolean.class, true)) + .thenReturn(true); + LegacyPropertyFactory.setEnvironment(environment); } @Test public void testSetListenAddressWithoutSchemaChineseSpaceNewSC() throws UnsupportedEncodingException { - new Expectations() { - { - RegistrationManager.getPublishAddress("my", "127.0.0.1:9090"); - } - }; - MyAbstractTransport transport = new MyAbstractTransport(); + transport.setEnvironment(environment); transport.setListenAddressWithoutSchema("127.0.0.1:9090", Collections.singletonMap("country", "中 国")); - Assert.assertEquals("my://127.0.0.1:9090?country=" + URLEncoder.encode("中 国", StandardCharsets.UTF_8.name()), + Assertions.assertEquals("my://127.0.0.1:9090?country=" + URLEncoder.encode("中 国", StandardCharsets.UTF_8.name()), transport.getEndpoint().getEndpoint()); } @Test public void testSetListenAddressWithoutSchemaNormalNotEncode() { MyAbstractTransport transport = new MyAbstractTransport(); + transport.setEnvironment(environment); transport.setListenAddressWithoutSchema("127.0.0.1:9090", Collections.singletonMap("country", "chinese")); - Assert.assertEquals("my://127.0.0.1:9090?country=chinese", transport.getEndpoint().getEndpoint()); + Assertions.assertEquals("my://127.0.0.1:9090?country=chinese", transport.getEndpoint().getEndpoint()); } @Test public void testSetListenAddressWithoutSchemaAlreadyHaveQuery() { MyAbstractTransport transport = new MyAbstractTransport(); + transport.setEnvironment(environment); transport.setListenAddressWithoutSchema("127.0.0.1:9090?a=aValue", Collections.singletonMap("country", "chinese")); - Assert.assertEquals("my://127.0.0.1:9090?a=aValue&country=chinese", transport.getEndpoint().getEndpoint()); + Assertions.assertEquals("my://127.0.0.1:9090?a=aValue&country=chinese", transport.getEndpoint().getEndpoint()); } @Test public void testMyAbstractTransport() { MyAbstractTransport transport = new MyAbstractTransport(); + transport.setEnvironment(environment); transport.setListenAddressWithoutSchema("127.0.0.1:9090"); - Assert.assertEquals("my", transport.getName()); - Assert.assertEquals("my://127.0.0.1:9090", transport.getEndpoint().getEndpoint()); - Assert.assertEquals("127.0.0.1", ((IpPort) transport.parseAddress("my://127.0.0.1:9090")).getHostOrIp()); + Assertions.assertEquals("my", transport.getName()); + Assertions.assertEquals("my://127.0.0.1:9090", transport.getEndpoint().getEndpoint()); + Assertions.assertEquals("127.0.0.1", ((IpPort) transport.parseAddress("my://127.0.0.1:9090")).getHostOrIp()); transport.setListenAddressWithoutSchema("0.0.0.0:9090"); - Assert.assertNotEquals("my://127.0.0.1:9090", transport.getEndpoint().getEndpoint()); + Assertions.assertNotEquals("my://127.0.0.1:9090", transport.getEndpoint().getEndpoint()); transport.setListenAddressWithoutSchema(null); - Assert.assertNull(transport.getEndpoint().getEndpoint()); - Assert.assertNull(transport.parseAddress(null)); + Assertions.assertNull(transport.getEndpoint().getEndpoint()); + Assertions.assertNull(transport.parseAddress(null)); } - @Test(expected = IllegalArgumentException.class) - public void testMyAbstractTransportException(@Mocked TransportManager manager) { + @Test + public void testMyAbstractTransportException() { MyAbstractTransport transport = new MyAbstractTransport(); - - transport.setListenAddressWithoutSchema(":127.0.0.1:9090"); + transport.setEnvironment(environment); + Assertions.assertThrows(IllegalArgumentException.class, () -> + transport.setListenAddressWithoutSchema(":127.0.0.1:9090")); } } diff --git a/core/src/test/java/org/apache/servicecomb/core/transport/TestTransportManager.java b/core/src/test/java/org/apache/servicecomb/core/transport/TestTransportManager.java index ed78e2c2c01..89b591beecb 100644 --- a/core/src/test/java/org/apache/servicecomb/core/transport/TestTransportManager.java +++ b/core/src/test/java/org/apache/servicecomb/core/transport/TestTransportManager.java @@ -25,123 +25,89 @@ import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mocked; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestTransportManager { @Test - public void testTransportManagerInitFail(@Mocked SCBEngine scbEngine, @Injectable Transport transport) + public void testTransportManagerInitFail() throws Exception { - new Expectations() { - { - transport.getName(); - result = "test"; - transport.init(); - result = false; - transport.canInit(); - result = true; - } - }; + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Transport transport = Mockito.mock(Transport.class); + Mockito.when(transport.getName()).thenReturn("test"); + Mockito.when(transport.init()).thenReturn(false); + Mockito.when(transport.canInit()).thenReturn(true); List transports = Arrays.asList(transport); - TransportManager manager = new TransportManager(); manager.addTransportsBeforeInit(transports); manager.init(scbEngine); - Assert.assertEquals(manager.findTransport("test"), transport); + Assertions.assertEquals(manager.findTransport("test"), transport); } @Test - public void testTransportManagerInitSucc(@Mocked SCBEngine scbEngine, @Injectable Transport transport, - @Injectable Endpoint endpoint, @Injectable MicroserviceInstance instance) throws Exception { - new Expectations() { - { - transport.getName(); - result = "test"; - transport.canInit(); - result = true; - transport.init(); - result = true; - transport.getPublishEndpoint(); - result = endpoint; - } - }; + public void testTransportManagerInitSuccess() throws Exception { + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Transport transport = Mockito.mock(Transport.class); + Endpoint endpoint = Mockito.mock(Endpoint.class); + Mockito.when(transport.getName()).thenReturn("test"); + Mockito.when(transport.init()).thenReturn(true); + Mockito.when(transport.canInit()).thenReturn(true); + Mockito.when(transport.getPublishEndpoint()).thenReturn(endpoint); List transports = Arrays.asList(transport); TransportManager manager = new TransportManager(); manager.addTransportsBeforeInit(transports); manager.init(scbEngine); - Assert.assertEquals(manager.findTransport("test"), transport); + Assertions.assertEquals(manager.findTransport("test"), transport); } @Test - public void testGroupByName(@Mocked Transport t1, @Mocked Transport t2_1, @Mocked Transport t2_2) { - new Expectations() { - { - t1.getName(); - result = "t1"; - - t2_1.getName(); - result = "t2"; - t2_2.getName(); - result = "t2"; - } - }; - + public void testGroupByName() { + Transport t1 = Mockito.mock(Transport.class); + Mockito.when(t1.getName()).thenReturn("t1"); + Transport t21 = Mockito.mock(Transport.class); + Mockito.when(t21.getName()).thenReturn("t2"); + Transport t22 = Mockito.mock(Transport.class); + Mockito.when(t22.getName()).thenReturn("t2"); TransportManager manager = new TransportManager(); - manager.addTransportsBeforeInit(Arrays.asList(t1, t2_1, t2_2)); + manager.addTransportsBeforeInit(Arrays.asList(t1, t21, t22)); Map> groups = manager.groupByName(); - Assert.assertEquals(2, groups.size()); - Assert.assertEquals(1, groups.get("t1").size()); - Assert.assertEquals(t1, groups.get("t1").get(0)); - Assert.assertEquals(2, groups.get("t2").size()); - Assert.assertEquals(t2_1, groups.get("t2").get(0)); - Assert.assertEquals(t2_2, groups.get("t2").get(1)); + Assertions.assertEquals(2, groups.size()); + Assertions.assertEquals(1, groups.get("t1").size()); + Assertions.assertEquals(t1, groups.get("t1").get(0)); + Assertions.assertEquals(2, groups.get("t2").size()); + Assertions.assertEquals(t21, groups.get("t2").get(0)); + Assertions.assertEquals(t22, groups.get("t2").get(1)); } @Test - public void testCheckTransportGroupInvalid(@Mocked Transport t1, @Mocked Transport t2) { - new Expectations() { - { - t1.getOrder(); - result = 1; - - t2.getOrder(); - result = 1; - } - }; + public void testCheckTransportGroupInvalid() { + Transport t1 = Mockito.mock(Transport.class); + Mockito.when(t1.getOrder()).thenReturn(1); + Transport t2 = Mockito.mock(Transport.class); + Mockito.when(t2.getOrder()).thenReturn(1); TransportManager manager = new TransportManager(); List group = Arrays.asList(t1, t2); try { manager.checkTransportGroup(group); - Assert.fail("must throw exception"); + Assertions.fail("must throw exception"); } catch (ServiceCombException e) { - Assert.assertEquals( - "org.apache.servicecomb.core.$Impl_Transport and org.apache.servicecomb.core.$Impl_Transport have the same order 1", - e.getMessage()); + Assertions.assertTrue(e.getMessage().contains("have the same order")); } } @Test - public void testCheckTransportGroupValid(@Mocked Transport t1, @Mocked Transport t2) { - new Expectations() { - { - t1.getOrder(); - result = 1; - - t2.getOrder(); - result = 2; - } - }; + public void testCheckTransportGroupValid() { + Transport t1 = Mockito.mock(Transport.class); + Mockito.when(t1.getOrder()).thenReturn(1); + Transport t2 = Mockito.mock(Transport.class); + Mockito.when(t2.getOrder()).thenReturn(2); TransportManager manager = new TransportManager(); List group = Arrays.asList(t1, t2); @@ -149,78 +115,56 @@ public void testCheckTransportGroupValid(@Mocked Transport t1, @Mocked Transport try { manager.checkTransportGroup(group); } catch (ServiceCombException e) { - Assert.fail("must not throw exception: " + e.getMessage()); + Assertions.fail("must not throw exception: " + e.getMessage()); } } @Test - public void testChooseOneTransportFirst(@Mocked Transport t1, @Mocked Transport t2) { - new Expectations() { - { - t1.getOrder(); - result = 1; - t1.canInit(); - result = true; - - t2.getOrder(); - result = 2; - } - }; + public void testChooseOneTransportFirst() { + Transport t1 = Mockito.mock(Transport.class); + Mockito.when(t1.getOrder()).thenReturn(1); + Mockito.when(t1.canInit()).thenReturn(true); + Transport t2 = Mockito.mock(Transport.class); + Mockito.when(t2.getOrder()).thenReturn(2); TransportManager manager = new TransportManager(); List group = Arrays.asList(t1, t2); - Assert.assertEquals(t1, manager.chooseOneTransport(group)); + Assertions.assertEquals(t1, manager.chooseOneTransport(group)); } @Test - public void testChooseOneTransportSecond(@Mocked Transport t1, @Mocked Transport t2) { - new Expectations() { - { - t1.getOrder(); - result = Integer.MAX_VALUE; - t1.canInit(); - result = true; - - t2.getOrder(); - result = -1000; - t2.canInit(); - result = false; - } - }; - + public void testChooseOneTransportSecond() { + Transport t1 = Mockito.mock(Transport.class); + Mockito.when(t1.getOrder()).thenReturn(Integer.MAX_VALUE); + Mockito.when(t1.canInit()).thenReturn(true); + Transport t2 = Mockito.mock(Transport.class); + Mockito.when(t2.getOrder()).thenReturn(-1000); + Mockito.when(t2.canInit()).thenReturn(false); TransportManager manager = new TransportManager(); List group = Arrays.asList(t1, t2); - Assert.assertEquals(t1, manager.chooseOneTransport(group)); + Assertions.assertEquals(t1, manager.chooseOneTransport(group)); } @Test - public void testChooseOneTransportNone(@Mocked Transport t1, @Mocked Transport t2) { - new Expectations() { - { - t1.getName(); - result = "t"; - t1.getOrder(); - result = 1; - t1.canInit(); - result = false; - - t2.getOrder(); - result = 2; - t2.canInit(); - result = false; - } - }; + public void testChooseOneTransportNone() { + Transport t1 = Mockito.mock(Transport.class); + Mockito.when(t1.getName()).thenReturn("t"); + Mockito.when(t1.getOrder()).thenReturn(1); + Mockito.when(t1.canInit()).thenReturn(false); + Transport t2 = Mockito.mock(Transport.class); + Mockito.when(t2.getOrder()).thenReturn(2); + Mockito.when(t2.canInit()).thenReturn(false); TransportManager manager = new TransportManager(); List group = Arrays.asList(t1, t2); try { manager.chooseOneTransport(group); - Assert.fail("must throw exception"); + Assertions.fail("must throw exception"); } catch (ServiceCombException e) { - Assert.assertEquals("all transport named t refused to init.", e.getMessage()); + Assertions.assertEquals("all transport named t refused to init.", e.getMessage()); } } } diff --git a/core/src/test/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter b/core/src/test/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter deleted file mode 100644 index ff338ab9d23..00000000000 --- a/core/src/test/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.core.handler.impl.ErrorToProducerResponseConverter \ No newline at end of file diff --git a/core/src/test/resources/config/cse.handler.xml b/core/src/test/resources/config/cse.handler.xml deleted file mode 100644 index 89510b4db65..00000000000 --- a/core/src/test/resources/config/cse.handler.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/core/src/test/resources/config/log4j.demo.properties b/core/src/test/resources/config/log4j.demo.properties deleted file mode 100644 index fe3ad5a2591..00000000000 --- a/core/src/test/resources/config/log4j.demo.properties +++ /dev/null @@ -1,21 +0,0 @@ -# -# 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. -# - -paas.logs.dir=../logs/ -paas.logs.file=cse.log - -log4j.rootLogger=INFO,paas,stdout diff --git a/core/src/test/resources/log4j.properties b/core/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/core/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/core/src/test/resources/log4j2.xml b/core/src/test/resources/log4j2.xml new file mode 100644 index 00000000000..8cee07220ec --- /dev/null +++ b/core/src/test/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/core/src/test/resources/microservice.yaml b/core/src/test/resources/microservice.yaml index 0baa251fd13..b17313cd44c 100644 --- a/core/src/test/resources/microservice.yaml +++ b/core/src/test/resources/microservice.yaml @@ -30,4 +30,4 @@ servicecomb: zq: - tlist: a - tlist: b - - tlist: 1 \ No newline at end of file + - tlist: 1 diff --git a/core/src/test/resources/test/test/microservice.yaml b/core/src/test/resources/test/test/microservice.yaml index a82dcd3f036..7ec47b07b63 100644 --- a/core/src/test/resources/test/test/microservice.yaml +++ b/core/src/test/resources/test/test/microservice.yaml @@ -18,7 +18,7 @@ service_description: name: default version: 0.0.1 - propertyExtentedClass: org.apache.servicecomb.serviceregistry.MicroServicePropertyExtendedStub + propertyExtendedClass: org.apache.servicecomb.serviceregistry.MicroServicePropertyExtendedStub servicecomb: service: registry: diff --git a/coverage-reports/pom.xml b/coverage-reports/pom.xml index 33875d69fb8..97f795fcbf5 100644 --- a/coverage-reports/pom.xml +++ b/coverage-reports/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default 4.0.0 @@ -31,24 +31,6 @@ - - - org.apache.servicecomb.archetypes - business-service-jaxrs-archetype - - - org.apache.servicecomb.archetypes - business-service-pojo-archetype - - - org.apache.servicecomb.archetypes - business-service-spring-boot2-starter-archetype - - - org.apache.servicecomb.archetypes - business-service-springmvc-archetype - - org.apache.servicecomb @@ -62,6 +44,10 @@ org.apache.servicecomb config-kie-client + + org.apache.servicecomb + dashboard-client + org.apache.servicecomb http-client-common @@ -91,12 +77,6 @@ java-chassis-core - - - org.apache.servicecomb - deployment - - org.apache.servicecomb @@ -166,10 +146,6 @@ - - org.apache.servicecomb - handler-bizkeeper - org.apache.servicecomb handler-fault-injection @@ -195,12 +171,6 @@ handler-tracing-zipkin - - - org.apache.servicecomb - inspector - - org.apache.servicecomb @@ -238,10 +208,6 @@ org.apache.servicecomb registry-local - - org.apache.servicecomb - registry-schema-discovery - org.apache.servicecomb registry-service-center @@ -258,10 +224,6 @@ - - org.apache.servicecomb - java-chassis-spring-boot-starter - org.apache.servicecomb java-chassis-spring-boot-starter-servlet @@ -272,10 +234,6 @@ - - org.apache.servicecomb - servicestage-environment - org.apache.servicecomb servicestage @@ -486,16 +444,17 @@ ${project.version} test - + + org.apache.servicecomb.demo - demo-spring-boot-jaxrs-client + demo-spring-boot-pojo-client ${project.version} test org.apache.servicecomb.demo - demo-spring-boot-jaxrs-server + demo-spring-boot-pojo-server ${project.version} test @@ -511,19 +470,6 @@ ${project.version} test - - - org.apache.servicecomb.demo - demo-spring-boot-pojo-client - ${project.version} - test - - - org.apache.servicecomb.demo - demo-spring-boot-pojo-server - ${project.version} - test - org.apache.servicecomb.demo @@ -540,142 +486,19 @@ org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry-client + demo-zeroconfig-registry-client ${project.version} test org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry-server + demo-zeroconfig-registry-server ${project.version} test org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry-tests - ${project.version} - test - - - - - org.apache.servicecomb.tests - dynamic-config-tests - ${project.version} - test - - - org.apache.servicecomb.tests - it-common - ${project.version} - test - - - org.apache.servicecomb.tests - it-consumer - ${project.version} - test - - - org.apache.servicecomb.tests - it-edge - ${project.version} - test - - - org.apache.servicecomb.tests - it-producer - ${project.version} - test - - - org.apache.servicecomb.tests - it-producer-deploy-springboot2-servlet - ${project.version} - test - - - org.apache.servicecomb.tests - it-producer-deploy-springboot2-standalone - ${project.version} - test - - - org.apache.servicecomb.tests - jaxrs-tests - ${project.version} - test - - - org.apache.servicecomb.tests - pojo-test - ${project.version} - test - - - org.apache.servicecomb.tests - spring-jaxrs-tests - ${project.version} - test - - - org.apache.servicecomb.tests - spring-pojo-connection-limit-test - ${project.version} - test - - - org.apache.servicecomb.tests - spring-pojo-tests - ${project.version} - test - - - - org.apache.servicecomb.tests - springmvc-tests-common - ${project.version} - test - - - org.apache.servicecomb.tests - springmvc-tests-connection-limit - ${project.version} - test - - - org.apache.servicecomb.tests - springmvc-tests-general - ${project.version} - test - - - org.apache.servicecomb.tests - springmvc-tests-general-with-springboot - ${project.version} - test - - - org.apache.servicecomb.tests - springmvc-tests-simplified-mapping - ${project.version} - test - - - org.apache.servicecomb.tests - springmvc-tests-simplified-mapping-with-springboot - ${project.version} - test - - - org.apache.servicecomb.tests - test-common - ${project.version} - test - - - org.apache.servicecomb.tests - tracing-tests + demo-zeroconfig-registry-tests ${project.version} test diff --git a/demo/README.md b/demo/README.md index 02ebd237c3d..18153ce7a57 100644 --- a/demo/README.md +++ b/demo/README.md @@ -1,9 +1,9 @@ -This module contains integrated test cases. Running these test cases, should include profile +This module contains integrated test cases. Running these test cases, should include profile ```shell script --Pdocker -Pdemo-run-release +-Pdocker ``` [java-chassis-samples][java-chassis-samples] project provides a lot of samples. - + [java-chassis-samples]: https://github.com/apache/servicecomb-samples/tree/master/java-chassis-samples 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 entity = new HttpEntity(headers); + ResponseEntity response = + template.exchange(Config.GATEWAY_URL + "/sayHello?name=World", HttpMethod.GET, entity, String.class); + TestMgr.check(1, response.getHeaders().get("X-B3-TraceId").size()); + TestMgr.check("81de2eb7691c2bbb", response.getHeaders().getFirst("X-B3-TraceId")); + TestMgr.check("Hello World", response.getBody()); + } +} diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ProviderIT.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ProviderIT.java new file mode 100644 index 00000000000..2bdd0ca42ca --- /dev/null +++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ProviderIT.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.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.utils.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +@Component +public class ProviderIT implements CategorizedTestCase { + + RestOperations template = new RestTemplate(); + + private static final Logger LOGGER = LoggerFactory.getLogger(ProviderIT.class); + + @Override + public void testRestTransport() throws Exception { + + User user = getUser("Application/json"); + TestMgr.check(1L, user.getId()); + TestMgr.check("czd", user.getName()); + + User user2 = getUser("application/json"); + TestMgr.check(1L, user2.getId()); + TestMgr.check("czd", user2.getName()); + + User user3 = getUser("APPLICATION/JSON"); + TestMgr.check(1L, user3.getId()); + TestMgr.check("czd", user3.getName()); + } + + private User getUser(String contentType) throws IOException { + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", contentType); + + String requestBody = """ + { + "id": 1, + "name": "czd" + } + """; + + HttpEntity entity = new HttpEntity<>(requestBody, headers); + + String url = Config.GATEWAY_URL + "/testContentType"; + ResponseEntity response = template.exchange( + url, HttpMethod.POST, entity, String.class); + + User user = JsonUtils.readValue(response.getBody().getBytes(StandardCharsets.UTF_8), User.class); + return user; + } +} diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java new file mode 100644 index 00000000000..488a6cf712a --- /dev/null +++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java @@ -0,0 +1,119 @@ +/* + * 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 org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.ReactiveStreamClient; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.ReactiveStreamClient.Model; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +public class ReactiveStreamIT implements CategorizedTestCase { + @Autowired + @Qualifier("reactiveStreamProvider") + ReactiveStreamClient reactiveStreamProvider; + + @Autowired + @Qualifier("reactiveStreamGateway") + ReactiveStreamClient reactiveStreamGateway; + + @Override + public void testRestTransport() throws Exception { + testSseString(reactiveStreamProvider); + testSseModel(reactiveStreamProvider); + testSseString(reactiveStreamGateway); + testSseModel(reactiveStreamGateway); + } + + private void testSseModel(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseModel(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(Model s) { + buffer.append(s.getName()).append(s.getAge()); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("jack0jack1jack2jack3jack4", buffer.toString()); + } + + private void testSseString(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseString(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(String s) { + buffer.append(s); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("abc", buffer.toString()); + } +} diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java new file mode 100644 index 00000000000..26a2a491bbe --- /dev/null +++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java @@ -0,0 +1,49 @@ +/* + * 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.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class TestClientApplication { + private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(TestClientApplication.class).run(args); + + run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("consumer"); + } +} diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java new file mode 100644 index 00000000000..abe96a4f10b --- /dev/null +++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java @@ -0,0 +1,125 @@ +/* + * 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.core.CoreConst; +import org.apache.servicecomb.core.annotation.Transport; +import org.apache.servicecomb.localregistry.RegistryBean; +import org.apache.servicecomb.localregistry.RegistryBean.Instance; +import org.apache.servicecomb.localregistry.RegistryBean.Instances; +import org.apache.servicecomb.provider.pojo.Invoker; +import org.reactivestreams.Publisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import io.vertx.core.http.WebSocket; + +@Configuration +public class ThirdSvcConfiguration { + @RequestMapping(path = "/ws") + public interface WebsocketClient { + @PostMapping("/websocket") + @Transport(name = CoreConst.WEBSOCKET) + WebSocket websocket(); + } + + @RequestMapping(path = "/") + public interface ReactiveStreamClient { + 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") + Publisher sseString(); + + @GetMapping("/sseModel") + Publisher sseModel(); + } + + @Bean + public RegistryBean providerServiceBean() { + return new RegistryBean() + .addSchemaInterface("ReactiveStreamController", ReactiveStreamClient.class) + .setAppId("demo-consul") + .setServiceName("provider") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of( + new Instance().setEndpoints(List.of("rest://localhost:9094"))))); + } + + @Bean + public RegistryBean gatewayServiceBean() { + return new RegistryBean() + .addSchemaInterface("ReactiveStreamController", ReactiveStreamClient.class) + .addSchemaInterface("WebsocketController", WebsocketClient.class) + .setAppId("demo-consul") + .setServiceName("gateway") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of( + new Instance().setEndpoints(List.of("rest://localhost:9090?websocketEnabled=true"))))); + } + + @Bean("reactiveStreamProvider") + public ReactiveStreamClient reactiveStreamProvider() { + return Invoker.createProxy("provider", "ReactiveStreamController", ReactiveStreamClient.class); + } + + @Bean("reactiveStreamGateway") + public ReactiveStreamClient reactiveStreamGateway() { + return Invoker.createProxy("gateway", "ReactiveStreamController", ReactiveStreamClient.class); + } + + @Bean + public WebsocketClient gatewayWebsocketClient() { + return Invoker.createProxy("gateway", "WebsocketController", WebsocketClient.class); + } +} diff --git a/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/User.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/User.java new file mode 100644 index 00000000000..ff421930ef2 --- /dev/null +++ b/demo/demo-consul/test-client/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/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java new file mode 100644 index 00000000000..c36f2d16d28 --- /dev/null +++ b/demo/demo-consul/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java @@ -0,0 +1,73 @@ +/* + * 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.AtomicBoolean; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.WebsocketClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import io.vertx.core.http.WebSocket; + +@Component +public class WebsocketIT implements CategorizedTestCase { + @Autowired + private WebsocketClient websocketClient; + + @Override + public void testRestTransport() throws Exception { + StringBuffer sb = new StringBuffer(); + AtomicBoolean closed = new AtomicBoolean(false); + CountDownLatch latchStarted = new CountDownLatch(1); + CountDownLatch latch = new CountDownLatch(1); + + WebSocket webSocket = websocketClient.websocket(); + webSocket.textMessageHandler(s -> { + if ("started".equals(s)) { + latchStarted.countDown(); + return; + } + sb.append(s); + sb.append(" "); + webSocket.writeTextMessage(s); + }); + webSocket.closeHandler(v -> { + closed.set(true); + latch.countDown(); + }); + + webSocket.writeTextMessage("start"); + int i = 0; + for (; i < 10; i++) { + if (!latchStarted.await(3, TimeUnit.SECONDS)) { + webSocket.writeTextMessage("start"); + continue; + } + break; + } + TestMgr.check(i < 10, true); + latch.await(30, TimeUnit.SECONDS); + TestMgr.check(sb.toString(), "hello hello 0 hello 1 hello 2 hello 3 hello 4 total 6 "); + TestMgr.check(closed.get(), true); + } +} diff --git a/demo/demo-consul/test-client/src/main/resources/application.yml b/demo/demo-consul/test-client/src/main/resources/application.yml new file mode 100644 index 00000000000..718fbd9cc84 --- /dev/null +++ b/demo/demo-consul/test-client/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 + name: test-client + version: 0.0.1 + + rest: + address: 0.0.0.0:9097 # should be same with server.port to use web container + + config: + consul: + enabled: true + host: 127.0.0.1 + scheme: http + acl-token: '' + instance-tag: tag1 + +test1: env +test2: applition +test3: service +test4: version +test5: tag diff --git a/demo/demo-consul/test-client/src/main/resources/log4j2.xml b/demo/demo-consul/test-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-consul/test-client/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-consul/test-client/src/test/java/org/apache/servicecomb/samples/ConsulIT.java b/demo/demo-consul/test-client/src/test/java/org/apache/servicecomb/samples/ConsulIT.java new file mode 100644 index 00000000000..62862743e27 --- /dev/null +++ b/demo/demo-consul/test-client/src/test/java/org/apache/servicecomb/samples/ConsulIT.java @@ -0,0 +1,53 @@ +/* + * 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.TestMgr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = TestClientApplication.class) +public class ConsulIT { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulIT.class); + + @BeforeEach + public void setUp() { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() { + try { + TestClientApplication.run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/demo-crossapp/crossapp-client/pom.xml b/demo/demo-crossapp/crossapp-client/pom.xml index 7ab53a9e519..fa2e051cd0f 100644 --- a/demo/demo-crossapp/crossapp-client/pom.xml +++ b/demo/demo-crossapp/crossapp-client/pom.xml @@ -23,50 +23,17 @@ org.apache.servicecomb.demo demo-crossapp - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT crossapp-client Java Chassis::Demo::CrossApp::Client - - org.apache.servicecomb.demo - demo-schema - - - org.apache.servicecomb - provider-pojo - - - org.apache.servicecomb - provider-springmvc - org.apache.servicecomb.demo.crossapp.CrossappClient - - - - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - @@ -75,6 +42,83 @@ crossapp-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-crossapp/crossapp-client/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappClient.java b/demo/demo-crossapp/crossapp-client/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappClient.java index f76ca083c96..7d78648963a 100644 --- a/demo/demo-crossapp/crossapp-client/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappClient.java +++ b/demo/demo-crossapp/crossapp-client/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappClient.java @@ -22,40 +22,39 @@ import org.apache.servicecomb.core.provider.consumer.InvokerUtils; import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; -@Component +@SpringBootApplication public class CrossappClient { @RpcReference(microserviceName = "appServer:appService", schemaId = "helloworld") private static HelloWorld helloWorld; public static void main(String[] args) throws Exception { - System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(CrossappClient.class).web(WebApplicationType.NONE).run(args); run(); - - TestMgr.summary(); - System.setProperty("sun.net.http.allowRestrictedHeaders", "false"); } - @SuppressWarnings({"deprecation"}) public static void run() { - Object result = InvokerUtils.syncInvoke("appServer:appService", "helloworld", "sayHello", null); + System.setProperty("sun.net.http.allowRestrictedHeaders", "true"); + + String result = InvokerUtils.syncInvoke("appServer:appService", "helloworld", + "sayHello", null, String.class); TestMgr.check("hello world", result); - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); result = restTemplate.getForObject("cse://appServer:appService/helloworld/hello", String.class); TestMgr.check("hello world", result); result = restTemplate.getForObject("servicecomb://appServer:appService/helloworld/hello", String.class); @@ -64,25 +63,84 @@ public static void run() { result = helloWorld.sayHello(); TestMgr.check("hello world", result); - testCorsHandler(); + testCorsHandlerOptions(); + testCorsHandlerGet(); + + TestMgr.summary(); + System.setProperty("sun.net.http.allowRestrictedHeaders", "false"); } - private static void testCorsHandler() { - RestTemplate springRestTemplate = new RestTemplate(); + private static void testCorsHandlerOptions() { + // first domain + RestOperations springRestTemplate = new RestTemplate(); MultiValueMap requestHeaders = new LinkedMultiValueMap<>(); - requestHeaders.put("Origin", Collections.singletonList("http://localhost:8080")); + requestHeaders.put("Origin", Collections.singletonList("http://test.domain:8080")); requestHeaders.put("Access-Control-Request-Method", Collections.singletonList("PUT")); - HttpEntity requestEntity = new HttpEntity<>(requestHeaders); ResponseEntity responseEntity = springRestTemplate .exchange("http://127.0.0.1:8080/helloworld/hello", HttpMethod.OPTIONS, requestEntity, String.class); - - TestMgr.check("204", responseEntity.getStatusCodeValue()); + TestMgr.check("204", responseEntity.getStatusCode().value()); TreeSet sortedSet = new TreeSet<>(responseEntity.getHeaders().get("Access-Control-Allow-Methods")); TestMgr.check("[DELETE,POST,GET,PUT]", sortedSet); sortedSet = new TreeSet<>(responseEntity.getHeaders().get("Access-Control-Allow-Headers")); TestMgr.check("[abc,def]", sortedSet); - TestMgr.check("*", responseEntity.getHeaders().getFirst("Access-Control-Allow-Origin")); + TestMgr.check("http://test.domain:8080", + responseEntity.getHeaders().getFirst("Access-Control-Allow-Origin")); + + // second domain + requestHeaders = new LinkedMultiValueMap<>(); + requestHeaders.put("Origin", Collections.singletonList("http://test.domain:9090")); + requestHeaders.put("Access-Control-Request-Method", Collections.singletonList("PUT")); + requestEntity = new HttpEntity<>(requestHeaders); + responseEntity = springRestTemplate + .exchange("http://127.0.0.1:8080/helloworld/hello", HttpMethod.OPTIONS, requestEntity, + String.class); + TestMgr.check("204", responseEntity.getStatusCode().value()); + sortedSet = new TreeSet<>(responseEntity.getHeaders().get("Access-Control-Allow-Methods")); + TestMgr.check("[DELETE,POST,GET,PUT]", sortedSet); + sortedSet = new TreeSet<>(responseEntity.getHeaders().get("Access-Control-Allow-Headers")); + TestMgr.check("[abc,def]", sortedSet); + TestMgr.check("http://test.domain:9090", + responseEntity.getHeaders().getFirst("Access-Control-Allow-Origin")); + } + + private static void testCorsHandlerGet() { + // allowed origin + RestOperations springRestTemplate = new RestTemplate(); + MultiValueMap requestHeaders = new LinkedMultiValueMap<>(); + requestHeaders.put("Origin", Collections.singletonList("http://test.domain:8080")); + HttpEntity requestEntity = new HttpEntity<>(requestHeaders); + ResponseEntity responseEntity = springRestTemplate + .exchange("http://127.0.0.1:8080/helloworld/hello", HttpMethod.GET, requestEntity, + String.class); + + TestMgr.check("200", responseEntity.getStatusCode().value()); + TestMgr.check("hello world", responseEntity.getBody()); + + // allowed origin + requestHeaders = new LinkedMultiValueMap<>(); + requestHeaders.put("Origin", Collections.singletonList("http://test.domain:9090")); + requestEntity = new HttpEntity<>(requestHeaders); + responseEntity = springRestTemplate + .exchange("http://127.0.0.1:8080/helloworld/hello", HttpMethod.GET, requestEntity, + String.class); + + TestMgr.check("200", responseEntity.getStatusCode().value()); + TestMgr.check("hello world", responseEntity.getBody()); + + // not allowed origin + try { + requestHeaders = new LinkedMultiValueMap<>(); + requestHeaders.put("Origin", Collections.singletonList("http://test.domain:7070")); + requestEntity = new HttpEntity<>(requestHeaders); + springRestTemplate + .exchange("http://127.0.0.1:8080/helloworld/hello", HttpMethod.GET, requestEntity, + String.class); + TestMgr.fail("must throw"); + } catch (HttpServerErrorException e) { + TestMgr.check(500, e.getStatusCode().value()); + TestMgr.check(true, e.getMessage().contains("500 CORS Rejected")); + } } } diff --git a/demo/demo-crossapp/crossapp-client/src/main/resources/log4j2.xml b/demo/demo-crossapp/crossapp-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-crossapp/crossapp-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-crossapp/crossapp-client/src/main/resources/microservice.yaml b/demo/demo-crossapp/crossapp-client/src/main/resources/microservice.yaml index 4590f8f8791..1728b196574 100644 --- a/demo/demo-crossapp/crossapp-client/src/main/resources/microservice.yaml +++ b/demo/demo-crossapp/crossapp-client/src/main/resources/microservice.yaml @@ -14,14 +14,13 @@ ## See the License for the specific language governing permissions and ## limitations under the License. ## --------------------------------------------------------------------------- - -APPLICATION_ID: appClient -service_description: - name: appClientService - version: 0.0.1 servicecomb: service: - registry: + application: appClient + name: appClientService + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 handler: chain: diff --git a/demo/demo-crossapp/crossapp-client/src/main/resources/schemas/helloworld.yaml b/demo/demo-crossapp/crossapp-client/src/main/resources/schemas/helloworld.yaml deleted file mode 100644 index 4a98f862cb1..00000000000 --- a/demo/demo-crossapp/crossapp-client/src/main/resources/schemas/helloworld.yaml +++ /dev/null @@ -1,36 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -swagger: '2.0' -info: - title: hello service - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.crossapp.HelloWorld - -basePath: /helloworld -produces: - - application/json - -paths: - /hello: - get: - operationId: sayHello - responses: - "200": - description: say hello - schema: - type: string diff --git a/demo/demo-crossapp/crossapp-client/src/test/java/org/apache/servicecomb/demo/crossapp/CrossAppIT.java b/demo/demo-crossapp/crossapp-client/src/test/java/org/apache/servicecomb/demo/crossapp/CrossAppIT.java index 71c7af1d324..54b02c90ae9 100644 --- a/demo/demo-crossapp/crossapp-client/src/test/java/org/apache/servicecomb/demo/crossapp/CrossAppIT.java +++ b/demo/demo-crossapp/crossapp-client/src/test/java/org/apache/servicecomb/demo/crossapp/CrossAppIT.java @@ -17,24 +17,27 @@ package org.apache.servicecomb.demo.crossapp; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = CrossappClient.class) public class CrossAppIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @Test public void clientGetsNoError() throws Exception { - CrossappClient.main(new String[0]); + CrossappClient.run(); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-crossapp/crossapp-server/pom.xml b/demo/demo-crossapp/crossapp-server/pom.xml index 0135ff43ee2..0207bdb7b20 100644 --- a/demo/demo-crossapp/crossapp-server/pom.xml +++ b/demo/demo-crossapp/crossapp-server/pom.xml @@ -23,20 +23,12 @@ org.apache.servicecomb.demo demo-crossapp - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT crossapp-server Java Chassis::Demo::CrossApp::Server - - org.apache.servicecomb.demo - demo-schema - - - org.apache.servicecomb - provider-pojo - @@ -45,21 +37,8 @@ - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -68,15 +47,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappBootListener.java b/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappBootListener.java deleted file mode 100644 index fa8202b7a5c..00000000000 --- a/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappBootListener.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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.demo.crossapp; - -import org.apache.servicecomb.core.BootListener; -import org.springframework.stereotype.Component; - -@Component -public class CrossappBootListener implements BootListener { - @Override - public void onBeforeProducerProvider(BootEvent event) { - event.getScbEngine().getSwaggerLoader().registerSwaggersInLocation("schemas"); - } -} diff --git a/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappServer.java b/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappServer.java index d64cdf569f3..63678f2e9d6 100644 --- a/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappServer.java +++ b/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/CrossappServer.java @@ -17,13 +17,13 @@ package org.apache.servicecomb.demo.crossapp; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +@SpringBootApplication public class CrossappServer { - public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(CrossappServer.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/HelloWorldImpl.java b/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/HelloWorldImpl.java index 00051c314c1..b8ede3eba7e 100644 --- a/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/HelloWorldImpl.java +++ b/demo/demo-crossapp/crossapp-server/src/main/java/org/apache/servicecomb/demo/crossapp/HelloWorldImpl.java @@ -17,10 +17,16 @@ package org.apache.servicecomb.demo.crossapp; -import org.apache.servicecomb.provider.pojo.RpcSchema; +import org.apache.servicecomb.provider.rest.common.RestSchema; -@RpcSchema(schemaId = "helloworld") +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; + +@RestSchema(schemaId = "helloworld") +@Path("helloworld") public class HelloWorldImpl { + @GET + @Path("hello") public String sayHello() { return "hello world"; } diff --git a/demo/demo-crossapp/crossapp-server/src/main/resources/log4j2.xml b/demo/demo-crossapp/crossapp-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-crossapp/crossapp-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-crossapp/crossapp-server/src/main/resources/microservice.yaml b/demo/demo-crossapp/crossapp-server/src/main/resources/microservice.yaml index 3f263b861bd..0f1bbdc8853 100644 --- a/demo/demo-crossapp/crossapp-server/src/main/resources/microservice.yaml +++ b/demo/demo-crossapp/crossapp-server/src/main/resources/microservice.yaml @@ -15,25 +15,22 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: appServer -service_description: - name: appService - version: 0.0.1 - properties: - allowCrossApp: true -instance_description: - properties: - tag0: value0 - servicecomb: service: - registry: + application: appServer + name: appService + version: 0.0.1 + properties: + allowCrossApp: true + tag0: value0 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8080 cors: enabled: true - origin: "*" + origin: "http://test.domain:8080,http://test.domain:9090" allowedHeader: abc,def allowedMethod: GET,PUT,POST,DELETE exposedHeader: abc,def diff --git a/demo/demo-crossapp/crossapp-server/src/main/resources/schemas/helloworld.yaml b/demo/demo-crossapp/crossapp-server/src/main/resources/schemas/helloworld.yaml deleted file mode 100644 index 4a98f862cb1..00000000000 --- a/demo/demo-crossapp/crossapp-server/src/main/resources/schemas/helloworld.yaml +++ /dev/null @@ -1,36 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -swagger: '2.0' -info: - title: hello service - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.crossapp.HelloWorld - -basePath: /helloworld -produces: - - application/json - -paths: - /hello: - get: - operationId: sayHello - responses: - "200": - description: say hello - schema: - type: string diff --git a/demo/demo-crossapp/pom.xml b/demo/demo-crossapp/pom.xml index 60d934797fb..08c2055d357 100644 --- a/demo/demo-crossapp/pom.xml +++ b/demo/demo-crossapp/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-crossapp Java Chassis::Demo::CrossApp @@ -34,17 +34,29 @@ + + org.apache.servicecomb.demo + demo-schema + org.apache.servicecomb registry-service-center - log4j - log4j + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-core diff --git a/demo/demo-cse-v1/consumer/pom.xml b/demo/demo-cse-v1/consumer/pom.xml index 9a3abe24d83..78a7bf75a23 100644 --- a/demo/demo-cse-v1/consumer/pom.xml +++ b/demo/demo-cse-v1/consumer/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-cse-v1 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v1-consumer @@ -44,4 +44,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java index 0010f13c817..3e7a2a0e285 100644 --- a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java +++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java @@ -17,14 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ConsumerApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java index 34a40bd5edb..f86c5a29492 100644 --- a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java +++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java @@ -26,17 +26,20 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import com.netflix.config.DynamicPropertyFactory; - @RestSchema(schemaId = "ConsumerConfigController") @RequestMapping(path = "/") public class ConsumerConfigController { - @Autowired private Environment environment; - @Autowired private ConsumerConfigurationProperties consumerConfigurationProperties; + @Autowired + public ConsumerConfigController(Environment environment, + ConsumerConfigurationProperties consumerConfigurationProperties) { + this.environment = environment; + this.consumerConfigurationProperties = consumerConfigurationProperties; + } + @GetMapping("/config") public String config(@RequestParam("key") String key) { return environment.getProperty(key); @@ -54,18 +57,12 @@ public String bar() { @GetMapping("/dynamicString") public String dynamicString(@RequestParam("key") String key) { - return DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); + return environment.getProperty(key); } @GetMapping("/dynamicArray") @SuppressWarnings("unchecked") public List dynamicArray() { return consumerConfigurationProperties.getDynamicArray(); -// DynamicPropertyFactory & Environment do not support arrays like: -// key[0]: v0 -// key[1]: v1 -// return environment.getProperty(key, List.class); -// return Arrays.asList(((AbstractConfiguration) DynamicPropertyFactory.getBackingConfigurationSource()) -// .getStringArray(key)); } } diff --git a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java index 940a79bb87a..dc3ead65da2 100644 --- a/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java +++ b/demo/demo-cse-v1/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java @@ -20,7 +20,6 @@ import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; diff --git a/demo/demo-cse-v1/consumer/src/main/resources/application.yml b/demo/demo-cse-v1/consumer/src/main/resources/application.yml index acc9b81f715..11f739de444 100644 --- a/demo/demo-cse-v1/consumer/src/main/resources/application.yml +++ b/demo/demo-cse-v1/consumer/src/main/resources/application.yml @@ -24,10 +24,10 @@ servicecomb: application: demo-java-chassis-cse-v1 name: consumer version: 0.0.1 - registry: + registry: + sc: address: https://cse.cn-south-1.myhuaweicloud.com - instance: - watch: false + watch: false config: client: serverUri: https://cse.cn-south-1.myhuaweicloud.com @@ -59,6 +59,71 @@ servicecomb: - weight: 100 tags: version: 0.0.1 + - precedence: 3 + match: + headers: + canary: + exact: fallback + route: + - weight: 100 + tags: + version: 0.0.3 + fallback: + - weight: 20 + tags: + version: 0.0.1 + - weight: 80 + tags: + version: 0.0.2 + - precedence: 4 + emptyProtection: false + match: + headers: + canary: + exact: emptyProtectionClose100 + route: + - weight: 100 + tags: + version: 0.0.3 + - precedence: 5 + emptyProtection: false + match: + headers: + canary: + exact: emptyProtectionCloseLess100 + route: + - weight: 50 + tags: + version: 0.0.3 + - precedence: 6 + emptyProtection: false + match: + headers: + canary: + exact: emptyProtectionCloseFallback + route: + - weight: 100 + tags: + version: 0.0.3 + fallback: + - weight: 100 + tags: + version: 0.0.1 + - precedence: 7 + emptyProtection: false + match: + headers: + canary: + exact: emptyProtectionClose100-2 + route: + - weight: 50 + tags: + version: 0.0.1 + - weight: 50 + tags: + version: 0.0.3 + + router: type: router header: canary @@ -70,5 +135,3 @@ servicecomb: secretKey: ${CREDENTIALS_SK} akskCustomCipher: default project: cn-south-1 - - diff --git a/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml b/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml index 313d1fcec1f..4e54783856a 100644 --- a/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v1/consumer/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/gateway/pom.xml b/demo/demo-cse-v1/gateway/pom.xml index cfcf47351f2..49241e669cf 100644 --- a/demo/demo-cse-v1/gateway/pom.xml +++ b/demo/demo-cse-v1/gateway/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-cse-v1 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v1-gateway @@ -47,4 +47,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java index f2e086b4235..7d58caafd9d 100644 --- a/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java +++ b/demo/demo-cse-v1/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java @@ -17,13 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class GatewayApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v1/gateway/src/main/resources/application.yml b/demo/demo-cse-v1/gateway/src/main/resources/application.yml index 9f8b8c0b8ef..52f065c4f62 100644 --- a/demo/demo-cse-v1/gateway/src/main/resources/application.yml +++ b/demo/demo-cse-v1/gateway/src/main/resources/application.yml @@ -24,10 +24,10 @@ servicecomb: application: demo-java-chassis-cse-v1 name: gateway version: 0.0.1 - registry: + registry: + sc: address: https://cse.cn-south-1.myhuaweicloud.com - instance: - watch: false + watch: false config: client: serverUri: https://cse.cn-south-1.myhuaweicloud.com @@ -50,9 +50,16 @@ servicecomb: microserviceName: consumer versionRule: 0.0.0+ - router: - type: router - header: canary + matchGroup: + canary-header: | + matches: + - headers: + canary: + prefix: "" + mapper: + canary-header: | + target: + canary: $H{canary} # Configure AK/SK credentials if needed. Default not enabled. credentials: @@ -60,4 +67,4 @@ servicecomb: accessKey: ${CREDENTIALS_AK} secretKey: ${CREDENTIALS_SK} akskCustomCipher: default - project: cn-south-1 \ No newline at end of file + project: cn-south-1 diff --git a/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml b/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml index e9bb2656f8f..165cdf7e0a3 100644 --- a/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v1/gateway/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/pom.xml b/demo/demo-cse-v1/pom.xml index 7bbc01c45a7..72e70e58c15 100644 --- a/demo/demo-cse-v1/pom.xml +++ b/demo/demo-cse-v1/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-cse-v1 Java Chassis::Demo::CSE-V1 @@ -47,7 +47,23 @@ org.apache.servicecomb - servicestage-environment + config-cc + + + org.apache.servicecomb + servicestage + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core @@ -59,4 +75,4 @@ test-client - \ No newline at end of file + diff --git a/demo/demo-cse-v1/provider-canary/pom.xml b/demo/demo-cse-v1/provider-canary/pom.xml index 9793374cb7e..34c393b9e8d 100644 --- a/demo/demo-cse-v1/provider-canary/pom.xml +++ b/demo/demo-cse-v1/provider-canary/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-cse-v1 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v1-provider-canary @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java index 6542bcedfbf..fde6f36b2e3 100644 --- a/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java +++ b/demo/demo-cse-v1/provider-canary/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java @@ -17,14 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ProviderApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v1/provider-canary/src/main/resources/application.yml b/demo/demo-cse-v1/provider-canary/src/main/resources/application.yml index 81bf7aaffb7..29e8e8f3879 100644 --- a/demo/demo-cse-v1/provider-canary/src/main/resources/application.yml +++ b/demo/demo-cse-v1/provider-canary/src/main/resources/application.yml @@ -23,10 +23,10 @@ servicecomb: application: demo-java-chassis-cse-v1 name: provider version: 0.0.2 - registry: + registry: + sc: address: https://cse.cn-south-1.myhuaweicloud.com - instance: - watch: false + watch: false config: client: serverUri: https://cse.cn-south-1.myhuaweicloud.com diff --git a/demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml b/demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml index 56fc9a0a676..9ac74305e0c 100644 --- a/demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v1/provider-canary/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/provider/pom.xml b/demo/demo-cse-v1/provider/pom.xml index f0a19567851..12015bd6b7a 100644 --- a/demo/demo-cse-v1/provider/pom.xml +++ b/demo/demo-cse-v1/provider/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-cse-v1 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v1-provider @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java index 6542bcedfbf..fde6f36b2e3 100644 --- a/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java +++ b/demo/demo-cse-v1/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java @@ -17,14 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ProviderApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v1/provider/src/main/resources/application.yml b/demo/demo-cse-v1/provider/src/main/resources/application.yml index 370c3cd975e..097e2e9cc85 100644 --- a/demo/demo-cse-v1/provider/src/main/resources/application.yml +++ b/demo/demo-cse-v1/provider/src/main/resources/application.yml @@ -23,10 +23,10 @@ servicecomb: application: demo-java-chassis-cse-v1 name: provider version: 0.0.1 - registry: + registry: + sc: address: https://cse.cn-south-1.myhuaweicloud.com - instance: - watch: false + watch: false config: client: serverUri: https://cse.cn-south-1.myhuaweicloud.com diff --git a/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml b/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml index 56fc9a0a676..9ac74305e0c 100644 --- a/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v1/provider/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/test-client/pom.xml b/demo/demo-cse-v1/test-client/pom.xml index 11c628b4f85..697c28fb64e 100644 --- a/demo/demo-cse-v1/test-client/pom.xml +++ b/demo/demo-cse-v1/test-client/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-cse-v1 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v1-test-client @@ -52,4 +52,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java index 30200b65160..2aff8c25966 100644 --- a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java +++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java @@ -22,11 +22,12 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @Component public class ConsumerConfigIT implements CategorizedTestCase { - RestTemplate template = new RestTemplate(); + RestOperations template = new RestTemplate(); @Override public void testRestTransport() throws Exception { @@ -37,11 +38,11 @@ public void testRestTransport() throws Exception { @SuppressWarnings("unchecked") private void testConfig() { String result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v1.test.foo", String.class); - TestMgr.check("\"foo\"", result); + TestMgr.check("foo", result); result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v1.test.bar", String.class); - TestMgr.check("\"bar\"", result); + TestMgr.check("bar", result); result = template.getForObject(Config.GATEWAY_URL + "/dynamicString?key=cse.v1.test.dynamicString", String.class); - TestMgr.check("\"a,b\"", result); + TestMgr.check("a,b", result); List listResult = template .getForObject(Config.GATEWAY_URL + "/dynamicArray", List.class); @@ -52,8 +53,8 @@ private void testConfig() { private void testFooBar() { String result = template.getForObject(Config.GATEWAY_URL + "/foo", String.class); - TestMgr.check("\"foo\"", result); + TestMgr.check("foo", result); result = template.getForObject(Config.GATEWAY_URL + "/bar", String.class); - TestMgr.check("\"bar\"", result); + TestMgr.check("bar", result); } } diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java index 124df7712ab..691ee47a162 100644 --- a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java +++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java @@ -24,17 +24,24 @@ 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 HelloWorldIT implements CategorizedTestCase { - RestTemplate template = new RestTemplate(); + RestOperations template = new RestTemplate(); @Override public void testRestTransport() throws Exception { + testHelloWorldFallback(); + testHelloWorldNoHeader(); testHelloWorld(); testHelloWorldCanary(); + testHelloWorldEmptyProtectionCloseWeight100(); + testHelloWorldeEmptyProtectionCloseWeightLess100(); + testHelloWorldEmptyProtectionCloseFallback(); + testHelloWorldEmptyProtectionCloseWeight100Two(); } private void testHelloWorld() { @@ -44,7 +51,7 @@ private void testHelloWorld() { HttpEntity entity = new HttpEntity<>(headers); String result = template .exchange(Config.GATEWAY_URL + "/sayHello?name=World", HttpMethod.GET, entity, String.class).getBody(); - TestMgr.check("\"Hello World\"", result); + TestMgr.check("Hello World", result); } } @@ -56,6 +63,30 @@ private void testHelloWorldCanary() { MultiValueMap headers = new HttpHeaders(); headers.add("canary", "new"); HttpEntity entity = new HttpEntity<>(headers); + String result = template + .exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, entity, String.class).getBody(); + if (result.equals("Hello Canary World")) { + oldCount++; + } else if (result.equals("Hello Canary in canary World")) { + newCount++; + } else { + TestMgr.fail("not expected result testHelloWorldCanary"); + return; + } + } + + double ratio = oldCount / (float) (oldCount + newCount); + TestMgr.check(ratio > 0.1 && ratio < 0.3, true); + } + + private void testHelloWorldFallback() { + int oldCount = 0; + int newCount = 0; + + for (int i = 0; i < 20; i++) { + MultiValueMap headers = new HttpHeaders(); + headers.add("canary", "fallback"); + HttpEntity entity = new HttpEntity<>(headers); String result = template .exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, entity, String.class).getBody(); if (result.equals("\"Hello Canary World\"")) { @@ -69,6 +100,105 @@ private void testHelloWorldCanary() { } double ratio = oldCount / (float) (oldCount + newCount); - TestMgr.check(ratio > 0.1 && ratio < 0.3, true); + TestMgr.check(Math.abs(ratio - 0.2) <= 0.1, true); + } + + private void testHelloWorldNoHeader() { + int oldCount = 0; + int newCount = 0; + + for (int i = 0; i < 20; i++) { + String result = template + .getForObject(Config.GATEWAY_URL + "/sayHelloCanary?name=World", String.class); + if (result.equals("\"Hello Canary World\"")) { + oldCount++; + } else if (result.equals("\"Hello Canary in canary World\"")) { + newCount++; + } else { + TestMgr.fail("not expected result testHelloWorldCanary"); + return; + } + } + + double ratio = oldCount / (float) (oldCount + newCount); + TestMgr.check(Double.compare(ratio, 0.5) == 0, true); + } + + private void testHelloWorldEmptyProtectionCloseWeight100() { + int failCount = 0; + + for (int i = 0; i < 20; i++) { + MultiValueMap headers = new HttpHeaders(); + headers.add("canary", "emptyProtectionClose100"); + HttpEntity entity = new HttpEntity<>(headers); + try { + template.exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, + entity, String.class); + } catch (Exception e) { + failCount++; + } + } + + TestMgr.check(failCount == 20, true); + } + + private void testHelloWorldeEmptyProtectionCloseWeightLess100() { + int failCount = 0; + int succCount = 0; + + for (int i = 0; i < 20; i++) { + MultiValueMap headers = new HttpHeaders(); + headers.add("canary", "emptyProtectionCloseLess100"); + HttpEntity entity = new HttpEntity<>(headers); + try { + template.exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, + entity, String.class); + succCount++; + } catch (Exception e) { + failCount++; + } + } + + TestMgr.check(succCount == 20, true); + } + + private void testHelloWorldEmptyProtectionCloseFallback() { + int failCount = 0; + int succCount = 0; + + for (int i = 0; i < 20; i++) { + MultiValueMap headers = new HttpHeaders(); + headers.add("canary", "emptyProtectionCloseFallback"); + HttpEntity entity = new HttpEntity<>(headers); + try { + template.exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, + entity, String.class); + succCount++; + } catch (Exception e) { + failCount++; + } + } + + TestMgr.check(succCount == 20, true); + } + + private void testHelloWorldEmptyProtectionCloseWeight100Two() { + int failCount = 0; + int succCount = 0; + + for (int i = 0; i < 20; i++) { + MultiValueMap headers = new HttpHeaders(); + headers.add("canary", "emptyProtectionClose100-2"); + HttpEntity entity = new HttpEntity<>(headers); + try { + template.exchange(Config.GATEWAY_URL + "/sayHelloCanary?name=World", HttpMethod.GET, + entity, String.class); + succCount++; + } catch (Exception e) { + failCount++; + } + } + + TestMgr.check(failCount == succCount, true); } } diff --git a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java index f2a67a3fd9d..10d62c6bba4 100644 --- a/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java +++ b/demo/demo-cse-v1/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java @@ -19,7 +19,6 @@ import org.apache.servicecomb.demo.CategorizedTestCaseRunner; import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.WebApplicationType; @@ -27,7 +26,6 @@ import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class TestClientApplication { private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class); diff --git a/demo/demo-cse-v1/test-client/src/main/resources/application.yml b/demo/demo-cse-v1/test-client/src/main/resources/application.yml index 63c28aa2d49..13ffddc60b8 100644 --- a/demo/demo-cse-v1/test-client/src/main/resources/application.yml +++ b/demo/demo-cse-v1/test-client/src/main/resources/application.yml @@ -23,10 +23,10 @@ servicecomb: application: demo-java-chassis-cse-v1 name: test-client version: 0.0.1 - registry: + registry: + sc: address: https://cse.cn-south-1.myhuaweicloud.com - instance: - watch: false + watch: false config: client: serverUri: https://cse.cn-south-1.myhuaweicloud.com @@ -40,4 +40,4 @@ servicecomb: accessKey: ${CREDENTIALS_AK} secretKey: ${CREDENTIALS_SK} akskCustomCipher: default - project: cn-south-1 \ No newline at end of file + project: cn-south-1 diff --git a/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml b/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml index 56fc9a0a676..9ac74305e0c 100644 --- a/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v1/test-client/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/README.md b/demo/demo-cse-v2/README.md index 299043ec3da..dda7dee702e 100644 --- a/demo/demo-cse-v2/README.md +++ b/demo/demo-cse-v2/README.md @@ -1,15 +1,15 @@ # 使用微服务引擎2.0的测试用例 -* 参考:https://github.com/apache/servicecomb-service-center/tree/master/ux 安装微服务引擎2.0 +* 参考:https://support.huaweicloud.com/devg-cse/cse_devg_0036.html 安装微服务引擎2.0 * 设置环境变量: - * CSE_V2_SC: 注册中心的地址 - * CSE_V2_CC: 配置中心的地址 + * PAAS_CSE_SC_ENDPOINT: 注册中心的地址 + * PAAS_CSE_CC_ENDPOINT: 配置中心的地址 * 依次启动 provider、consumer、gateway * 在配置中心增加如下配置: - * 应用级配置:consumer.yaml。类型为 yaml。 +* 应用级配置:consumer.yaml。类型为 yaml。 ```yaml cse: @@ -18,7 +18,7 @@ cse: foo: foo ``` - * 自定义配置:priority1.yaml。label信息: public=default 。类型为 yaml。 + * 自定义配置:priority1.yaml。label信息: public=default 。类型为 yaml。 ```yaml cse: v2: @@ -27,7 +27,7 @@ cse: common: common ``` - * 自定义配置:priority1.yaml。label信息: public=default,extra=default 。类型为 yaml。 + * 自定义配置:priority1.yaml。label信息: public=default,extra=default 。类型为 yaml。 ```yaml cse: v2: @@ -36,7 +36,7 @@ cse: extra: common ``` - * 应用级配置:priority2.yaml。类型为 yaml。 + * 应用级配置:priority2.yaml。类型为 yaml。 ```yaml cse: v2: @@ -44,7 +44,7 @@ cse: priority: v2 ``` - * 服务级配置:priority3.yaml,微服务性选择consumer。类型为 yaml。 + * 服务级配置:priority3.yaml,微服务性选择consumer。类型为 yaml。 ```yaml cse: v2: @@ -52,20 +52,28 @@ cse: priority: v3 ``` - * 自定义配置:priority3.yaml,labels: app=demo-java-chassis-cse-v2,environment=,service=consumer,extra=。类型为 yaml。 +* 应用级配置:consumerApp.yaml,应用选择demo-java-chassis-cse-v2。类型为 yaml。 ```yaml cse: v2: test: - priority: v4 + priority1: v1 ``` - * 应用级配置: cse.v2.test.bar: bar 。 类型为 text。 - +* 服务级配置:consumerService.yaml,微服务性选择consumer。类型为 yaml。 +```yaml +cse: + v2: + test: + priority1: v2 +``` + + * 应用级配置: cse.v2.test.bar: bar 。 类型为 text。 + * 执行 tests-client 里面的集成测试用例 (成功) * 修改 - * priority1.yaml。label信息: public=default 。类型为 yaml。 + * priority1.yaml。label信息: public=default 。类型为 yaml。 ```yaml cse: v2: @@ -73,10 +81,10 @@ cse: priority: v4 ``` -* 执行 tests-client 里面的集成测试用例 (成功) +* 执行 tests-client 里面的集成测试用例 (成功) * 修改 - * 应用级priority3.yaml。 + * 应用级priority3.yaml。 ```yaml cse: v2: @@ -84,10 +92,10 @@ cse: priority: v5 ``` -* 执行 tests-client 里面的集成测试用例 (失败) +* 执行 tests-client 里面的集成测试用例 (失败) * 修改 - * 应用级priority3.yaml。label信息: + * 应用级priority3.yaml。label信息: ```yaml cse: v2: @@ -95,4 +103,35 @@ cse: priority: v3 ``` -* 执行 tests-client 里面的集成测试用例 (成功) \ No newline at end of file +* 执行 tests-client 里面的集成测试用例 (成功) +* 修改 + * 应用级consumerApp.yaml。 +```yaml +cse: + v2: + test: + priority1: v10 +``` + +* 执行 tests-client 里面的集成测试用例 (成功) +* 修改 + * 服务级配置:consumerService.yaml。 +```yaml +cse: + v2: + test: + priority1: v20 +``` + +* 执行 tests-client 里面的集成测试用例 (成功) + +* 修改 + * 版本级配置:consumerIns.yaml。 +```yaml +cse: + v2: + test: + priority1: v30 +``` + +* 执行 tests-client 里面的集成测试用例 (失败) diff --git a/demo/demo-cse-v2/consumer/pom.xml b/demo/demo-cse-v2/consumer/pom.xml index a845d2b3a03..0fe6e05f4d0 100644 --- a/demo/demo-cse-v2/consumer/pom.xml +++ b/demo/demo-cse-v2/consumer/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-cse-v2 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v2-consumer @@ -44,4 +44,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java index 0010f13c817..3e7a2a0e285 100644 --- a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java +++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java @@ -17,14 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ConsumerApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java index 7cd564d96ca..8c3c45d24a3 100644 --- a/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java +++ b/demo/demo-cse-v2/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerConfigController.java @@ -27,12 +27,16 @@ @RestSchema(schemaId = "ConsumerConfigController") @RequestMapping(path = "/") public class ConsumerConfigController { - @Autowired private Environment environment; - @Autowired private ConsumerConfigurationProperties consumerConfigurationProperties; + @Autowired + public ConsumerConfigController(Environment environment, ConsumerConfigurationProperties consumerConfigurationProperties) { + this.environment = environment; + this.consumerConfigurationProperties = consumerConfigurationProperties; + } + @GetMapping("/config") public String config(@RequestParam("key") String key) { return environment.getProperty(key); diff --git a/demo/demo-cse-v2/consumer/src/main/resources/application.yml b/demo/demo-cse-v2/consumer/src/main/resources/application.yml index 72a6dafadb5..5982bb668b5 100644 --- a/demo/demo-cse-v2/consumer/src/main/resources/application.yml +++ b/demo/demo-cse-v2/consumer/src/main/resources/application.yml @@ -24,15 +24,14 @@ servicecomb: application: demo-java-chassis-cse-v2 name: consumer version: 0.0.1 - registry: - address: ${CSE_V2_SC} - instance: - watch: false + registry: + sc: + address: ${PAAS_CSE_SC_ENDPOINT:http://127.0.0.1:30100} + watch: false kie: - serverUri: ${CSE_V2_CC} + serverUri: ${PAAS_CSE_CC_ENDPOINT:http://127.0.0.1:30110} customLabel: public customLabelValue: default rest: address: 0.0.0.0:9092 # should be same with server.port to use web container - diff --git a/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml b/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml index 313d1fcec1f..4e54783856a 100644 --- a/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v2/consumer/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/gateway/pom.xml b/demo/demo-cse-v2/gateway/pom.xml index a226e8e1f66..1d04a248410 100644 --- a/demo/demo-cse-v2/gateway/pom.xml +++ b/demo/demo-cse-v2/gateway/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-cse-v2 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v2-gateway @@ -47,4 +47,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java index f2e086b4235..7d58caafd9d 100644 --- a/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java +++ b/demo/demo-cse-v2/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java @@ -17,13 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class GatewayApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v2/gateway/src/main/resources/application.yml b/demo/demo-cse-v2/gateway/src/main/resources/application.yml index b7d95e47e5c..32d2a728d76 100644 --- a/demo/demo-cse-v2/gateway/src/main/resources/application.yml +++ b/demo/demo-cse-v2/gateway/src/main/resources/application.yml @@ -24,12 +24,13 @@ servicecomb: application: demo-java-chassis-cse-v2 name: gateway version: 0.0.1 - registry: - address: ${CSE_V2_SC} - instance: - watch: false + registry: + sc: + address: ${PAAS_CSE_SC_ENDPOINT:http://127.0.0.1:30100} + watch: false + kie: - serverUri: ${CSE_V2_CC} + serverUri: ${PAAS_CSE_CC_ENDPOINT:http://127.0.0.1:30110} customLabel: public rest: @@ -49,11 +50,3 @@ servicecomb: path: "/.*" microserviceName: consumer versionRule: 0.0.0+ - - # Configure AK/SK credentials if needed. Default not enabled. - credentials: - akskEnabled: true - accessKey: ${CREDENTIALS_AK} - secretKey: ${CREDENTIALS_SK} - akskCustomCipher: default - project: cn-south-1 \ No newline at end of file diff --git a/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml b/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml index e9bb2656f8f..165cdf7e0a3 100644 --- a/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v2/gateway/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/pom.xml b/demo/demo-cse-v2/pom.xml index ad519788d91..35a623930da 100644 --- a/demo/demo-cse-v2/pom.xml +++ b/demo/demo-cse-v2/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-cse-v2 Java Chassis::Demo::CSE-V2 @@ -39,7 +39,19 @@ org.apache.servicecomb - servicestage-environment + config-kie + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core @@ -50,4 +62,4 @@ test-client - \ No newline at end of file + diff --git a/demo/demo-cse-v2/provider/pom.xml b/demo/demo-cse-v2/provider/pom.xml index b95fb7e1593..4308b1169d9 100644 --- a/demo/demo-cse-v2/provider/pom.xml +++ b/demo/demo-cse-v2/provider/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-cse-v2 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v2-provider @@ -48,4 +48,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java index 6542bcedfbf..fde6f36b2e3 100644 --- a/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java +++ b/demo/demo-cse-v2/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java @@ -17,14 +17,11 @@ package org.apache.servicecomb.samples; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ProviderApplication { public static void main(String[] args) throws Exception { try { diff --git a/demo/demo-cse-v2/provider/src/main/resources/application.yml b/demo/demo-cse-v2/provider/src/main/resources/application.yml index 991bf6d7de0..bb55de45abc 100644 --- a/demo/demo-cse-v2/provider/src/main/resources/application.yml +++ b/demo/demo-cse-v2/provider/src/main/resources/application.yml @@ -27,14 +27,13 @@ servicecomb: application: demo-java-chassis-cse-v2 name: provider version: 0.0.1 - registry: - address: ${CSE_V2_SC} - instance: - watch: false + registry: + sc: + address: ${PAAS_CSE_SC_ENDPOINT:http://127.0.0.1:30100} + watch: false kie: - serverUri: ${CSE_V2_CC} + serverUri: ${PAAS_CSE_CC_ENDPOINT:http://127.0.0.1:30110} customLabel: public rest: address: 0.0.0.0:9093 # should be same with server.port to use web container - diff --git a/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml b/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml index 56fc9a0a676..9ac74305e0c 100644 --- a/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v2/provider/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/test-client/pom.xml b/demo/demo-cse-v2/test-client/pom.xml index f935bf20b34..78917aa7e5c 100644 --- a/demo/demo-cse-v2/test-client/pom.xml +++ b/demo/demo-cse-v2/test-client/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-cse-v2 - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT cse-v2-test-client @@ -52,4 +52,4 @@ - \ No newline at end of file + diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java index 18011c4108e..16b1388641a 100644 --- a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java +++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/ConsumerConfigIT.java @@ -20,11 +20,12 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @Component public class ConsumerConfigIT implements CategorizedTestCase { - RestTemplate template = new RestTemplate(); + RestOperations template = new RestTemplate(); @Override public void testRestTransport() throws Exception { @@ -34,27 +35,29 @@ public void testRestTransport() throws Exception { private void testConfig() { String result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.foo", String.class); - TestMgr.check("\"foo\"", result); + TestMgr.check("foo", result); result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.bar", String.class); - TestMgr.check("\"bar\"", result); + TestMgr.check("bar", result); result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.priority", String.class); - TestMgr.check("\"v3\"", result); + TestMgr.check("v1", result); result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.common", String.class); - TestMgr.check("\"common\"", result); + TestMgr.check("common", result); result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.extra", String.class); - TestMgr.check("\"common\"", result); + TestMgr.check("common", result); + result = template.getForObject(Config.GATEWAY_URL + "/config?key=cse.v2.test.priority1", String.class); + TestMgr.check("v2", result); } private void testFooBar() { String result = template.getForObject(Config.GATEWAY_URL + "/bar", String.class); - TestMgr.check("\"bar\"", result); + TestMgr.check("bar", result); result = template.getForObject(Config.GATEWAY_URL + "/foo", String.class); - TestMgr.check("\"foo\"", result); + TestMgr.check("foo", result); result = template.getForObject(Config.GATEWAY_URL + "/priority", String.class); - TestMgr.check("\"v3\"", result); + TestMgr.check("v1", result); result = template.getForObject(Config.GATEWAY_URL + "/common", String.class); - TestMgr.check("\"common\"", result); + TestMgr.check("common", result); result = template.getForObject(Config.GATEWAY_URL + "/extra", String.class); - TestMgr.check("\"common\"", result); + TestMgr.check("common", result); } } diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java index bce14568675..59d06bb1e01 100644 --- a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java +++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java @@ -20,11 +20,12 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @Component public class HelloWorldIT implements CategorizedTestCase { - RestTemplate template = new RestTemplate(); + RestOperations template = new RestTemplate(); @Override public void testRestTransport() throws Exception { @@ -34,6 +35,6 @@ public void testRestTransport() throws Exception { private void testHelloWorld() { String result = template .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class); - TestMgr.check("\"Hello World\"", result); + TestMgr.check("Hello World", result); } } diff --git a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java index f2a67a3fd9d..10d62c6bba4 100644 --- a/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java +++ b/demo/demo-cse-v2/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java @@ -19,7 +19,6 @@ import org.apache.servicecomb.demo.CategorizedTestCaseRunner; import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.WebApplicationType; @@ -27,7 +26,6 @@ import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class TestClientApplication { private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class); diff --git a/demo/demo-cse-v2/test-client/src/main/resources/application.yml b/demo/demo-cse-v2/test-client/src/main/resources/application.yml index f185d07a6d4..046fa53ee6b 100644 --- a/demo/demo-cse-v2/test-client/src/main/resources/application.yml +++ b/demo/demo-cse-v2/test-client/src/main/resources/application.yml @@ -27,21 +27,13 @@ servicecomb: application: demo-java-chassis-cse-v2 name: test-client version: 0.0.1 - registry: - address: https://cse.cn-south-1.myhuaweicloud.com - instance: - watch: false - config: - client: - serverUri: https://cse.cn-south-1.myhuaweicloud.com + registry: + sc: + address: ${PAAS_CSE_SC_ENDPOINT:http://127.0.0.1:30100} + watch: false + kie: + serverUri: ${PAAS_CSE_CC_ENDPOINT:http://127.0.0.1:30110} + customLabel: public rest: address: 0.0.0.0:9097 # should be same with server.port to use web container - - # Configure AK/SK credentials if needed. Default not enabled. - credentials: - akskEnabled: true - accessKey: ${CREDENTIALS_AK} - secretKey: ${CREDENTIALS_SK} - akskCustomCipher: default - project: cn-south-1 \ No newline at end of file diff --git a/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml b/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml index 56fc9a0a676..9ac74305e0c 100644 --- a/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml +++ b/demo/demo-cse-v2/test-client/src/main/resources/log4j2.xml @@ -42,4 +42,4 @@ - \ No newline at end of file + diff --git a/demo/demo-edge/README.md b/demo/demo-edge/README.md new file mode 100644 index 00000000000..b5a552e0668 --- /dev/null +++ b/demo/demo-edge/README.md @@ -0,0 +1,17 @@ +# About edge service API compatibility + +* Edge service use the latest version of the microservice meta. e.g. For business 1.0.0, 1.1.0, 2.0.0 have the following APIs: + + * 1.0.0: /business/v1/add + * 1.1.0: /business/v1/add, /business/v1/dec + * 2.0.0: /business/v2/add, /business/v2/dec + + If users invoke /business/v1/add, edge service will give NOT FOUND, because 2.0.0 microservice meta do not have this API. Even using router to route all /business/v1/* requests to 1.1.0, path locating happens before load balance. + +* It's very important to keep your API compatibility cross versions if these versions need work together. e.g. + + * 1.0.0: /business/v1/add + * 1.1.0: /business/v1/add, /business/v1/dec + * 2.0.0: /business/v1/add, /business/v1/dec, /business/v2/add, /business/v2/dec + + Together with router, /business/v1/add will go correctly to 1.0.0 or 1.1.0, and /business/v2/add will go correctly to 2.0.0. Without router, /business/v2/add may route to 1.0.0 or 1.1.0 and NOT FOUND is reported. diff --git a/demo/demo-edge/authentication/pom.xml b/demo/demo-edge/authentication/pom.xml index de41f675184..4849faf28fe 100644 --- a/demo/demo-edge/authentication/pom.xml +++ b/demo/demo-edge/authentication/pom.xml @@ -21,19 +21,11 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT authentication Java Chassis::Demo::Edge::Authentication - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - transport-rest-vertx - org.apache.servicecomb.demo.edge.authentication.AuthMain @@ -41,21 +33,8 @@ - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -64,15 +43,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-edge/authentication/src/main/java/org/apache/servicecomb/demo/edge/authentication/AuthMain.java b/demo/demo-edge/authentication/src/main/java/org/apache/servicecomb/demo/edge/authentication/AuthMain.java index 734db1e273d..4928706edcd 100644 --- a/demo/demo-edge/authentication/src/main/java/org/apache/servicecomb/demo/edge/authentication/AuthMain.java +++ b/demo/demo-edge/authentication/src/main/java/org/apache/servicecomb/demo/edge/authentication/AuthMain.java @@ -17,12 +17,13 @@ package org.apache.servicecomb.demo.edge.authentication; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +@SpringBootApplication public class AuthMain { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(AuthMain.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-edge/authentication/src/main/resources/log4j2.xml b/demo/demo-edge/authentication/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-edge/authentication/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-edge/authentication/src/main/resources/microservice.yaml b/demo/demo-edge/authentication/src/main/resources/microservice.yaml index aed5cc96fb2..038b64eb1ec 100644 --- a/demo/demo-edge/authentication/src/main/resources/microservice.yaml +++ b/demo/demo-edge/authentication/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: edge -service_description: - name: auth - version: 0.0.1 servicecomb: service: - registry: + application: edge + name: auth + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:7070?protocol=http2 diff --git a/demo/demo-edge/business-1-1-0/pom.xml b/demo/demo-edge/business-1-1-0/pom.xml index 959457549d5..1cef9b01cab 100644 --- a/demo/demo-edge/business-1-1-0/pom.xml +++ b/demo/demo-edge/business-1-1-0/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT business-1-1-0 Java Chassis::Demo::Edge::Business 1.1.0 @@ -30,18 +30,6 @@ - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-rest-servlet - org.apache.servicecomb.demo model @@ -51,21 +39,8 @@ - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -74,15 +49,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_1_0.java b/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_1_0.java index 2e92e7b9ba0..f725fa24e0e 100644 --- a/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_1_0.java +++ b/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_1_0.java @@ -17,12 +17,13 @@ package org.apache.servicecomb.demo.edge.business; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +@SpringBootApplication public class BusinessMain_V1_1_0 { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(BusinessMain_V1_1_0.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java b/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java index 0c5c18e0dee..38420d285d6 100644 --- a/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java +++ b/demo/demo-edge/business-1-1-0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java @@ -21,6 +21,8 @@ import org.apache.servicecomb.demo.edge.model.ChannelRequestBase; import org.apache.servicecomb.demo.edge.model.ResultWithInstance; import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -28,6 +30,13 @@ @RestSchema(schemaId = "news-v1") @RequestMapping(path = "/business/v1") public class Impl { + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + @RequestMapping(path = "/channel/news/subscribe", method = RequestMethod.POST) public AppClientDataRsp subscribeNewsColumn(@RequestBody ChannelRequestBase request) { AppClientDataRsp response = new AppClientDataRsp(); @@ -38,11 +47,11 @@ public AppClientDataRsp subscribeNewsColumn(@RequestBody ChannelRequestBase requ @RequestMapping(path = "/add", method = RequestMethod.GET) public ResultWithInstance add(int x, int y) { - return ResultWithInstance.create(x + y); + return ResultWithInstance.create(x + y, environment); } @RequestMapping(path = "/dec", method = RequestMethod.GET) public ResultWithInstance dec(int x, int y) { - return ResultWithInstance.create(x - y); + return ResultWithInstance.create(x - y, environment); } } diff --git a/demo/demo-edge/business-1-1-0/src/main/resources/log4j2.xml b/demo/demo-edge/business-1-1-0/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-edge/business-1-1-0/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-edge/business-1-1-0/src/main/resources/microservice.yaml b/demo/demo-edge/business-1-1-0/src/main/resources/microservice.yaml index 3ea33d77160..0fa3a1764e4 100644 --- a/demo/demo-edge/business-1-1-0/src/main/resources/microservice.yaml +++ b/demo/demo-edge/business-1-1-0/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: edge -service_description: - name: business - version: 1.1.0 servicecomb: service: - registry: + application: edge + name: business + version: 1.1.0 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8090 diff --git a/demo/demo-edge/business-1.0.0/pom.xml b/demo/demo-edge/business-1.0.0/pom.xml index 11197659180..d7e35748fef 100644 --- a/demo/demo-edge/business-1.0.0/pom.xml +++ b/demo/demo-edge/business-1.0.0/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT business-1-0-0 Java Chassis::Demo::Edge::Business 1.0.0 @@ -32,18 +32,6 @@ - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-rest-servlet - org.apache.servicecomb.demo model @@ -53,21 +41,8 @@ - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -76,15 +51,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_0_0.java b/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_0_0.java index 83ef6309ec7..e1a57c7e8b1 100644 --- a/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_0_0.java +++ b/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V1_0_0.java @@ -17,12 +17,13 @@ package org.apache.servicecomb.demo.edge.business; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +@SpringBootApplication public class BusinessMain_V1_0_0 { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(BusinessMain_V1_0_0.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java b/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java index 9ce38698699..1e0d1b84bb8 100644 --- a/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java +++ b/demo/demo-edge/business-1.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java @@ -21,6 +21,8 @@ import org.apache.servicecomb.demo.edge.model.ChannelRequestBase; import org.apache.servicecomb.demo.edge.model.ResultWithInstance; import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -28,6 +30,13 @@ @RestSchema(schemaId = "news-v1") @RequestMapping(path = "/business/v1") public class Impl { + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + @RequestMapping(path = "/channel/news/subscribe", method = RequestMethod.POST) public AppClientDataRsp subscribeNewsColumn(@RequestBody ChannelRequestBase request) { AppClientDataRsp response = new AppClientDataRsp(); @@ -38,6 +47,6 @@ public AppClientDataRsp subscribeNewsColumn(@RequestBody ChannelRequestBase requ @RequestMapping(path = "/add", method = RequestMethod.GET) public ResultWithInstance add(int x, int y) { - return ResultWithInstance.create(x + y); + return ResultWithInstance.create(x + y, environment); } } diff --git a/demo/demo-edge/business-1.0.0/src/main/resources/log4j2.xml b/demo/demo-edge/business-1.0.0/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-edge/business-1.0.0/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-edge/business-1.0.0/src/main/resources/microservice.yaml b/demo/demo-edge/business-1.0.0/src/main/resources/microservice.yaml index d85b4b5cd8d..cc3c45ed92c 100644 --- a/demo/demo-edge/business-1.0.0/src/main/resources/microservice.yaml +++ b/demo/demo-edge/business-1.0.0/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: edge -service_description: - name: business - version: 1.0.0 servicecomb: service: - registry: + application: edge + name: business + version: 1.0.0 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8080 diff --git a/demo/demo-edge/business-2.0.0/pom.xml b/demo/demo-edge/business-2.0.0/pom.xml index 92bedf720a1..3500be47d75 100644 --- a/demo/demo-edge/business-2.0.0/pom.xml +++ b/demo/demo-edge/business-2.0.0/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT business-2-0-0 Java Chassis::Demo::Edge::Business 2.0.0 @@ -32,18 +32,6 @@ - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-rest-servlet - org.apache.servicecomb.demo model @@ -53,21 +41,8 @@ - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -76,15 +51,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V2_0_0.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V2_0_0.java index 04646157e56..81559ce431f 100644 --- a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V2_0_0.java +++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/BusinessMain_V2_0_0.java @@ -17,12 +17,13 @@ package org.apache.servicecomb.demo.edge.business; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +@SpringBootApplication public class BusinessMain_V2_0_0 { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(BusinessMain_V2_0_0.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/EdgeServiceGovernanceService.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/EdgeServiceGovernanceService.java new file mode 100644 index 00000000000..f8d951cd226 --- /dev/null +++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/EdgeServiceGovernanceService.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.demo.edge.business; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +@RestSchema(schemaId = "EdgeServiceGovernanceService") +@RequestMapping(path = "/business/v2") +public class EdgeServiceGovernanceService { + private static final Logger LOGGER = LoggerFactory.getLogger(EdgeServiceGovernanceService.class); + + private Map retryTimes = new HashMap<>(); + + private AtomicInteger instanceIsolationIndex = new AtomicInteger(); + + @GetMapping("/testEdgeServiceRetry") + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)), description = ""), + @ApiResponse(responseCode = "502", content = @Content(schema = @Schema(implementation = String.class)), description = "")}) + public String testEdgeServiceRetry(@RequestParam(name = "invocationID") String invocationID) { + LOGGER.info("invoke service: {}", invocationID); + retryTimes.putIfAbsent(invocationID, 0); + retryTimes.put(invocationID, retryTimes.get(invocationID) + 1); + + int retry = retryTimes.get(invocationID); + + if (retry == 3) { + return "try times: " + retry; + } + throw new InvocationException(502, "retry", "retry"); + } + + @GetMapping("/testEdgeServiceInstanceIsolation") + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)), description = ""), + @ApiResponse(responseCode = "502", content = @Content(schema = @Schema(implementation = String.class)), description = "")}) + public String testEdgeServiceInstanceIsolation(@RequestParam(name = "name") String name) { + if (instanceIsolationIndex.getAndIncrement() % 3 != 0) { + throw new InvocationException(502, "InstanceIsolation", "InstanceIsolation"); + } + return name; + } + + @GetMapping("/testEdgeServiceInstanceBulkhead") + public String testEdgeServiceInstanceBulkhead(@RequestParam(name = "name") String name) { + return name; + } +} diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java index 046259713b7..fde945e50bf 100644 --- a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java +++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/Impl.java @@ -17,40 +17,24 @@ package org.apache.servicecomb.demo.edge.business; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.nio.charset.StandardCharsets; - -import org.apache.commons.io.FileUtils; import org.apache.servicecomb.demo.edge.model.AppClientDataRsp; import org.apache.servicecomb.demo.edge.model.ChannelRequestBase; -import org.apache.servicecomb.demo.edge.model.DependTypeA; -import org.apache.servicecomb.demo.edge.model.RecursiveSelfType; import org.apache.servicecomb.demo.edge.model.ResultWithInstance; -import org.apache.servicecomb.demo.edge.model.User; import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; - -@RestSchema(schemaId = "news-v2") -@RequestMapping(path = "/business/v2") +@RestSchema(schemaId = "news-v1") +@RequestMapping(path = "/business/v1") public class Impl { - File tempDir = new File("target/downloadTemp"); + private Environment environment; - public Impl() throws IOException { - FileUtils.forceMkdir(tempDir); + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; } @RequestMapping(path = "/channel/news/subscribe", method = RequestMethod.POST) @@ -63,52 +47,11 @@ public AppClientDataRsp subscribeNewsColumn(@RequestBody ChannelRequestBase requ @RequestMapping(path = "/add", method = RequestMethod.GET) public ResultWithInstance add(int x, int y) { - return ResultWithInstance.create(x + y); + return ResultWithInstance.create(x + y, environment); } @RequestMapping(path = "/dec", method = RequestMethod.GET) public ResultWithInstance dec(int x, int y) { - return ResultWithInstance.create(x - y); - } - - @GetMapping(path = "/download") - @ApiResponses({ - @ApiResponse(code = 200, response = File.class, message = ""), - }) - public ResponseEntity download() throws IOException { - return ResponseEntity - .ok() - .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE) - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=download.txt") - .body(new ByteArrayInputStream("download".getBytes(StandardCharsets.UTF_8))); - } - - protected File createBigFile() throws IOException { - File file = new File(tempDir, "bigFile.txt"); - file.delete(); - RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); - randomAccessFile.setLength(10 * 1024 * 1024); - randomAccessFile.close(); - return file; - } - - @GetMapping(path = "/bigFile") - public File bigFile() throws IOException { - return createBigFile(); - } - - @PostMapping(path = "recursiveSelf") - public RecursiveSelfType recursiveSelf(@RequestBody RecursiveSelfType value) { - return value; - } - - @PostMapping(path = "dependType") - public DependTypeA dependType(@RequestBody DependTypeA value) { - return value; - } - - @PostMapping(path = "encrypt") - public User encrypt(@RequestBody User value) { - return value; + return ResultWithInstance.create(x - y, environment); } } diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/ImplV2.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/ImplV2.java new file mode 100644 index 00000000000..0e5eabf290f --- /dev/null +++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/ImplV2.java @@ -0,0 +1,125 @@ +/* + * 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.demo.edge.business; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.RandomAccessFile; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.FileUtils; +import org.apache.servicecomb.demo.edge.model.AppClientDataRsp; +import org.apache.servicecomb.demo.edge.model.ChannelRequestBase; +import org.apache.servicecomb.demo.edge.model.DependTypeA; +import org.apache.servicecomb.demo.edge.model.RecursiveSelfType; +import org.apache.servicecomb.demo.edge.model.ResultWithInstance; +import org.apache.servicecomb.demo.edge.model.User; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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.RequestMethod; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +@RestSchema(schemaId = "news-v2") +@RequestMapping(path = "/business/v2") +public class ImplV2 { + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + File tempDir = new File("target/downloadTemp"); + + public ImplV2() throws IOException { + FileUtils.forceMkdir(tempDir); + } + + @RequestMapping(path = "/channel/news/subscribe", method = RequestMethod.POST) + public AppClientDataRsp subscribeNewsColumn(@RequestBody ChannelRequestBase request) { + AppClientDataRsp response = new AppClientDataRsp(); + String rsp = "result from 2.0.0"; + response.setRsp(rsp); + return response; + } + + @RequestMapping(path = "/add", method = RequestMethod.GET) + public ResultWithInstance add(int x, int y) { + return ResultWithInstance.create(x + y, environment); + } + + @RequestMapping(path = "/dec", method = RequestMethod.GET) + public ResultWithInstance dec(int x, int y) { + return ResultWithInstance.create(x - y, environment); + } + + @GetMapping(path = "/download") + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = File.class)), description = ""), + }) + public ResponseEntity download() throws IOException { + return ResponseEntity + .ok() + .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=download.txt") + .body(new ByteArrayInputStream("download".getBytes(StandardCharsets.UTF_8))); + } + + protected File createBigFile() throws IOException { + File file = new File(tempDir, "bigFile.txt"); + file.delete(); + RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); + randomAccessFile.setLength(10 * 1024 * 1024); + randomAccessFile.close(); + return file; + } + + @GetMapping(path = "/bigFile") + public File bigFile() throws IOException { + return createBigFile(); + } + + @PostMapping(path = "recursiveSelf") + public RecursiveSelfType recursiveSelf(@RequestBody RecursiveSelfType value) { + return value; + } + + @PostMapping(path = "dependType") + public DependTypeA dependType(@RequestBody DependTypeA value) { + return value; + } + + @PostMapping(path = "encrypt") + public User encrypt(@RequestBody User value) { + return value; + } +} diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToProducerResponseConverter.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToProducerResponseConverter.java index 9894b6d37b7..9fd5aeec777 100644 --- a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToProducerResponseConverter.java +++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/CustomExceptionToProducerResponseConverter.java @@ -17,18 +17,18 @@ package org.apache.servicecomb.demo.edge.business.error; -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.SwaggerInvocation; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.exception.ExceptionConverter; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.StatusType; + public class CustomExceptionToProducerResponseConverter implements - ExceptionToProducerResponseConverter { + ExceptionConverter { @Override - public Class getExceptionClass() { - return IllegalStateException.class; + public boolean canConvert(Throwable throwable) { + return throwable instanceof IllegalStateException; } @Override @@ -37,12 +37,12 @@ public int getOrder() { } @Override - public Response convert(SwaggerInvocation swaggerInvocation, IllegalStateException e) { + public InvocationException convert(Invocation invocation, IllegalStateException e, + StatusType genericStatus) { IllegalStateErrorData data = new IllegalStateErrorData(); data.setId(500); data.setMessage(e.getMessage()); data.setState(e.getMessage()); - InvocationException state = new InvocationException(Status.INTERNAL_SERVER_ERROR, data); - return Response.failResp(state); + return new InvocationException(Status.INTERNAL_SERVER_ERROR, data); } } diff --git a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java index 8bdba9c2bc3..f4b56e58782 100644 --- a/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java +++ b/demo/demo-edge/business-2.0.0/src/main/java/org/apache/servicecomb/demo/edge/business/error/ErrorService.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.demo.edge.business.error; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; diff --git a/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter b/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter new file mode 100644 index 00000000000..2675a9b60dd --- /dev/null +++ b/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter @@ -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.servicecomb.demo.edge.business.error.CustomExceptionToProducerResponseConverter diff --git a/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter b/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter deleted file mode 100644 index 1633f696818..00000000000 --- a/demo/demo-edge/business-2.0.0/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.exception.ExceptionToProducerResponseConverter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.demo.edge.business.error.CustomExceptionToProducerResponseConverter \ No newline at end of file diff --git a/demo/demo-edge/business-2.0.0/src/main/resources/log4j2.xml b/demo/demo-edge/business-2.0.0/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-edge/business-2.0.0/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-edge/business-2.0.0/src/main/resources/microservice.yaml b/demo/demo-edge/business-2.0.0/src/main/resources/microservice.yaml index 2866854302f..45a9f2ff743 100644 --- a/demo/demo-edge/business-2.0.0/src/main/resources/microservice.yaml +++ b/demo/demo-edge/business-2.0.0/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: edge -service_description: - name: business - version: 2.0.0 servicecomb: service: - registry: + application: edge + name: business + version: 2.0.0 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8091 diff --git a/demo/demo-edge/consumer/pom.xml b/demo/demo-edge/consumer/pom.xml index f6479c223b9..c26ca048528 100644 --- a/demo/demo-edge/consumer/pom.xml +++ b/demo/demo-edge/consumer/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT consumer Java Chassis::Demo::Edge::Consumer @@ -32,22 +32,6 @@ - - org.apache.servicecomb - provider-pojo - - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-rest-servlet - org.apache.servicecomb.demo demo-schema @@ -58,36 +42,212 @@ ${project.version} - - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config-edge - ${project.version} - - - - - - + docker + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + authentication:${project.version} + authentication + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/authentication-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 7070 + + + + + + 7070:7070 + + + service-center + + + + + business-1-0-0:${project.version} + business-1-0-0 + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/business-1-0-0-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 8080:8080 + + + service-center + + + + + business-1-1-0:${project.version} + business-1-1-0 + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/business-1-1-0-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8090 + + + + + + 8090:8090 + + + service-center + + + + + business-2-0-0:${project.version} + business-2-0-0 + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/business-2-0-0-${project.version}.jar + + + service-center:sc.servicecomb.io + + + Register microservice instance success + + + 8091 + + + + + + 8091:8091 + + + service-center + + + + + edge-service:${project.version} + edge-service + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/edge-service-${project.version}.jar + + + service-center:sc.servicecomb.io + + + Register microservice instance success + + + + 18090 + + + + + + 18090:18090 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java index 6d00edbd393..ab10a7c3713 100644 --- a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java +++ b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java @@ -26,6 +26,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.demo.edge.model.AppClientDataRsp; import org.apache.servicecomb.demo.edge.model.ChannelRequestBase; import org.apache.servicecomb.demo.edge.model.DependTypeA; @@ -33,12 +34,11 @@ import org.apache.servicecomb.demo.edge.model.RecursiveSelfType; import org.apache.servicecomb.demo.edge.model.ResultWithInstance; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.springframework.core.env.Environment; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; @@ -49,10 +49,10 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; public class Consumer { - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); ChannelRequestBase request = new ChannelRequestBase(); @@ -66,6 +66,10 @@ public class Consumer { List decV2Result = new ArrayList<>(); + DiscoveryManager discoveryManager = BeanUtils.getBean(DiscoveryManager.class); + + Environment environment = BeanUtils.getBean(Environment.class); + public Consumer() { request.setDeviceId("2a5cc42ff60006ac"); request.setServiceToken( @@ -141,7 +145,7 @@ public void testEncrypt() { String expected = "{name=userName, age=10, userId=serviceTokenTest-userId, body1=b1, body2=b2, body3=b3}"; Assert.isTrue(expected.equalsIgnoreCase(result.toString()), - String.format("expected: %s\nreal : %s", expected, result.toString())); + String.format("expected: %s\nreal : %s", expected, result)); } protected void testRecursiveSelf() { @@ -172,22 +176,22 @@ protected void testErrorCode() { try { Map raw = template.getForObject(url + "?x=99&y=3", Map.class); } catch (HttpServerErrorException e) { - Assert.isTrue(e.getRawStatusCode() == 500, "x99"); - Assert.isTrue(e.getResponseBodyAsString().contains("Unexpected exception when processing the request"), "x99"); + Assert.isTrue(e.getStatusCode().value() == 500, "x99"); + Assert.isTrue(e.getResponseBodyAsString().contains("un expected NPE test."), "x99"); } try { template.getForObject(url + "?x=88&y=3", Map.class); Assert.isTrue(false, "x88"); } catch (HttpClientErrorException e) { - Assert.isTrue(e.getRawStatusCode() == 403, "x88"); + Assert.isTrue(e.getStatusCode().value() == 403, "x88"); Assert.isTrue(e.getResponseBodyAsString().equals("{\"id\":12,\"message\":\"not allowed id.\"}"), "x88"); } try { template.getForObject(url + "?x=77&y=3", Map.class); Assert.isTrue(false, "x77"); } catch (HttpServerErrorException e) { - Assert.isTrue(e.getRawStatusCode() == 500, "x77"); + Assert.isTrue(e.getStatusCode().value() == 500, "x77"); Assert.isTrue(e.getResponseBodyAsString().equals("{\"id\":500,\"message\":\"77\",\"state\":\"77\"}"), "x77"); } } @@ -227,7 +231,7 @@ protected void testDownloadBigFile() { } return null; }); - Assert.isTrue(size.get() == 10 * 1024 * 1024, "size is : " + String.valueOf(size.get()) + " not 10 * 1024 * 1024"); + Assert.isTrue(size.get() == 10 * 1024 * 1024, "size is : " + size.get() + " not 10 * 1024 * 1024"); System.out.println("test download bigFile finished"); } @@ -268,23 +272,19 @@ protected void invoke(String appendUrl, int x, int y, List r } private URIEndpointObject prepareEdge(String prefix) { - Microservice microservice = RegistrationManager.INSTANCE.getMicroservice(); - MicroserviceInstance microserviceInstance = (MicroserviceInstance) DiscoveryManager.INSTANCE - .getAppManager() - .getOrCreateMicroserviceVersionRule(microservice.getAppId(), "edge", DefinitionConst.VERSION_RULE_ALL) - .getVersionedCache() - .mapData() - .values() + DiscoveryInstance instance = discoveryManager.findServiceInstances( + BootStrapProperties.readApplication(environment), "edge") .stream() .findFirst() .get(); - URIEndpointObject edgeAddress = new URIEndpointObject(microserviceInstance.getEndpoints().get(0)); + URIEndpointObject edgeAddress = new URIEndpointObject(instance.getEndpoints().get(0)); edgePrefix = String.format("http://%s:%d/%s/business", edgeAddress.getHostOrIp(), edgeAddress.getPort(), prefix); return edgeAddress; } protected void invokeBusiness(String urlPrefix, ChannelRequestBase request) { - for (int i = 0; i < 3; i++) { + List result = new ArrayList<>(6); + for (int i = 0; i < 6; i++) { String url = urlPrefix + "/channel/news/subscribe"; HttpHeaders headers = new HttpHeaders(); @@ -293,7 +293,10 @@ protected void invokeBusiness(String urlPrefix, ChannelRequestBase request) { HttpEntity entity = new HttpEntity<>(request, headers); ResponseEntity response = template.postForEntity(url, entity, AppClientDataRsp.class); - Assert.isTrue(response.getBody().getRsp().equals("result from 1.1.0"), response.getBody().getRsp()); + result.add(response.getBody().getRsp()); } + Assert.isTrue(result.contains("result from 2.0.0"), "invokeBusiness not balance"); + Assert.isTrue(result.contains("result from 1.1.0"), "invokeBusiness not balance"); + Assert.isTrue(result.contains("result from 1.0.0"), "invokeBusiness not balance"); } } diff --git a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java index 8feeaeb2cb2..ae462eb6fd1 100644 --- a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java +++ b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java @@ -17,15 +17,22 @@ package org.apache.servicecomb.demo.edge.consumer; +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.edge.model.ChannelRequestBase; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +@SpringBootApplication public class ConsumerMain { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(ConsumerMain.class).web(WebApplicationType.NONE).run(args); + runTest(); + } + + public static void runTest() throws Exception { new Consumer().testEncrypt(); new Consumer().invokeBusiness("cse://business/business/v1", new ChannelRequestBase()); @@ -35,9 +42,22 @@ public static void main(String[] args) throws Exception { new Consumer().run("rest"); System.out.println("Running url dispatcher."); new Consumer().run("url"); - System.out.println("Running http dispatcher."); - new Consumer().run("http"); +// Common Http Dispatcher do not have OperationMeta, can not use router. +// System.out.println("Running http dispatcher."); +// new Consumer().run("http"); System.out.println("All test case finished."); + + runCategorizedTest(); + + TestMgr.summary(); + if (!TestMgr.errors().isEmpty()) { + throw new IllegalStateException("tests failed"); + } + } + + private static void runCategorizedTest() throws Exception { + CategorizedTestCaseRunner + .runCategorizedTestCase("edge"); } } diff --git a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/EdgeServiceGovernanceTest.java b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/EdgeServiceGovernanceTest.java new file mode 100644 index 00000000000..ad774433957 --- /dev/null +++ b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/EdgeServiceGovernanceTest.java @@ -0,0 +1,162 @@ +/* + * 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.demo.edge.consumer; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.net.URIEndpointObject; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestOperations; + +@Component +public class EdgeServiceGovernanceTest implements CategorizedTestCase { + RestOperations template = RestTemplateBuilder.create(); + + String edgePrefix; + + @Autowired + Environment environment; + + @Autowired + DiscoveryManager discoveryManager; + + @Override + public void testRestTransport() throws Exception { + prepareEdge("url"); + // edge service do not support retry +// testEdgeServiceRetry(); + testEdgeServiceInstanceBulkhead(); + testEdgeServiceInstanceIsolation(); // may isolate instance for 5 seconds. + Thread.sleep(6000); // ensure isolation is open for new requests + } + + private void testEdgeServiceInstanceBulkhead() throws Exception { + String url = edgePrefix + "/business/v2/testEdgeServiceInstanceBulkhead"; + + CountDownLatch latch = new CountDownLatch(100); + AtomicBoolean expectedFailed503 = new AtomicBoolean(false); + AtomicBoolean notExpectedFailed = new AtomicBoolean(false); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + String name = "t-" + i + "-" + j; + new Thread(name) { + public void run() { + try { + String result = template.getForObject(url + "?name={1}", String.class, "hello"); + if (!"hello".equals(result)) { + notExpectedFailed.set(true); + } + } catch (Exception e) { + if (!(e instanceof HttpServerErrorException)) { + notExpectedFailed.set(true); + } else { + if (((HttpServerErrorException) e).getStatusCode().value() == 503) { + expectedFailed503.set(true); + } + } + } + latch.countDown(); + } + }.start(); + } + Thread.sleep(100); + } + + latch.await(20, TimeUnit.SECONDS); + TestMgr.check(true, expectedFailed503.get()); + TestMgr.check(false, notExpectedFailed.get()); + } + + private void testEdgeServiceInstanceIsolation() throws Exception { + String url = edgePrefix + "/business/v2/testEdgeServiceInstanceIsolation"; + + CountDownLatch latch = new CountDownLatch(100); + AtomicBoolean expectedFailed404 = new AtomicBoolean(false); + AtomicBoolean expectedFailed502 = new AtomicBoolean(false); + AtomicBoolean expectedFailed503 = new AtomicBoolean(false); + AtomicBoolean notExpectedFailed = new AtomicBoolean(false); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + String name = "t-" + i + "-" + j; + new Thread(name) { + public void run() { + try { + String result = template.getForObject(url + "?name={1}", String.class, "hello"); + if (!"hello".equals(result)) { + notExpectedFailed.set(true); + } + } catch (Exception e) { + if (e instanceof HttpClientErrorException) { + // isolate 2.0.0 and other instance will give 404 + if (((HttpClientErrorException) e).getStatusCode().value() == 404) { + expectedFailed404.set(true); + } else { + notExpectedFailed.set(true); + } + } else if (e instanceof HttpServerErrorException) { + // instance isolated and return 503 + if (((HttpServerErrorException) e).getStatusCode().value() == 503) { + expectedFailed503.set(true); + } + // provider throw 502 exception to trigger instance isolation + if (((HttpServerErrorException) e).getStatusCode().value() == 502) { + expectedFailed502.set(true); + } + } else { + notExpectedFailed.set(true); + } + } + latch.countDown(); + } + }.start(); + } + Thread.sleep(100); + } + + latch.await(20, TimeUnit.SECONDS); + TestMgr.check(true, expectedFailed404.get()); + TestMgr.check(true, expectedFailed502.get()); + TestMgr.check(true, expectedFailed503.get()); + TestMgr.check(false, notExpectedFailed.get()); + } + + private URIEndpointObject prepareEdge(String prefix) { + DiscoveryInstance microserviceInstance = discoveryManager.findServiceInstances( + BootStrapProperties.readApplication(environment), "edge") + .stream() + .findFirst() + .get(); + URIEndpointObject edgeAddress = new URIEndpointObject(microserviceInstance.getEndpoints().get(0)); + edgePrefix = String.format("http://%s:%d/%s", edgeAddress.getHostOrIp(), edgeAddress.getPort(), prefix); + return edgeAddress; + } +} diff --git a/demo/demo-edge/consumer/src/main/resources/log4j2.xml b/demo/demo-edge/consumer/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-edge/consumer/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-edge/consumer/src/main/resources/microservice.yaml b/demo/demo-edge/consumer/src/main/resources/microservice.yaml index 660dfbf2849..953b1e567e4 100644 --- a/demo/demo-edge/consumer/src/main/resources/microservice.yaml +++ b/demo/demo-edge/consumer/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: edge -service_description: - name: consumer - version: 0.0.1 servicecomb: service: - registry: + application: edge + name: consumer + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 rest: client.http2.useAlpnEnabled: false @@ -29,5 +29,3 @@ servicecomb: chain: Consumer: default: loadbalance - references: - version-rule: 1.1.0 \ No newline at end of file diff --git a/demo/demo-edge/consumer/src/test/java/org/apache/servicecomb/demo/edge/consumer/EdgeDemoIT.java b/demo/demo-edge/consumer/src/test/java/org/apache/servicecomb/demo/edge/consumer/EdgeDemoIT.java index f5f161f1d17..0ef1f0c9ba3 100644 --- a/demo/demo-edge/consumer/src/test/java/org/apache/servicecomb/demo/edge/consumer/EdgeDemoIT.java +++ b/demo/demo-edge/consumer/src/test/java/org/apache/servicecomb/demo/edge/consumer/EdgeDemoIT.java @@ -17,23 +17,26 @@ package org.apache.servicecomb.demo.edge.consumer; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = ConsumerMain.class) public class EdgeDemoIT { - @Before + @BeforeEach public void setUp() { TestMgr.errors().clear(); } @Test public void clientGetsNoError() throws Exception { - ConsumerMain.main(new String[0]); + ConsumerMain.runTest(); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-edge/edge-service/pom.xml b/demo/demo-edge/edge-service/pom.xml index 9bd6d01d43e..31fdcff3874 100644 --- a/demo/demo-edge/edge-service/pom.xml +++ b/demo/demo-edge/edge-service/pom.xml @@ -21,13 +21,13 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT edge-service Java Chassis::Demo::Edge::Service - org.apache.servicecomb.demo.edge.service.EdgeMain + org.apache.servicecomb.demo.edge.EdgeMain @@ -35,33 +35,12 @@ org.apache.servicecomb edge-core - - org.apache.servicecomb - handler-loadbalance - - - org.apache.servicecomb - provider-pojo - - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -70,15 +49,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/EdgeMain.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/EdgeMain.java new file mode 100644 index 00000000000..b1c17a93cab --- /dev/null +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/EdgeMain.java @@ -0,0 +1,29 @@ +/* + * 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.demo.edge; + +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class EdgeMain { + public static void main(String[] args) throws Exception { + new SpringApplicationBuilder(EdgeMain.class).web(WebApplicationType.NONE).run(args); + } +} diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java index eca61582902..7aa294c83ed 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/CustomResponseMetaMapper.java @@ -26,7 +26,7 @@ import com.fasterxml.jackson.databind.type.SimpleType; public class CustomResponseMetaMapper implements ResponseMetaMapper { - private final static Map CODES = new HashMap<>(1); + private static final Map CODES = new HashMap<>(1); static { CODES.put(500, SimpleType.constructUnsafe(IllegalStateErrorData.class)); diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeConst.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeConst.java index dc5b3f2d437..7439ec60d44 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeConst.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeConst.java @@ -1,4 +1,4 @@ -package org.apache.servicecomb.demo.edge.service;/* +/* * 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. @@ -15,6 +15,8 @@ * limitations under the License. */ +package org.apache.servicecomb.demo.edge.service; + public interface EdgeConst { String ENCRYPT_CONTEXT = "encryptContext"; } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeDispatcher.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeDispatcher.java index 0eef0ba6c91..b900a427409 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeDispatcher.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeDispatcher.java @@ -19,16 +19,19 @@ import java.util.Map; +import org.apache.servicecomb.common.rest.RestProducerInvocationFlow; +import org.apache.servicecomb.core.invocation.InvocationCreator; import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher; -import org.apache.servicecomb.edge.core.CompatiblePathVersionMapper; -import org.apache.servicecomb.edge.core.EdgeInvocation; +import org.apache.servicecomb.edge.core.EdgeInvocationCreator; +import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; +import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; +import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; +import org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; public class EdgeDispatcher extends AbstractEdgeDispatcher { - private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper(); - @Override public int getOrder() { return 10000; @@ -45,13 +48,17 @@ public void init(Router router) { protected void onRequest(RoutingContext context) { Map pathParams = context.pathParams(); String microserviceName = pathParams.get("param0"); - String pathVersion = pathParams.get("param1"); String path = context.request().path().substring(4); - EdgeInvocation edgeInvocation = new EdgeInvocation(); - edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule()); + requestByFilter(context, microserviceName, path); + } - edgeInvocation.init(microserviceName, context, path, httpServerFilters); - edgeInvocation.edgeInvoke(); + protected void requestByFilter(RoutingContext context, String microserviceName, String path) { + HttpServletRequestEx requestEx = new VertxServerRequestToHttpServletRequest(context); + HttpServletResponseEx responseEx = new VertxServerResponseToHttpServletResponse(context.response()); + InvocationCreator creator = new EdgeInvocationCreator(context, requestEx, responseEx, + microserviceName, path); + new RestProducerInvocationFlow(creator, requestEx, responseEx) + .run(); } } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeMain.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeMain.java deleted file mode 100644 index 1c5aebb61fa..00000000000 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/EdgeMain.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.demo.edge.service; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; - -public class EdgeMain { - public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); - } -} diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeDispatcher.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeDispatcher.java index c4900a61faa..76ea1840402 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeDispatcher.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeDispatcher.java @@ -20,9 +20,17 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; +import org.apache.servicecomb.common.rest.RestProducerInvocationFlow; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.invocation.InvocationCreator; import org.apache.servicecomb.demo.edge.authentication.encrypt.Hcr; +import org.apache.servicecomb.demo.edge.service.EdgeConst; import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher; -import org.apache.servicecomb.edge.core.CompatiblePathVersionMapper; +import org.apache.servicecomb.edge.core.EdgeInvocationCreator; +import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; +import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; +import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; +import org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse; import org.apache.servicecomb.provider.pojo.Invoker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,8 +42,6 @@ public class EncryptEdgeDispatcher extends AbstractEdgeDispatcher { private static final Logger LOGGER = LoggerFactory.getLogger(EncryptEdgeDispatcher.class); - private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper(); - private Encrypt encrypt = Invoker.createProxy("auth", "encrypt", Encrypt.class); private String prefix = "encryptApi"; @@ -47,12 +53,10 @@ public int getOrder() { @Override public void init(Router router) { - { - String regex = "/" + prefix + "/([^\\\\/]+)/([^\\\\/]+)/(.*)"; - // cookies handler are enabled by default start from 3.8.3 - router.routeWithRegex(regex).handler(createBodyHandler()); - router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest); - } + String regex = "/" + prefix + "/([^\\\\/]+)/(.*)"; + // cookies handler are enabled by default start from 3.8.3 + router.routeWithRegex(regex).handler(createBodyHandler()); + router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest); } protected void onRequest(RoutingContext context) { @@ -101,13 +105,30 @@ private CompletableFuture queryHcr(HttpServerRequest httpServerRequest) { private void routeToBackend(RoutingContext context, Hcr hcr, String userId) { Map pathParams = context.pathParams(); String microserviceName = pathParams.get("param0"); - String pathVersion = pathParams.get("param1"); String path = context.request().path().substring(prefix.length() + 1); - EncryptEdgeInvocation edgeInvocation = new EncryptEdgeInvocation(new EncryptContext(hcr, userId)); - edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule()); + requestByFilter(context, microserviceName, path, + new EncryptContext(hcr, userId)); + } - edgeInvocation.init(microserviceName, context, path, httpServerFilters); - edgeInvocation.edgeInvoke(); + protected void requestByFilter(RoutingContext context, String microserviceName, String path + , EncryptContext encryptContext) { + HttpServletRequestEx requestEx = new VertxServerRequestToHttpServletRequest(context); + HttpServletResponseEx responseEx = new VertxServerResponseToHttpServletResponse(context.response()); + InvocationCreator creator = new EdgeInvocationCreator(context, requestEx, responseEx, + microserviceName, path) { + @Override + public CompletableFuture createAsync() { + CompletableFuture result = super.createAsync(); + return result.whenComplete((invocation, throwable) + -> { + if (throwable == null) { + invocation.getHandlerContext().put(EdgeConst.ENCRYPT_CONTEXT, encryptContext); + } + }); + } + }; + new RestProducerInvocationFlow(creator, requestEx, responseEx) + .run(); } } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeInvocation.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeInvocation.java deleted file mode 100644 index cdeb3355e70..00000000000 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/EncryptEdgeInvocation.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.demo.edge.service.encrypt; - -import org.apache.servicecomb.edge.core.EdgeInvocation; - -public class EncryptEdgeInvocation extends EdgeInvocation { - private EncryptContext encryptContext; - - public EncryptEdgeInvocation(EncryptContext encryptContext) { - this.encryptContext = encryptContext; - } - - @Override - protected void createInvocation() { - super.createInvocation(); - - invocation.getHandlerContext().put("encryptContext", encryptContext); - } -} diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java index 73c533e678c..d9e0f332318 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/DecodeBodyFilter.java @@ -17,38 +17,48 @@ package org.apache.servicecomb.demo.edge.service.encrypt.filter; import java.util.Map; +import java.util.concurrent.CompletableFuture; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.demo.edge.authentication.encrypt.Hcr; import org.apache.servicecomb.demo.edge.service.EdgeConst; import org.apache.servicecomb.demo.edge.service.encrypt.EncryptContext; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; -public class DecodeBodyFilter implements HttpServerFilter { +@Component +public class DecodeBodyFilter extends AbstractFilter implements EdgeFilter { private JavaType bodyType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, String[].class); @Override public int getOrder() { - return -9000; + return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1790; } @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { + public String getName() { + return "test-edge-decode-body"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT); if (encryptContext == null) { - return null; + return nextNode.onFilter(invocation); } Hcr hcr = encryptContext.getHcr(); - String encodedBody = requestEx.getParameter("body"); + String encodedBody = invocation.getRequestEx().getParameter("body"); if (encodedBody == null) { - return null; + return nextNode.onFilter(invocation); } encodedBody = encodedBody.substring(hcr.getBodyKey().length()); @@ -56,11 +66,11 @@ public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx try { Map decodedBody = RestObjectMapperFactory.getRestObjectMapper() .readValue(encodedBody, bodyType); - requestEx.getParameterMap().putAll(decodedBody); + invocation.getRequestEx().getParameterMap().putAll(decodedBody); } catch (Throwable e) { // should be a meaning exception response - return Response.producerFailResp(e); + return CompletableFuture.failedFuture(e); } - return null; + return nextNode.onFilter(invocation); } } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureRequestFilter.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureRequestFilter.java index 0eae860c273..42443b555b4 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureRequestFilter.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureRequestFilter.java @@ -20,48 +20,58 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.concurrent.CompletableFuture; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.demo.edge.authentication.encrypt.Hcr; import org.apache.servicecomb.demo.edge.service.EdgeConst; import org.apache.servicecomb.demo.edge.service.encrypt.EncryptContext; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.swagger.invocation.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; import com.google.common.hash.Hasher; import com.google.common.hash.Hashing; -public class EdgeSignatureRequestFilter implements HttpServerFilter { +@Component +public class EdgeSignatureRequestFilter extends AbstractFilter implements EdgeFilter { private static final Logger LOGGER = LoggerFactory.getLogger(EdgeSignatureRequestFilter.class); @Override public int getOrder() { - return -10000; + return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1800; } @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { + public String getName() { + return "test-edge-signature-request"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT); if (encryptContext == null) { - return null; + return nextNode.onFilter(invocation); } Hcr hcr = encryptContext.getHcr(); // signature for query and form - List names = Collections.list(requestEx.getParameterNames()); + List names = Collections.list(invocation.getRequestEx().getParameterNames()); names.sort(Comparator.naturalOrder()); Hasher hasher = Hashing.sha256().newHasher(); hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8); for (String name : names) { hasher.putString(name, StandardCharsets.UTF_8); - hasher.putString(requestEx.getParameter(name), StandardCharsets.UTF_8); + hasher.putString(invocation.getRequestEx().getParameter(name), StandardCharsets.UTF_8); } - LOGGER.info("afterReceiveRequest signature: {}", hasher.hash().toString()); + LOGGER.info("afterReceiveRequest signature: {}", hasher.hash()); - return null; + return nextNode.onFilter(invocation); } } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java index 4d9a3805b5b..a3909d75540 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/EdgeSignatureResponseFilter.java @@ -17,60 +17,65 @@ package org.apache.servicecomb.demo.edge.service.encrypt.filter; import java.nio.charset.StandardCharsets; +import java.util.concurrent.CompletableFuture; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.demo.edge.authentication.encrypt.Hcr; import org.apache.servicecomb.demo.edge.service.EdgeConst; import org.apache.servicecomb.demo.edge.service.encrypt.EncryptContext; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.swagger.invocation.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; import com.google.common.hash.Hasher; import com.google.common.hash.Hashing; import io.vertx.core.buffer.Buffer; -public class EdgeSignatureResponseFilter implements HttpServerFilter { +@Component +public class EdgeSignatureResponseFilter extends AbstractFilter implements EdgeFilter { private static final Logger LOGGER = LoggerFactory.getLogger(EdgeSignatureResponseFilter.class); @Override public int getOrder() { - return 10000; + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1991; } @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { - return null; + public String getName() { + return "test-edge-signature-response"; } @Override - public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) { - if (invocation == null) { - return; - } + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + return nextNode.onFilter(invocation).whenComplete((response, throwable) -> { + if (throwable != null) { + return; + } + EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT); + if (encryptContext == null) { + return; + } + Hcr hcr = encryptContext.getHcr(); - EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT); - if (encryptContext == null) { - return; - } - Hcr hcr = encryptContext.getHcr(); + // bad practice: it's better to set signature in response header + Buffer bodyBuffer = response.getResult(); + String body = bodyBuffer.toString(); + if (body.endsWith("}")) { + Hasher hasher = Hashing.sha256().newHasher(); + hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8); + hasher.putString(body, StandardCharsets.UTF_8); + String signature = hasher.hash().toString(); + LOGGER.info("beforeSendResponse signature: {}", signature); - // bad practice: it's better to set signature in response header - Buffer bodyBuffer = responseEx.getBodyBuffer(); - String body = bodyBuffer.toString(); - if (body.endsWith("}")) { - Hasher hasher = Hashing.sha256().newHasher(); - hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8); - hasher.putString(body, StandardCharsets.UTF_8); - String signature = hasher.hash().toString(); - LOGGER.info("beforeSendResponse signature: {}", signature); - - body = body.substring(0, body.length() - 1) + ",\"signature\":\"" + signature + "\"}"; - responseEx.setBodyBuffer(Buffer.buffer(body)); - } + body = body.substring(0, body.length() - 1) + ",\"signature\":\"" + signature + "\"}"; + response.setResult(Buffer.buffer(body)); + } + }); } } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/UserIdFilter.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/UserIdFilter.java index 2212042ef7c..fd20c0e6d7e 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/UserIdFilter.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/encrypt/filter/UserIdFilter.java @@ -16,31 +16,42 @@ */ package org.apache.servicecomb.demo.edge.service.encrypt.filter; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; +import java.util.concurrent.CompletableFuture; + import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.demo.edge.service.EdgeConst; import org.apache.servicecomb.demo.edge.service.encrypt.EncryptContext; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.stereotype.Component; -public class UserIdFilter implements HttpServerFilter { +@Component +public class UserIdFilter extends AbstractFilter implements EdgeFilter { @Override public int getOrder() { - return -8000; + return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1790; + } + + @Override + public String getName() { + return "test-edge-user-id"; } @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT); if (encryptContext == null) { - return null; + return nextNode.onFilter(invocation); } String userId = encryptContext.getUserId(); if (userId != null) { - requestEx.setParameter("userId", userId); + invocation.getRequestEx().setParameter("userId", userId); } - return null; + return nextNode.onFilter(invocation); } } diff --git a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/handler/AuthHandler.java b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/handler/AuthHandler.java index 75bd6fdbd42..4aeb44be08a 100644 --- a/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/handler/AuthHandler.java +++ b/demo/demo-edge/edge-service/src/main/java/org/apache/servicecomb/demo/edge/service/handler/AuthHandler.java @@ -17,20 +17,25 @@ package org.apache.servicecomb.demo.edge.service.handler; -import javax.ws.rs.core.Response.Status; +import java.util.concurrent.CompletableFuture; -import org.apache.servicecomb.core.Handler; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; import org.apache.servicecomb.demo.edge.service.EdgeConst; import org.apache.servicecomb.provider.pojo.Invoker; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.InvocationType; +import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; -public class AuthHandler implements Handler { +import jakarta.ws.rs.core.Response.Status; + +@Component +public class AuthHandler extends AbstractFilter implements EdgeFilter { private static Logger LOGGER = LoggerFactory.getLogger(AuthHandler.class); private static Auth auth; @@ -40,35 +45,36 @@ public class AuthHandler implements Handler { } @Override - public void init(MicroserviceMeta microserviceMeta, InvocationType invocationType) { + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1980; } @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - if (invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT) != null) { - invocation.next(asyncResp); - return; - } + public boolean enabledForMicroservice(String application, String serviceName) { + // Do not enable for service auth and not enable for internal management access(myself) + return !"auth".equals(serviceName) && !"edge".equals(serviceName); + } - auth.auth("").whenComplete((succ, e) -> doHandle(invocation, asyncResp, succ, e)); + @Override + public String getName() { + return "test-auth"; } - protected void doHandle(Invocation invocation, AsyncResponse asyncResp, Boolean authSucc, Throwable authException) { - if (authException != null) { - asyncResp.consumerFail(new InvocationException(Status.UNAUTHORIZED, (Object) authException.getMessage())); - return; + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT) != null) { + return nextNode.onFilter(invocation); } + return auth.auth("").thenCompose(result -> doHandle(invocation, nextNode, result)); + } + + protected CompletableFuture doHandle(Invocation invocation, FilterNode nextNode, Boolean authSucc) { if (!authSucc) { - asyncResp.consumerFail(new InvocationException(Status.UNAUTHORIZED, (Object) "auth failed")); - return; + return CompletableFuture.failedFuture(new InvocationException(Status.UNAUTHORIZED, (Object) "auth failed")); } LOGGER.debug("auth success."); - try { - invocation.next(asyncResp); - } catch (Throwable e) { - asyncResp.consumerFail(e); - } + return nextNode.onFilter(invocation); } } diff --git a/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter deleted file mode 100644 index eb91526f3d5..00000000000 --- a/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter +++ /dev/null @@ -1,21 +0,0 @@ -# -# 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.servicecomb.demo.edge.service.encrypt.filter.EdgeSignatureRequestFilter -org.apache.servicecomb.demo.edge.service.encrypt.filter.DecodeBodyFilter -org.apache.servicecomb.demo.edge.service.encrypt.filter.UserIdFilter -org.apache.servicecomb.demo.edge.service.encrypt.filter.EdgeSignatureResponseFilter \ No newline at end of file diff --git a/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper b/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper index d8a88a70544..dcc25e0a838 100644 --- a/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper +++ b/demo/demo-edge/edge-service/src/main/resources/META-INF/services/org.apache.servicecomb.swagger.invocation.response.ResponseMetaMapper @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.demo.edge.service.CustomResponseMetaMapper \ No newline at end of file +org.apache.servicecomb.demo.edge.service.CustomResponseMetaMapper diff --git a/demo/demo-edge/edge-service/src/main/resources/config/cse.handler.xml b/demo/demo-edge/edge-service/src/main/resources/config/cse.handler.xml deleted file mode 100644 index 3a27cb37339..00000000000 --- a/demo/demo-edge/edge-service/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties b/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties deleted file mode 100644 index efd6a27d95f..00000000000 --- a/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO,stdout -log4j.appender.stdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS/zzz}][%t][%p]%m %l%n \ No newline at end of file diff --git a/demo/demo-edge/edge-service/src/main/resources/log4j2.xml b/demo/demo-edge/edge-service/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-edge/edge-service/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-edge/edge-service/src/main/resources/microservice.yaml b/demo/demo-edge/edge-service/src/main/resources/microservice.yaml index 544cbcf1d14..56403677e38 100644 --- a/demo/demo-edge/edge-service/src/main/resources/microservice.yaml +++ b/demo/demo-edge/edge-service/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: edge -service_description: - name: edge - version: 0.0.1 servicecomb: service: - registry: + application: edge + name: edge + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 edge: filter: @@ -29,7 +29,7 @@ servicecomb: enabled: true allowedHeaders: xxx rest: - address: 0.0.0.0:18080 + address: 0.0.0.0:18090 server: # for test case run in one core machine verticle-count: 1 @@ -39,9 +39,9 @@ servicecomb: handler: chain: Consumer: - default: auth,loadbalance + default: auth,loadbalance,instance-isolation-consumer,instance-bulkhead-consumer service: - auth: loadbalance + auth: loadbalance,instance-isolation-consumer,instance-bulkhead-consumer http: dispatcher: edge: @@ -57,12 +57,10 @@ servicecomb: prefixSegmentCount: 1 path: "/url/business/v1/.*" microserviceName: business - versionRule: 1.0.0-2.0.0 businessV2: prefixSegmentCount: 1 path: "/url/business/v2/.*" microserviceName: business - versionRule: 2.0.0-3.0.0 http: enabled: true mappings: @@ -70,14 +68,70 @@ servicecomb: prefixSegmentCount: 1 path: "/http/business/v2/.*" microserviceName: business - versionRule: 2.0.0 businessV1: prefixSegmentCount: 1 path: "/http/business/v1/add.*" microserviceName: business - versionRule: 1.0.0-1.2.0 businessV1_1: prefixSegmentCount: 1 path: "/http/business/v1/dec.*" microserviceName: business - versionRule: 1.1.0 \ No newline at end of file + + # 服务治理配置 + matchGroup: + testEdgeServiceRetry: | + matches: + - apiPath: + exact: "/business/v2/testEdgeServiceRetry" + testEdgeServiceInstanceIsolation: | + matches: + - apiPath: + exact: "/business/v2/testEdgeServiceInstanceIsolation" + testEdgeServiceInstanceBulkhead: | + matches: + - apiPath: + exact: "/business/v2/testEdgeServiceInstanceBulkhead" + # retry not supported now + # retry: + # testEdgeServiceRetry: | + # maxAttempts: 2 + # retryOnSame: 0 + instanceIsolation: + testEdgeServiceInstanceIsolation: | + minimumNumberOfCalls: 10 + slidingWindowSize: 20 + slidingWindowType: COUNT_BASED + failureRateThreshold: 50 + slowCallRateThreshold: 100 + slowCallDurationThreshold: 3000 + waitDurationInOpenState: 3000 + permittedNumberOfCallsInHalfOpenState: 10 + instanceBulkhead: + testEdgeServiceInstanceBulkhead: | + maxConcurrentCalls: 1 + maxWaitDuration: 1 + + # enable router for edge service + router: + type: router + routeRule: + business: | + - precedence: 2 + match: + apiPath: + prefix: "/business/v2" + route: + - weight: 100 + tags: + version: 2.0.0 + - precedence: 1 + match: + apiPath: + prefix: "/business/v1/dec" + route: + - weight: 50 + tags: + version: 1.1.0 + - weight: 50 + tags: + version: 2.0.0 diff --git a/demo/demo-edge/model/pom.xml b/demo/demo-edge/model/pom.xml index 75028171a8e..3adda2c13e4 100644 --- a/demo/demo-edge/model/pom.xml +++ b/demo/demo-edge/model/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT model Java Chassis::Demo::Edge::Model diff --git a/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/ResultWithInstance.java b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/ResultWithInstance.java index b9c3d3d83a1..c225f7fee34 100644 --- a/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/ResultWithInstance.java +++ b/demo/demo-edge/model/src/main/java/org/apache/servicecomb/demo/edge/model/ResultWithInstance.java @@ -17,7 +17,8 @@ package org.apache.servicecomb.demo.edge.model; -import org.apache.servicecomb.registry.RegistrationManager; +import org.apache.servicecomb.config.BootStrapProperties; +import org.springframework.core.env.Environment; public class ResultWithInstance { private int result; @@ -28,12 +29,10 @@ public class ResultWithInstance { private String version; - public static ResultWithInstance create(int value) { + public static ResultWithInstance create(int value, Environment environment) { ResultWithInstance result = new ResultWithInstance(); result.setResult(value); - result.setInstanceId(RegistrationManager.INSTANCE.getMicroserviceInstance().getInstanceId()); - result.setServiceId(RegistrationManager.INSTANCE.getMicroservice().getServiceId()); - result.setVersion(RegistrationManager.INSTANCE.getMicroservice().getVersion()); + result.setVersion(BootStrapProperties.readServiceVersion(environment)); return result; } diff --git a/demo/demo-edge/pom.xml b/demo/demo-edge/pom.xml index 042578a9baf..34cdcd1fccc 100644 --- a/demo/demo-edge/pom.xml +++ b/demo/demo-edge/pom.xml @@ -22,28 +22,36 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-edge Java Chassis::Demo::Edge pom + + org.apache.servicecomb + solution-basic + org.apache.servicecomb registry-service-center org.apache.servicecomb - registry-schema-discovery + java-chassis-spring-boot-starter-standalone + + + org.apache.logging.log4j + log4j-slf4j-impl - log4j - log4j + org.apache.logging.log4j + log4j-api - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-core diff --git a/demo/demo-etcd/README.md b/demo/demo-etcd/README.md new file mode 100644 index 00000000000..046bec6c968 --- /dev/null +++ b/demo/demo-etcd/README.md @@ -0,0 +1,5 @@ +# Notice + +This integration tests is designed for Etcd 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-etcd/consumer/pom.xml b/demo/demo-etcd/consumer/pom.xml new file mode 100644 index 00000000000..20a03319d43 --- /dev/null +++ b/demo/demo-etcd/consumer/pom.xml @@ -0,0 +1,114 @@ + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-etcd + 3.4.0-SNAPSHOT + + + etcd-consumer + Java Chassis::Demo::Etcd::CONSUMER + jar + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + com.google.protobuf + protobuf-java + 3.25.5 + runtime + + + org.apache.servicecomb + registry-etcd + + + org.apache.servicecomb + config-etcd + + + + + + + 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-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java new file mode 100644 index 00000000000..f71738a9ed6 --- /dev/null +++ b/demo/demo-etcd/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-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java new file mode 100644 index 00000000000..e66fb2cb3d0 --- /dev/null +++ b/demo/demo-etcd/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-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java new file mode 100644 index 00000000000..f0e894d6745 --- /dev/null +++ b/demo/demo-etcd/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-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java new file mode 100644 index 00000000000..aa169801cf7 --- /dev/null +++ b/demo/demo-etcd/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-etcd/consumer/src/main/java/org/apache/servicecomb/samples/EtcdConsumerApplication.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/EtcdConsumerApplication.java new file mode 100644 index 00000000000..2101e6512f8 --- /dev/null +++ b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/EtcdConsumerApplication.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 EtcdConsumerApplication { + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(EtcdConsumerApplication.class).run(args); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java new file mode 100644 index 00000000000..2899546c752 --- /dev/null +++ b/demo/demo-etcd/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-etcd/consumer/src/main/java/org/apache/servicecomb/samples/User.java b/demo/demo-etcd/consumer/src/main/java/org/apache/servicecomb/samples/User.java new file mode 100644 index 00000000000..ff421930ef2 --- /dev/null +++ b/demo/demo-etcd/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-etcd/consumer/src/main/resources/application.yml b/demo/demo-etcd/consumer/src/main/resources/application.yml new file mode 100644 index 00000000000..e0db5f1434e --- /dev/null +++ b/demo/demo-etcd/consumer/src/main/resources/application.yml @@ -0,0 +1,35 @@ +# +## --------------------------------------------------------------------------- +## 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-etcd + version: 0.0.1 + name: consumer + properties: + group: red + registry: + etcd: + connectString: http://127.0.0.1:2379 + config: + etcd: + connectString: http://127.0.0.1:2379 + + rest: + address: 0.0.0.0:9092?websocketEnabled=true + server: + websocket-prefix: /ws diff --git a/demo/demo-etcd/consumer/src/main/resources/log4j2.xml b/demo/demo-etcd/consumer/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-etcd/consumer/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-etcd/gateway/pom.xml b/demo/demo-etcd/gateway/pom.xml new file mode 100644 index 00000000000..0b52381a492 --- /dev/null +++ b/demo/demo-etcd/gateway/pom.xml @@ -0,0 +1,113 @@ + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-etcd + 3.4.0-SNAPSHOT + + + etcd-gateway + Java Chassis::Demo::Etcd::GATEWAY + jar + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + edge-core + + + com.google.protobuf + protobuf-java + 3.25.5 + runtime + + + org.apache.servicecomb + registry-etcd + + + + + + 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-etcd/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-etcd/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java new file mode 100644 index 00000000000..7d58caafd9d --- /dev/null +++ b/demo/demo-etcd/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-etcd/gateway/src/main/resources/application.yml b/demo/demo-etcd/gateway/src/main/resources/application.yml new file mode 100644 index 00000000000..f526eb3de70 --- /dev/null +++ b/demo/demo-etcd/gateway/src/main/resources/application.yml @@ -0,0 +1,53 @@ +# +## --------------------------------------------------------------------------- +## 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-etcd + version: 0.0.1 + name: gateway + registry: + etcd: + enabled: true + connectString: http://127.0.0.1:2379 + + 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-etcd/gateway/src/main/resources/log4j2.xml b/demo/demo-etcd/gateway/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-etcd/gateway/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-etcd/pom.xml b/demo/demo-etcd/pom.xml new file mode 100644 index 00000000000..c615edd88b1 --- /dev/null +++ b/demo/demo-etcd/pom.xml @@ -0,0 +1,61 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-parent + 3.4.0-SNAPSHOT + + demo-etcd + Java Chassis::Demo::Etcd + 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-etcd/provider/pom.xml b/demo/demo-etcd/provider/pom.xml new file mode 100644 index 00000000000..8d8c005a1e1 --- /dev/null +++ b/demo/demo-etcd/provider/pom.xml @@ -0,0 +1,123 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-etcd + 3.4.0-SNAPSHOT + + + etcd-provider + Java Chassis::Demo::Etcd::PROVIDER + jar + + + + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + com.google.protobuf + protobuf-java + 3.25.5 + runtime + + + org.apache.servicecomb + registry-etcd + + + org.apache.servicecomb + config-etcd + + + + 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-etcd/provider/src/main/java/org/apache/servicecomb/samples/EtcdProviderApplication.java b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/EtcdProviderApplication.java new file mode 100644 index 00000000000..388b962dc61 --- /dev/null +++ b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/EtcdProviderApplication.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 EtcdProviderApplication { + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(EtcdProviderApplication.class).run(args); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java new file mode 100644 index 00000000000..8a773f91c72 --- /dev/null +++ b/demo/demo-etcd/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-etcd/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java new file mode 100644 index 00000000000..677c20ed106 --- /dev/null +++ b/demo/demo-etcd/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-etcd/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java new file mode 100644 index 00000000000..8108d15fd46 --- /dev/null +++ b/demo/demo-etcd/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-etcd/provider/src/main/java/org/apache/servicecomb/samples/User.java b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/User.java new file mode 100644 index 00000000000..ca12402d672 --- /dev/null +++ b/demo/demo-etcd/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-etcd/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java new file mode 100644 index 00000000000..3bc88c64ac5 --- /dev/null +++ b/demo/demo-etcd/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java @@ -0,0 +1,65 @@ +/* + * 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.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) { + // Client may have not registered message handler, and messages sent may get lost. + // So we sleep for a while to send message. + AtomicInteger receiveCount = new AtomicInteger(0); + serverWebsocket.textMessageHandler(s -> { + receiveCount.getAndIncrement(); + }); + serverWebsocket.closeHandler((v) -> System.out.println("closed")); + + new Thread(() -> { + try { + Thread.sleep(1000); + } 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-etcd/provider/src/main/resources/application.yml b/demo/demo-etcd/provider/src/main/resources/application.yml new file mode 100644 index 00000000000..da2051cd77e --- /dev/null +++ b/demo/demo-etcd/provider/src/main/resources/application.yml @@ -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. +## --------------------------------------------------------------------------- +# spring boot configurations +servicecomb: + service: + application: demo-etcd + version: 0.0.1 + name: provider + properties: + group: green + registry: + etcd: + connectString: http://127.0.0.1:2379 + config: + etcd: + connectString: http://127.0.0.1:2379 + instance-tag: tag1 + + 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-etcd/provider/src/main/resources/log4j2.xml b/demo/demo-etcd/provider/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-etcd/provider/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-etcd/test-client/pom.xml b/demo/demo-etcd/test-client/pom.xml new file mode 100644 index 00000000000..ab839d762f5 --- /dev/null +++ b/demo/demo-etcd/test-client/pom.xml @@ -0,0 +1,211 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-etcd + 3.4.0-SNAPSHOT + + + etcd-test-client + Java Chassis::Demo::Etcd::TEST-CLIENT + jar + + + + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb.demo + demo-schema + + + org.apache.servicecomb + registry-local + + + io.etcd + jetcd-core + + + com.google.protobuf + protobuf-java + 3.25.5 + runtime + + + + + + docker + + + + + io.fabric8 + docker-maven-plugin + + + + bitnami/etcd:3.5.16 + etcd + + alias + + etcdserver + + + 2379 + + + + + + 2379:2379 + + + yes + + + + + etcd-provider:${project.version} + etcd-provider + + alias + + + -Dservicecomb.registry.etcd.connectString=http://etcd:2379 + -Dservicecomb.config.etcd.connectString=http://etcd:2379 + + /maven/maven/etcd-provider-${project.version}.jar + + + etcd:etcd + + + ServiceComb is ready + + + 9094 + + + + + + 9094:9094 + + + + + etcd-consumer:${project.version} + etcd-consumer + + alias + + + -Dservicecomb.registry.etcd.connectString=http://etcd:2379 + -Dservicecomb.config.etcd.connectString=http://etcd:2379 + + /maven/maven/etcd-consumer-${project.version}.jar + + + etcd:etcd + + + ServiceComb is ready + + + 9092 + + + + + + 9092:9092 + + + + + etcd-gateway:${project.version} + etcd-gateway + + alias + + + -Dservicecomb.registry.etcd.connectString=http://etcd:2379 + + /maven/maven/etcd-gateway-${project.version}.jar + + + etcd:etcd + + + 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-etcd/test-client/src/main/java/org/apache/servicecomb/samples/Config.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/Config.java new file mode 100644 index 00000000000..2e9105cdd4a --- /dev/null +++ b/demo/demo-etcd/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-etcd/test-client/src/main/java/org/apache/servicecomb/samples/EtcdConfigIT.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/EtcdConfigIT.java new file mode 100644 index 00000000000..92432e01f5f --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/EtcdConfigIT.java @@ -0,0 +1,146 @@ +/* + * 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.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; + +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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +import io.etcd.jetcd.ByteSequence; +import io.etcd.jetcd.Client; + +@Component +public class EtcdConfigIT implements CategorizedTestCase { + RestOperations template = new RestTemplate(); + + private static final Logger LOGGER = LoggerFactory.getLogger(EtcdConfigIT.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-etcd/application2.properties", + "testValue=t2"); + testGetConfig("testValue", "t2"); + putValue("/servicecomb/config/service/production/demo-etcd/provider/application2.properties", + "testValue=t3"); + testGetConfig("testValue", "t3"); + putValue("/servicecomb/config/version/production/demo-etcd/provider/0.0.1/application2.properties", + "testValue=t4"); + testGetConfig("testValue", "t4"); + putValue("/servicecomb/config/tag/production/demo-etcd/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-etcd/application.properties", + "test2=applition"); + putValue("/servicecomb/config/application/production/demo-etcd/application.properties", + "test2=applition2"); + testGetConfig("test2", "applition2"); + } + + private void testService() { + + putValue("/servicecomb/config/service/production/demo-etcd/provider/application.properties", + "test3=service"); + putValue("/servicecomb/config/service/production/demo-etcd/provider/application.properties", + "test3=service3"); + testGetConfig("test3", "service3"); + } + + private void testVersion() { + + putValue("/servicecomb/config/version/production/demo-etcd/provider/0.0.1/application.properties", + "test3=version"); + putValue("/servicecomb/config/version/production/demo-etcd/provider/0.0.1/application.properties", + "test4=version4"); + testGetConfig("test4", "version4"); + } + + private void testTag() { + + putValue("/servicecomb/config/tag/production/demo-etcd/provider/0.0.1/tag1/application.properties", + "test5=tag"); + putValue("/servicecomb/config/tag/production/demo-etcd/provider/0.0.1/tag1/application.properties", + "test5=tag5"); + testGetConfig("test5", "tag5"); + } + + + public void putValue(String key, String value) { + try (Client client = Client.builder().endpoints("http://localhost:2379").build()) { + + client.getKVClient().put( + ByteSequence.from(key, StandardCharsets.UTF_8), + ByteSequence.from(value, StandardCharsets.UTF_8) + ).get(); + + 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-etcd/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java new file mode 100644 index 00000000000..1b129acc2c6 --- /dev/null +++ b/demo/demo-etcd/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-etcd/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java new file mode 100644 index 00000000000..97e883fb45f --- /dev/null +++ b/demo/demo-etcd/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 entity = new HttpEntity(headers); + ResponseEntity response = + template.exchange(Config.GATEWAY_URL + "/sayHello?name=World", HttpMethod.GET, entity, String.class); + TestMgr.check(1, response.getHeaders().get("X-B3-TraceId").size()); + TestMgr.check("81de2eb7691c2bbb", response.getHeaders().getFirst("X-B3-TraceId")); + TestMgr.check("Hello World", response.getBody()); + } +} diff --git a/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ProviderIT.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ProviderIT.java new file mode 100644 index 00000000000..2bdd0ca42ca --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ProviderIT.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.io.IOException; +import java.nio.charset.StandardCharsets; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.utils.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +@Component +public class ProviderIT implements CategorizedTestCase { + + RestOperations template = new RestTemplate(); + + private static final Logger LOGGER = LoggerFactory.getLogger(ProviderIT.class); + + @Override + public void testRestTransport() throws Exception { + + User user = getUser("Application/json"); + TestMgr.check(1L, user.getId()); + TestMgr.check("czd", user.getName()); + + User user2 = getUser("application/json"); + TestMgr.check(1L, user2.getId()); + TestMgr.check("czd", user2.getName()); + + User user3 = getUser("APPLICATION/JSON"); + TestMgr.check(1L, user3.getId()); + TestMgr.check("czd", user3.getName()); + } + + private User getUser(String contentType) throws IOException { + HttpHeaders headers = new HttpHeaders(); + headers.set("Content-Type", contentType); + + String requestBody = """ + { + "id": 1, + "name": "czd" + } + """; + + HttpEntity entity = new HttpEntity<>(requestBody, headers); + + String url = Config.GATEWAY_URL + "/testContentType"; + ResponseEntity response = template.exchange( + url, HttpMethod.POST, entity, String.class); + + User user = JsonUtils.readValue(response.getBody().getBytes(StandardCharsets.UTF_8), User.class); + return user; + } +} diff --git a/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java new file mode 100644 index 00000000000..488a6cf712a --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java @@ -0,0 +1,119 @@ +/* + * 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 org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.ReactiveStreamClient; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.ReactiveStreamClient.Model; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +public class ReactiveStreamIT implements CategorizedTestCase { + @Autowired + @Qualifier("reactiveStreamProvider") + ReactiveStreamClient reactiveStreamProvider; + + @Autowired + @Qualifier("reactiveStreamGateway") + ReactiveStreamClient reactiveStreamGateway; + + @Override + public void testRestTransport() throws Exception { + testSseString(reactiveStreamProvider); + testSseModel(reactiveStreamProvider); + testSseString(reactiveStreamGateway); + testSseModel(reactiveStreamGateway); + } + + private void testSseModel(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseModel(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(Model s) { + buffer.append(s.getName()).append(s.getAge()); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("jack0jack1jack2jack3jack4", buffer.toString()); + } + + private void testSseString(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseString(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(String s) { + buffer.append(s); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("abc", buffer.toString()); + } +} diff --git a/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java new file mode 100644 index 00000000000..26a2a491bbe --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java @@ -0,0 +1,49 @@ +/* + * 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.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class TestClientApplication { + private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(TestClientApplication.class).run(args); + + run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("consumer"); + } +} diff --git a/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java new file mode 100644 index 00000000000..3ee5db8c346 --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java @@ -0,0 +1,125 @@ +/* + * 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.core.CoreConst; +import org.apache.servicecomb.core.annotation.Transport; +import org.apache.servicecomb.localregistry.RegistryBean; +import org.apache.servicecomb.localregistry.RegistryBean.Instance; +import org.apache.servicecomb.localregistry.RegistryBean.Instances; +import org.apache.servicecomb.provider.pojo.Invoker; +import org.reactivestreams.Publisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import io.vertx.core.http.WebSocket; + +@Configuration +public class ThirdSvcConfiguration { + @RequestMapping(path = "/ws") + public interface WebsocketClient { + @PostMapping("/websocket") + @Transport(name = CoreConst.WEBSOCKET) + WebSocket websocket(); + } + + @RequestMapping(path = "/") + public interface ReactiveStreamClient { + 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") + Publisher sseString(); + + @GetMapping("/sseModel") + Publisher sseModel(); + } + + @Bean + public RegistryBean providerServiceBean() { + return new RegistryBean() + .addSchemaInterface("ReactiveStreamController", ReactiveStreamClient.class) + .setAppId("demo-etcd") + .setServiceName("provider") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of( + new Instance().setEndpoints(List.of("rest://localhost:9094"))))); + } + + @Bean + public RegistryBean gatewayServiceBean() { + return new RegistryBean() + .addSchemaInterface("ReactiveStreamController", ReactiveStreamClient.class) + .addSchemaInterface("WebsocketController", WebsocketClient.class) + .setAppId("demo-etcd") + .setServiceName("gateway") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of( + new Instance().setEndpoints(List.of("rest://localhost:9090?websocketEnabled=true"))))); + } + + @Bean("reactiveStreamProvider") + public ReactiveStreamClient reactiveStreamProvider() { + return Invoker.createProxy("provider", "ReactiveStreamController", ReactiveStreamClient.class); + } + + @Bean("reactiveStreamGateway") + public ReactiveStreamClient reactiveStreamGateway() { + return Invoker.createProxy("gateway", "ReactiveStreamController", ReactiveStreamClient.class); + } + + @Bean + public WebsocketClient gatewayWebsocketClient() { + return Invoker.createProxy("gateway", "WebsocketController", WebsocketClient.class); + } +} diff --git a/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/User.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/User.java new file mode 100644 index 00000000000..ff421930ef2 --- /dev/null +++ b/demo/demo-etcd/test-client/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-etcd/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java new file mode 100644 index 00000000000..ea7a7f45b15 --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.samples; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.WebsocketClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import io.vertx.core.http.WebSocket; + +@Component +public class WebsocketIT implements CategorizedTestCase { + @Autowired + private WebsocketClient websocketClient; + + @Override + public void testRestTransport() throws Exception { + StringBuffer sb = new StringBuffer(); + AtomicBoolean closed = new AtomicBoolean(false); + CountDownLatch latch = new CountDownLatch(1); + + WebSocket webSocket = websocketClient.websocket(); + webSocket.textMessageHandler(s -> { + sb.append(s); + sb.append(" "); + webSocket.writeTextMessage(s); + }); + webSocket.closeHandler(v -> { + closed.set(true); + latch.countDown(); + }); + latch.await(30, TimeUnit.SECONDS); + TestMgr.check(sb.toString(), "hello hello 0 hello 1 hello 2 hello 3 hello 4 total 6 "); + TestMgr.check(closed.get(), true); + } +} diff --git a/demo/demo-etcd/test-client/src/main/resources/application.yml b/demo/demo-etcd/test-client/src/main/resources/application.yml new file mode 100644 index 00000000000..adcf259e984 --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/resources/application.yml @@ -0,0 +1,35 @@ +# +## --------------------------------------------------------------------------- +## 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-etcd + name: test-client + version: 0.0.1 + + rest: + address: 0.0.0.0:9097 # should be same with server.port to use web container + + config: + etcd: + instance-tag: tag1 + +test1: env +test2: applition +test3: service +test4: version +test5: tag diff --git a/demo/demo-etcd/test-client/src/main/resources/log4j2.xml b/demo/demo-etcd/test-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-etcd/test-client/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-etcd/test-client/src/test/java/org/apache/servicecomb/samples/EtcdIT.java b/demo/demo-etcd/test-client/src/test/java/org/apache/servicecomb/samples/EtcdIT.java new file mode 100644 index 00000000000..833feff87c0 --- /dev/null +++ b/demo/demo-etcd/test-client/src/test/java/org/apache/servicecomb/samples/EtcdIT.java @@ -0,0 +1,53 @@ +/* + * 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.TestMgr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = TestClientApplication.class) +public class EtcdIT { + private static final Logger LOGGER = LoggerFactory.getLogger(EtcdIT.class); + + @BeforeEach + public void setUp() { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() { + try { + TestClientApplication.run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/demo-filter/filter-client/pom.xml b/demo/demo-filter/filter-client/pom.xml new file mode 100644 index 00000000000..6c39fb4f5ad --- /dev/null +++ b/demo/demo-filter/filter-client/pom.xml @@ -0,0 +1,108 @@ + + + + + 4.0.0 + + org.apache.servicecomb.demo + demo-filter + 3.4.0-SNAPSHOT + + filter-client + Java Chassis::Demo::Filter::Client + + + + org.apache.servicecomb.demo + demo-schema + + + org.apache.servicecomb + foundation-test-scaffolding + + + + + org.apache.servicecomb.demo.filter.FilterClient + + + + + + 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-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/FilterClient.java b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/FilterClient.java new file mode 100644 index 00000000000..ab454f7c9e2 --- /dev/null +++ b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/FilterClient.java @@ -0,0 +1,49 @@ +/* + * 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.demo.filter; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class FilterClient { + private static final Logger LOGGER = LoggerFactory.getLogger(FilterClient.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder(FilterClient.class).web(WebApplicationType.NONE).run(args); + + run(); + } catch (Throwable e) { + TestMgr.check("success", "failed"); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("com.servicecomb.filterServer"); + } +} diff --git a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/ClientExceptionSchema.java b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/ClientExceptionSchema.java new file mode 100644 index 00000000000..3d64b25b426 --- /dev/null +++ b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/ClientExceptionSchema.java @@ -0,0 +1,69 @@ +/* + * 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.demo.filter.client; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.provider.consumer.InvokerUtils; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.client.RestOperations; + +@RestSchema(schemaId = "ClientExceptionSchema") +@RequestMapping(path = "/exception", produces = MediaType.APPLICATION_JSON_VALUE) +public class ClientExceptionSchema { + interface IExceptionSchema { + boolean blockingException(); + + CompletableFuture reactiveException(); + } + + private IExceptionSchema exceptionSchema; + + private RestOperations restTemplate = RestTemplateBuilder.create(); + + @RpcReference(microserviceName = "com.servicecomb.filterServer", schemaId = "ExceptionSchema") + public void setExceptionSchema(IExceptionSchema exceptionSchema) { + this.exceptionSchema = exceptionSchema; + } + + @GetMapping(path = "/blockingExceptionRestTemplate") + public boolean blockingExceptionRestTemplate() { + return restTemplate.getForObject( + "servicecomb://com.servicecomb.filterServer/exception/blockingException", boolean.class); + } + + @GetMapping(path = "/blockingExceptionReference") + public boolean blockingExceptionReference() { + return exceptionSchema.blockingException(); + } + + @GetMapping(path = "/blockingExceptionInvoker") + public boolean blockingExceptionInvoker() { + return InvokerUtils.syncInvoke("com.servicecomb.filterServer", + "ExceptionSchema", "blockingException", null, boolean.class); + } + + @GetMapping(path = "/reactiveExceptionReference") + public CompletableFuture reactiveExceptionReference() { + return exceptionSchema.reactiveException(); + } +} diff --git a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/GovernanceConsumerSchema.java b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/GovernanceConsumerSchema.java new file mode 100644 index 00000000000..733d3ab1f54 --- /dev/null +++ b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/GovernanceConsumerSchema.java @@ -0,0 +1,45 @@ +/* + * 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.demo.filter.client; + +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.RequestMapping; + +@RestSchema(schemaId = "GovernanceConsumerSchema") +@RequestMapping(path = "/govern", produces = MediaType.APPLICATION_JSON_VALUE) +public class GovernanceConsumerSchema { + interface GovernanceProviderSchemaInf { + boolean providerFlowControl(); + } + + @RpcReference(microserviceName = "com.servicecomb.filterServer", schemaId = "GovernanceProviderSchema") + private GovernanceProviderSchemaInf retrySchemaInf; + + + @GetMapping(path = "/edgeFlowControl") + public boolean edgeFlowControl() { + return true; + } + + @GetMapping(path = "/providerFlowControl") + public boolean providerFlowControl() { + return retrySchemaInf.providerFlowControl(); + } +} diff --git a/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/RetryClientSchema.java b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/RetryClientSchema.java new file mode 100644 index 00000000000..159c52fe340 --- /dev/null +++ b/demo/demo-filter/filter-client/src/main/java/org/apache/servicecomb/demo/filter/client/RetryClientSchema.java @@ -0,0 +1,76 @@ +/* + * 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.demo.filter.client; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.core.Response.Status; + +@RestSchema(schemaId = "RetryClientSchema") +@RequestMapping(path = "/retry", produces = MediaType.APPLICATION_JSON_VALUE) +public class RetryClientSchema { + interface RetrySchemaInf { + CompletableFuture successWhenRetryAsync(); + } + + @RpcReference(microserviceName = "com.servicecomb.filterServer", schemaId = "RetrySchema") + private RetrySchemaInf retrySchemaInf; + + RestOperations restTemplate = RestTemplateBuilder.create(); + + private AtomicLong counter = new AtomicLong(0); + + @GetMapping(path = "/governance/edgeSuccessWhenRetry") + public boolean edgeSuccessWhenRetry() { + if (counter.getAndIncrement() % 3 != 0) { + throw new InvocationException(Status.INTERNAL_SERVER_ERROR, "try again later."); + } + return true; + } + + @GetMapping(path = "/governance/edgeSuccessWhenRetryAsync") + public CompletableFuture edgeSuccessWhenRetryAsync() { + CompletableFuture result = new CompletableFuture<>(); + if (counter.getAndIncrement() % 2 == 0) { + result.completeExceptionally(new InvocationException(Status.INTERNAL_SERVER_ERROR, "try again later.")); + } else { + result.complete(true); + } + return result; + } + + @GetMapping(path = "/governance/successWhenRetry") + public boolean successWhenRetry() { + return restTemplate.getForObject("servicecomb://com.servicecomb.filterServer/retry/governance/successWhenRetry", + Boolean.class); + } + + @GetMapping(path = "/governance/successWhenRetryAsync") + public CompletableFuture successWhenRetryAsync() { + return retrySchemaInf.successWhenRetryAsync(); + } +} diff --git a/demo/demo-filter/filter-client/src/main/resources/log4j2.xml b/demo/demo-filter/filter-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-filter/filter-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-filter/filter-client/src/main/resources/microservice.yaml b/demo/demo-filter/filter-client/src/main/resources/microservice.yaml new file mode 100644 index 00000000000..72f90936c83 --- /dev/null +++ b/demo/demo-filter/filter-client/src/main/resources/microservice.yaml @@ -0,0 +1,48 @@ +## --------------------------------------------------------------------------- +## 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: filtertest + # test service name with dot + name: com.servicecomb.filterClient + version: 0.0.1 + + registry: + sc: + address: http://127.0.0.1:30100 + rest: + address: 0.0.0.0:8082 + server: + compression: true + highway: + address: 0.0.0.0:7072 + + invocation: + exception: + print-stack-trace: true + # test governance retry + matchGroup: + retry-governance: | + matches: + - apiPath: + prefix: "/retry/governance/" + + retry: + retry-governance: | + maxAttempts: 2 + retryOnResponseStatus: [500] diff --git a/demo/demo-filter/filter-edge/pom.xml b/demo/demo-filter/filter-edge/pom.xml new file mode 100644 index 00000000000..798f7b7697e --- /dev/null +++ b/demo/demo-filter/filter-edge/pom.xml @@ -0,0 +1,112 @@ + + + + + 4.0.0 + + org.apache.servicecomb.demo + demo-filter + 3.4.0-SNAPSHOT + + filter-edge + Java Chassis::Demo::Filter::Edge + + + + org.apache.servicecomb.demo + demo-schema + + + org.apache.servicecomb + edge-core + + + org.apache.servicecomb + foundation-test-scaffolding + + + + + org.apache.servicecomb.demo.filter.FilterEdge + + + + + + 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-filter/filter-edge/src/main/java/org/apache/servicecomb/demo/filter/FilterEdge.java b/demo/demo-filter/filter-edge/src/main/java/org/apache/servicecomb/demo/filter/FilterEdge.java new file mode 100644 index 00000000000..8ea4b7cb22d --- /dev/null +++ b/demo/demo-filter/filter-edge/src/main/java/org/apache/servicecomb/demo/filter/FilterEdge.java @@ -0,0 +1,49 @@ +/* + * 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.demo.filter; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class FilterEdge { + private static final Logger LOGGER = LoggerFactory.getLogger(FilterEdge.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder(FilterEdge.class).web(WebApplicationType.NONE).run(args); + + run(); + } catch (Throwable e) { + TestMgr.check("success", "failed"); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("filterEdge"); + } +} diff --git a/demo/demo-filter/filter-edge/src/main/resources/log4j2.xml b/demo/demo-filter/filter-edge/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-filter/filter-edge/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-filter/filter-edge/src/main/resources/microservice.yaml b/demo/demo-filter/filter-edge/src/main/resources/microservice.yaml new file mode 100644 index 00000000000..128a825e6d6 --- /dev/null +++ b/demo/demo-filter/filter-edge/src/main/resources/microservice.yaml @@ -0,0 +1,79 @@ +## --------------------------------------------------------------------------- +## 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: filtertest + # test service name with dot + name: com.servicecomb.filterEdge + version: 0.0.1 + + registry: + sc: + address: http://127.0.0.1:30100 + + rest: + address: 0.0.0.0:9090 + server: + compression: true + + edge: + filter: + addHeader: + allowedHeaders: X-B3-TraceId + + invocation: + exception: + print-stack-trace: true + + http: + dispatcher: + edge: + default: + enabled: true + prefix: service + withVersion: false + prefixSegmentCount: 2 + url: + enabled: true + mappings: + filterClient: + prefixSegmentCount: 0 + path: "/retry/.*" + microserviceName: com.servicecomb.filterClient + filterClient2: + prefixSegmentCount: 0 + path: "/govern/.*" + microserviceName: com.servicecomb.filterClient + matchGroup: + edgeFlowControl: | + matches: + - apiPath: + exact: "/govern/edgeFlowControl" + retry-governance: | + matches: + - apiPath: + prefix: "/retry/governance/" + rateLimiting: + edgeFlowControl: | + timeoutDuration: 0 + limitRefreshPeriod: 1000 + rate: 1 + retry: + retry-governance: | + maxAttempts: 2 + retryOnResponseStatus: [500] diff --git a/demo/demo-filter/filter-server/pom.xml b/demo/demo-filter/filter-server/pom.xml new file mode 100644 index 00000000000..b3f257fd875 --- /dev/null +++ b/demo/demo-filter/filter-server/pom.xml @@ -0,0 +1,102 @@ + + + + + 4.0.0 + + org.apache.servicecomb.demo + demo-filter + 3.4.0-SNAPSHOT + + filter-server + Java Chassis::Demo::Filter::Server + + + + org.apache.servicecomb.demo + demo-schema + + + + + org.apache.servicecomb.demo.filter.FilterServer + + + + + 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-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java new file mode 100644 index 00000000000..c947b0e7d0b --- /dev/null +++ b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/FilterServer.java @@ -0,0 +1,49 @@ +/* + * 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.demo.filter; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class FilterServer { + private static final Logger LOGGER = LoggerFactory.getLogger(FilterServer.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder(FilterServer.class).web(WebApplicationType.NONE).run(args); + + run(); + } catch (Throwable e) { + TestMgr.check("success", "failed"); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("filterServer"); + } +} diff --git a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/ExceptionSchema.java b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/ExceptionSchema.java new file mode 100644 index 00000000000..980681b6b96 --- /dev/null +++ b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/ExceptionSchema.java @@ -0,0 +1,42 @@ +/* + * 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.demo.filter.server; + +import java.util.concurrent.CompletableFuture; + +import jakarta.ws.rs.core.Response.Status; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RestSchema(schemaId = "ExceptionSchema") +@RequestMapping(path = "/exception", produces = MediaType.APPLICATION_JSON_VALUE) +public class ExceptionSchema { + @GetMapping(path = "/blockingException") + public boolean blockingException() { + throw new InvocationException(Status.SERVICE_UNAVAILABLE, new CommonExceptionData("Blocking Exception")); + } + + @GetMapping(path = "/reactiveException") + public CompletableFuture reactiveException() { + throw new InvocationException(Status.SERVICE_UNAVAILABLE, new CommonExceptionData("Reactive Exception")); + } +} diff --git a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/GovernanceProviderSchema.java b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/GovernanceProviderSchema.java new file mode 100644 index 00000000000..c2b5f37cadf --- /dev/null +++ b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/GovernanceProviderSchema.java @@ -0,0 +1,31 @@ +/* + * 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.demo.filter.server; + +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.RequestMapping; + +@RestSchema(schemaId = "GovernanceProviderSchema") +@RequestMapping(path = "/govern", produces = MediaType.APPLICATION_JSON_VALUE) +public class GovernanceProviderSchema { + @GetMapping(path = "/providerFlowControl") + public boolean providerFlowControl() { + return true; + } +} diff --git a/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/RetrySchema.java b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/RetrySchema.java new file mode 100644 index 00000000000..603f2a79e55 --- /dev/null +++ b/demo/demo-filter/filter-server/src/main/java/org/apache/servicecomb/demo/filter/server/RetrySchema.java @@ -0,0 +1,54 @@ +/* + * 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.demo.filter.server; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicLong; + +import jakarta.ws.rs.core.Response.Status; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +// test cases for retry +@RestSchema(schemaId = "RetrySchema") +@RequestMapping(path = "/retry", produces = MediaType.APPLICATION_JSON_VALUE) +public class RetrySchema { + private AtomicLong counter = new AtomicLong(0); + + @GetMapping(path = "/governance/successWhenRetry") + public boolean successWhenRetry() { + if (counter.getAndIncrement() % 3 != 0) { + throw new InvocationException(Status.INTERNAL_SERVER_ERROR, "try again later."); + } + return true; + } + + @GetMapping(path = "/governance/successWhenRetryAsync") + public CompletableFuture successWhenRetryAsync() { + CompletableFuture result = new CompletableFuture<>(); + if (counter.getAndIncrement() % 2 == 0) { + result.completeExceptionally(new InvocationException(Status.INTERNAL_SERVER_ERROR, "try again later.")); + } else { + result.complete(true); + } + return result; + } +} diff --git a/demo/demo-filter/filter-server/src/main/resources/log4j2.xml b/demo/demo-filter/filter-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-filter/filter-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-filter/filter-server/src/main/resources/microservice.yaml b/demo/demo-filter/filter-server/src/main/resources/microservice.yaml new file mode 100644 index 00000000000..bb96cf5f576 --- /dev/null +++ b/demo/demo-filter/filter-server/src/main/resources/microservice.yaml @@ -0,0 +1,62 @@ +## --------------------------------------------------------------------------- +## 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: filtertest + # test service name with dot + name: com.servicecomb.filterServer + version: 0.0.1 + + registry: + sc: + address: http://127.0.0.1:30100 + + rest: + address: 0.0.0.0:8080 + server: + compression: true + highway: + address: 0.0.0.0:7070 + + matchGroup: + providerFlowControl: | + matches: + - apiPath: + exact: "/govern/providerFlowControl" + rateLimiting: + providerFlowControl: | + timeoutDuration: 0 + limitRefreshPeriod: 1000 + rate: 1 + +#########SSL options +ssl.protocols: TLSv1.2 +ssl.authPeer: true +ssl.checkCN.host: true + +#########certificates config +ssl.trustStore: trust.jks +ssl.trustStoreType: JKS +ssl.trustStoreValue: Changeme_123 +ssl.keyStore: server.p12 +ssl.keyStoreType: PKCS12 +ssl.keyStoreValue: Changeme_123 +ssl.crl: revoke.crl +ssl.sslCustomClass: org.apache.servicecomb.demo.DemoSSLCustom + +vertx.disableFileCPResolving: false # false: create the .vertx directory, true: do not create diff --git a/demo/demo-filter/filter-tests/pom.xml b/demo/demo-filter/filter-tests/pom.xml new file mode 100644 index 00000000000..3936a85f517 --- /dev/null +++ b/demo/demo-filter/filter-tests/pom.xml @@ -0,0 +1,192 @@ + + + + + 4.0.0 + + org.apache.servicecomb.demo + demo-filter + 3.4.0-SNAPSHOT + + filter-tests + Java Chassis::Demo::Filter::Tests + + + + org.apache.servicecomb.demo + demo-schema + + + org.apache.servicecomb + registry-local + + + + + org.apache.servicecomb.demo.filter.FilterTests + + + + + docker + + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service30100 + + alias + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + filter-server:${project.version} + filter-server + + alias + + + -Dservicecomb.registry.sc.address=http://service30100:30100 + + /maven/maven/filter-server-${project.version}.jar + + + service30100:service30100 + + + ServiceComb is ready + + + 8080 + + + + + + 8080:8080 + + + + + filter-client:${project.version} + filter-client + + alias + + + -Dservicecomb.registry.sc.address=http://service30100:30100 + + /maven/maven/filter-client-${project.version}.jar + + + service30100:service30100 + + + ServiceComb is ready + + + 8082 + + + + + + 8082:8082 + + + + + filter-edge:${project.version} + filter-edge + + alias + + + -Dservicecomb.registry.sc.address=http://service30100:30100 + + /maven/maven/filter-edge-${project.version}.jar + + + service30100:service30100 + + + 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-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/FilterTests.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/FilterTests.java new file mode 100644 index 00000000000..0c7551b685d --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/FilterTests.java @@ -0,0 +1,49 @@ +/* + * 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.demo.filter; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class FilterTests { + private static final Logger LOGGER = LoggerFactory.getLogger(FilterTests.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder(FilterTests.class).web(WebApplicationType.NONE).run(args); + + run(); + } catch (Throwable e) { + TestMgr.check("success", "failed"); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("filterTests"); + } +} diff --git a/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestExceptionSchemaFromClient.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestExceptionSchemaFromClient.java new file mode 100644 index 00000000000..e404b38b8a9 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestExceptionSchemaFromClient.java @@ -0,0 +1,86 @@ +/* + * 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.demo.filter.tests; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +@Component +public class TestExceptionSchemaFromClient implements CategorizedTestCase { + + RestOperations restTemplate = RestTemplateBuilder.create(); + + private static final String SERVER = "servicecomb://com.servicecomb.filterClient"; + + @Override + public String getMicroserviceName() { + return "filterEdge"; + } + + @Override + public void testAllTransport() throws Exception { + testBlockingExceptionRestTemplate(); + testBlockingExceptionReference(); + testBlockingExceptionInvoker(); + testReactiveExceptionReference(); + } + + private void testBlockingExceptionRestTemplate() { + try { + restTemplate.getForObject(SERVER + "/exception/blockingExceptionRestTemplate", + boolean.class); + } catch (InvocationException e) { + TestMgr.check(503, e.getStatus().getStatusCode()); + TestMgr.check("Blocking Exception", ((CommonExceptionData) e.getErrorData()).getMessage()); + } + } + + private void testBlockingExceptionReference() { + try { + restTemplate.getForObject(SERVER + "/exception/blockingExceptionReference", + boolean.class); + } catch (InvocationException e) { + TestMgr.check(503, e.getStatus().getStatusCode()); + TestMgr.check("Blocking Exception", ((CommonExceptionData) e.getErrorData()).getMessage()); + } + } + + private void testBlockingExceptionInvoker() { + try { + restTemplate.getForObject(SERVER + "/exception/blockingExceptionInvoker", + boolean.class); + } catch (InvocationException e) { + TestMgr.check(503, e.getStatus().getStatusCode()); + TestMgr.check("Blocking Exception", ((CommonExceptionData) e.getErrorData()).getMessage()); + } + } + + private void testReactiveExceptionReference() { + try { + restTemplate.getForObject(SERVER + "/exception/reactiveExceptionReference", + boolean.class); + } catch (InvocationException e) { + TestMgr.check(503, e.getStatus().getStatusCode()); + TestMgr.check("Reactive Exception", ((CommonExceptionData) e.getErrorData()).getMessage()); + } + } +} diff --git a/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestGovernanceSchemaFromEdge.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestGovernanceSchemaFromEdge.java new file mode 100644 index 00000000000..cd9958b7624 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestGovernanceSchemaFromEdge.java @@ -0,0 +1,115 @@ +/* + * 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.demo.filter.tests; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class TestGovernanceSchemaFromEdge implements CategorizedTestCase { + interface GovernanceEdgeSchemaInf { + boolean edgeFlowControl(); + + boolean providerFlowControl(); + } + + @RpcReference(microserviceName = "com.servicecomb.filterEdge", schemaId = "GovernanceConsumerSchema") + private GovernanceEdgeSchemaInf retrySchemaInf; + + @Override + public String getMicroserviceName() { + return "com.servicecomb.filterEdge"; + } + + @Override + public void testRestTransport() throws Exception { + testEdgeFlowControl(); + testConsumerFlowControl(); + } + + private void testConsumerFlowControl() throws Exception { + CountDownLatch latch = new CountDownLatch(100); + AtomicBoolean expectedFailed = new AtomicBoolean(false); + AtomicBoolean notExpectedFailed = new AtomicBoolean(false); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + String name = "t-" + i + "-" + j; + new Thread(name) { + public void run() { + try { + boolean result = retrySchemaInf.providerFlowControl(); + if (!result) { + notExpectedFailed.set(true); + } + } catch (Exception e) { + if (!e.getMessage().contains("rate limited")) { + notExpectedFailed.set(true); + } + expectedFailed.set(true); + } + latch.countDown(); + } + }.start(); + } + Thread.sleep(100); + } + + latch.await(20, TimeUnit.SECONDS); + TestMgr.check(expectedFailed.get(), true); + TestMgr.check(notExpectedFailed.get(), false); + } + + private void testEdgeFlowControl() throws Exception { + CountDownLatch latch = new CountDownLatch(100); + AtomicBoolean expectedFailed = new AtomicBoolean(false); + AtomicBoolean notExpectedFailed = new AtomicBoolean(false); + + for (int i = 0; i < 10; i++) { + for (int j = 0; j < 10; j++) { + String name = "t-" + i + "-" + j; + new Thread(name) { + public void run() { + try { + boolean result = retrySchemaInf.edgeFlowControl(); + if (!result) { + notExpectedFailed.set(true); + } + } catch (Exception e) { + if (!e.getMessage().contains("rate limited")) { + notExpectedFailed.set(true); + } + expectedFailed.set(true); + } + latch.countDown(); + } + }.start(); + } + Thread.sleep(100); + } + + latch.await(20, TimeUnit.SECONDS); + TestMgr.check(expectedFailed.get(), true); + TestMgr.check(notExpectedFailed.get(), false); + } +} diff --git a/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestRetrySchemaFromClient.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestRetrySchemaFromClient.java new file mode 100644 index 00000000000..944f7831910 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestRetrySchemaFromClient.java @@ -0,0 +1,66 @@ +/* + * 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.demo.filter.tests; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +@Component +public class TestRetrySchemaFromClient implements CategorizedTestCase { + interface RetrySchemaInf { + boolean successWhenRetry(); + + CompletableFuture successWhenRetryAsync(); + } + + @RpcReference(microserviceName = "com.servicecomb.filterClient", schemaId = "RetryClientSchema") + private RetrySchemaInf retrySchemaInf; + + RestOperations restTemplate = RestTemplateBuilder.create(); + + private static final String SERVER = "servicecomb://com.servicecomb.filterClient"; + + @Override + public String getMicroserviceName() { + return "com.servicecomb.filterClient"; + } + + @Override + public void testAllTransport() throws Exception { + testRetryGovernanceRestTemplate(); + testRetryGovernanceRpc(); + } + + private void testRetryGovernanceRpc() throws Exception { + TestMgr.check(retrySchemaInf.successWhenRetry(), true); + TestMgr.check(retrySchemaInf.successWhenRetry(), true); + + TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true); + TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true); + } + + private void testRetryGovernanceRestTemplate() { + TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true); + TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true); + } +} diff --git a/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestRetrySchemaFromEdge.java b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestRetrySchemaFromEdge.java new file mode 100644 index 00000000000..b28eaff3cbc --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/java/org/apache/servicecomb/demo/filter/tests/TestRetrySchemaFromEdge.java @@ -0,0 +1,94 @@ +/* + * 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.demo.filter.tests; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + +@Component +public class TestRetrySchemaFromEdge implements CategorizedTestCase { + interface RetrySchemaInf { + boolean edgeSuccessWhenRetry(); + + boolean successWhenRetry(); + + CompletableFuture edgeSuccessWhenRetryAsync(); + + CompletableFuture successWhenRetryAsync(); + } + + @RpcReference(microserviceName = "com.servicecomb.filterEdge", schemaId = "RetryClientSchema") + private RetrySchemaInf retrySchemaInf; + + RestOperations restTemplate = RestTemplateBuilder.create(); + + RestTemplate springRestTemplate = new RestTemplate(); + + private static final String SERVER = "servicecomb://com.servicecomb.filterEdge"; + + private static final String EDGE_SERVER = "http://127.0.0.1:9090"; + + @Override + public String getMicroserviceName() { + return "com.servicecomb.filterEdge"; + } + + @Override + public void testRestTransport() throws Exception { + testRetryGovernanceFromEdgeDefaultDispatcher(); + testRetryGovernanceRestTemplate(); + testRetryGovernanceRpc(); + testEdgeRetryGovernanceRpc(); + } + + private void testRetryGovernanceRpc() throws Exception { + TestMgr.check(retrySchemaInf.successWhenRetry(), true); + TestMgr.check(retrySchemaInf.successWhenRetry(), true); + + TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true); + TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true); + } + + private void testEdgeRetryGovernanceRpc() throws Exception { + TestMgr.check(retrySchemaInf.edgeSuccessWhenRetry(), true); + TestMgr.check(retrySchemaInf.edgeSuccessWhenRetry(), true); + + TestMgr.check(retrySchemaInf.edgeSuccessWhenRetryAsync().get(), true); + TestMgr.check(retrySchemaInf.edgeSuccessWhenRetryAsync().get(), true); + } + + private void testRetryGovernanceRestTemplate() { + TestMgr.check(restTemplate.getForObject( + SERVER + "/retry/governance/successWhenRetry", boolean.class), true); + TestMgr.check(restTemplate.getForObject( + SERVER + "/retry/governance/successWhenRetry", boolean.class), true); + } + + private void testRetryGovernanceFromEdgeDefaultDispatcher() { + TestMgr.check(springRestTemplate.getForObject( + EDGE_SERVER + "/service/com.servicecomb.filterClient/retry/governance/successWhenRetry", boolean.class), true); + TestMgr.check(springRestTemplate.getForObject( + EDGE_SERVER + "/service/com.servicecomb.filterClient/retry/governance/successWhenRetry", boolean.class), true); + } +} diff --git a/demo/demo-filter/filter-tests/src/main/resources/log4j2.xml b/demo/demo-filter/filter-tests/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-filter/filter-tests/src/main/resources/microservice.yaml b/demo/demo-filter/filter-tests/src/main/resources/microservice.yaml new file mode 100644 index 00000000000..5694d54ac56 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/resources/microservice.yaml @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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: filtertest + # test service name with dot + name: com.servicecomb.filterTests + version: 0.0.1 + + registry: + sc: + address: http://127.0.0.1:30100 + + invocation: + exception: + print-stack-trace: true diff --git a/demo/demo-filter/filter-tests/src/main/resources/microservices/com.servicecomb.filterEdge/GovernanceConsumerSchema.yaml b/demo/demo-filter/filter-tests/src/main/resources/microservices/com.servicecomb.filterEdge/GovernanceConsumerSchema.yaml new file mode 100644 index 00000000000..b29502270ab --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/resources/microservices/com.servicecomb.filterEdge/GovernanceConsumerSchema.yaml @@ -0,0 +1,45 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +--- +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.filter.client.GovernanceConsumerSchema + version: 1.0.0 +servers: +- url: /govern +paths: + /edgeFlowControl: + get: + operationId: edgeFlowControl + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean + /providerFlowControl: + get: + operationId: providerFlowControl + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean +components: {} diff --git a/demo/demo-filter/filter-tests/src/main/resources/microservices/com.servicecomb.filterEdge/RetryClientSchema.yaml b/demo/demo-filter/filter-tests/src/main/resources/microservices/com.servicecomb.filterEdge/RetryClientSchema.yaml new file mode 100644 index 00000000000..77517becf68 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/resources/microservices/com.servicecomb.filterEdge/RetryClientSchema.yaml @@ -0,0 +1,65 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +--- +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.filter.client.RetryClientSchema + version: 1.0.0 +servers: +- url: /retry +paths: + /governance/edgeSuccessWhenRetry: + get: + operationId: edgeSuccessWhenRetry + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean + /governance/edgeSuccessWhenRetryAsync: + get: + operationId: edgeSuccessWhenRetryAsync + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean + /governance/successWhenRetry: + get: + operationId: successWhenRetry + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean + /governance/successWhenRetryAsync: + get: + operationId: successWhenRetryAsync + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean +components: {} diff --git a/demo/demo-filter/filter-tests/src/main/resources/registry.yaml b/demo/demo-filter/filter-tests/src/main/resources/registry.yaml new file mode 100644 index 00000000000..1e09e18eea2 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/main/resources/registry.yaml @@ -0,0 +1,23 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +com.servicecomb.filterEdge: + - id: "001" + version: "1.0" + appid: filtertest + instances: + - endpoints: + - rest://127.0.0.1:9090 diff --git a/demo/demo-filter/filter-tests/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterTestsIT.java b/demo/demo-filter/filter-tests/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterTestsIT.java new file mode 100644 index 00000000000..d09de401c20 --- /dev/null +++ b/demo/demo-filter/filter-tests/src/test/java/org/apache/servicecomb/demo/filter/retry/FilterTestsIT.java @@ -0,0 +1,44 @@ +/* + * 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.demo.filter.retry; + +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.filter.FilterTests; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = FilterTests.class) +public class FilterTestsIT { + + @BeforeEach + public void setUp() { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() throws Exception { + FilterTests.run(); + + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/demo-filter/pom.xml b/demo/demo-filter/pom.xml new file mode 100644 index 00000000000..45e0206faf1 --- /dev/null +++ b/demo/demo-filter/pom.xml @@ -0,0 +1,62 @@ + + + + + 4.0.0 + + org.apache.servicecomb.demo + demo-parent + 3.4.0-SNAPSHOT + + demo-filter + Java Chassis::Demo::Filter + pom + + filter-server + filter-client + filter-edge + filter-tests + + + + org.apache.servicecomb + solution-basic + + + org.apache.servicecomb + registry-service-center + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + + + diff --git a/demo/demo-jaxrs/jaxrs-client/pom.xml b/demo/demo-jaxrs/jaxrs-client/pom.xml index cea530a486e..d25a3cdecca 100644 --- a/demo/demo-jaxrs/jaxrs-client/pom.xml +++ b/demo/demo-jaxrs/jaxrs-client/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-jaxrs - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT jaxrs-client Java Chassis::Demo::JAXRS::Client @@ -33,56 +33,11 @@ org.apache.servicecomb.demo demo-schema - - org.apache.servicecomb - provider-jaxrs - - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - provider-pojo - - - - - - - - org.apache.servicecomb.demo.jaxrs.client.JaxrsClient + org.apache.servicecomb.demo.jaxrs.JaxrsClient - - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - docker @@ -90,6 +45,83 @@ jaxrs-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/JaxrsClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/JaxrsClient.java new file mode 100644 index 00000000000..2428e654774 --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/JaxrsClient.java @@ -0,0 +1,555 @@ +/* + * 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.demo.jaxrs; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpStatus; +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.CodeFirstRestTemplate; +import org.apache.servicecomb.demo.DemoConst; +import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper; +import org.apache.servicecomb.demo.RestObjectMapperWithStringMapperNotWriteNull; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.compute.Person; +import org.apache.servicecomb.demo.jaxrs.client.CodeFirstRestTemplateJaxrs; +import org.apache.servicecomb.demo.jaxrs.client.pojoDefault.DefaultModelServiceClient; +import org.apache.servicecomb.demo.jaxrs.client.validation.ValidationServiceClient; +import org.apache.servicecomb.demo.validator.Student; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response.Status; + +@SpringBootApplication +public class JaxrsClient { + private static final Logger LOGGER = LoggerFactory.getLogger(JaxrsClient.class); + + private static RestOperations templateNew = RestTemplateBuilder.create(); + + public static void main(String[] args) throws Exception { + new SpringApplicationBuilder(JaxrsClient.class).web(WebApplicationType.NONE).run(args); + + init(); + + try { + run(); + } catch (Exception e) { + TestMgr.check("success", "failed"); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + + TestMgr.summary(); + LOGGER.info("-------------- last time updated checks(maybe more/less): 540 -------------"); + } + + public static void init() throws Exception { + RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper()); + RestObjectMapperFactory.setConsumerWriterMapper(new RestObjectMapperWithStringMapperNotWriteNull()); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("jaxrs"); + + CodeFirstRestTemplate codeFirstClient = BeanUtils.getBean(CodeFirstRestTemplateJaxrs.class); + codeFirstClient.testCodeFirst(templateNew, "jaxrs", "/codeFirstJaxrs/"); + testCompute(templateNew); + testValidator(templateNew); + testJaxRSDefaultValuesAllTransport(templateNew); + testSpringMvcDefaultValuesJavaPrimitiveAllTransport(templateNew); + + DefaultModelServiceClient.run(); + ValidationServiceClient.run(); + + testOnlyRest(templateNew); + } + + private static void testOnlyRest(RestOperations template) { + String microserviceName = "jaxrs"; + String cseUrlPrefix = "cse://" + microserviceName; + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, "rest"); + + testGetRest(template, cseUrlPrefix); + testSpringMvcDefaultValuesJavaPrimitiveRest(templateNew); + } + + private static void testCompute(RestOperations template) throws Exception { + String microserviceName = "jaxrs"; + for (String transport : DemoConst.transports) { + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); + TestMgr.setMsg(microserviceName, transport); + + String cseUrlPrefix = "cse://" + microserviceName; + + testGetAllTransport(template, cseUrlPrefix); + testPost(template, cseUrlPrefix); + testPut(template, cseUrlPrefix); + testDelete(template, cseUrlPrefix); + testExchange(template, cseUrlPrefix); + testRawJsonParam(template, cseUrlPrefix); + } + } + + private static void testValidator(RestOperations template) { + String microserviceName = "jaxrs"; + for (String transport : DemoConst.transports) { + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); + TestMgr.setMsg(microserviceName, transport); + + String cseUrlPrefix = "cse://" + microserviceName + "/validator/"; + + testValidatorAddSuccess(template, cseUrlPrefix); + if ("rest".equals(transport)) { + testValidatorAddFail(template, cseUrlPrefix); + testValidatorSayHiFail(template, cseUrlPrefix); + testValidatorExchangeFail(template, cseUrlPrefix); + testJaxRSDefaultValuesRest(template); + } else if ("highway".equals(transport)) { + testValidatorAddFail(template, cseUrlPrefix); + testValidatorSayHiFail(template, cseUrlPrefix); + testValidatorExchangeFail(template, cseUrlPrefix); + } + testValidatorSayHiSuccess(template, cseUrlPrefix); + testValidatorExchangeSuccess(template, cseUrlPrefix); + } + } + + private static void testJaxRSDefaultValuesRest(RestOperations template) { + String result; + String microserviceName = "jaxrs"; + String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; + boolean failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + + failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(failed, true); + + failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(failed, true); + + result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); + TestMgr.check("Hello 20bobo40302", result); + + failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(failed, true); + } + + private static void testJaxRSDefaultValuesAllTransport(RestOperations template) { + String microserviceName = "jaxrs"; + for (String transport : DemoConst.transports) { + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); + TestMgr.setMsg(microserviceName, transport); + + String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; + + //default values + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap map = new LinkedMultiValueMap<>(); + HttpEntity> request = new HttpEntity<>(map, headers); + String result = template.postForObject(cseUrlPrefix + "/form", request, String.class); + // TODO: do not support form parameters default value + // TestMgr.check("Hello 20bobo", result); + TestMgr.check("Hello 0null", result); + + headers = new HttpHeaders(); + HttpEntity entity = new HttpEntity<>(null, headers); + result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); + TestMgr.check("Hello 20bobo30", result); + + result = template.getForObject(cseUrlPrefix + "/query?d=10", String.class); + TestMgr.check("Hello 20bobo4010", result); + boolean failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + + failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(failed, true); + + failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(failed, true); + + result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); + TestMgr.check("Hello 20bobo40302", result); + + failed = false; + try { + result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(failed, true); + + result = template.getForObject(cseUrlPrefix + "/query3?a=30&b=2", String.class); + TestMgr.check("Hello 302", result); + + result = template.getForObject(cseUrlPrefix + "/query3?a=30", String.class); + TestMgr.check("Hello 30null", result); + + //input values + headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); + Map params = new HashMap<>(); + params.put("a", "30"); + params.put("b", "sam"); + HttpEntity> requestPara = new HttpEntity<>(params, headers); + result = template.postForObject(cseUrlPrefix + "/form", requestPara, String.class); + TestMgr.check("Hello 30sam", result); + + headers = new HttpHeaders(); + headers.add("a", "30"); + headers.add("b", "sam"); + headers.add("c", "40"); + entity = new HttpEntity<>(null, headers); + result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); + TestMgr.check("Hello 30sam40", result); + + result = template.getForObject(cseUrlPrefix + "/query?a=3&b=sam&c=5&d=30", String.class); + TestMgr.check("Hello 3sam530", result); + + result = template.getForObject(cseUrlPrefix + "/query2?a=3&b=4&c=5&d=30&e=2", String.class); + TestMgr.check("Hello 345302", result); + } + } + + private static void testGetRest(RestOperations template, String cseUrlPrefix) { + Map params = new HashMap<>(); + params.put("a", "5"); + params.put("b", "3"); + int result = + template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, params); + TestMgr.check(2, result); + + result = template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, 5, 4); + TestMgr.check(1, result); + + result = template.getForObject(cseUrlPrefix + "/compute/reduce?a=5&b=6", + Integer.class); + TestMgr.check(-1, result); + } + + private static void testGetAllTransport(RestOperations template, String cseUrlPrefix) { + Map params = new HashMap<>(); + params.put("a", "5"); + params.put("b", "3"); + int result = + template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, params); + TestMgr.check(2, result); + + result = template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, 5, 4); + TestMgr.check(1, result); + + result = template.getForObject(cseUrlPrefix + "/compute/reduce?a=5&b=6", + Integer.class); + TestMgr.check(-1, result); + } + + private static void testPost(RestOperations template, String cseUrlPrefix) { + Map params = new HashMap<>(); + params.put("a", "5"); + params.put("b", "3"); + int result = + template.postForObject(cseUrlPrefix + "/compute/add", params, Integer.class); + TestMgr.check(8, result); + + Person person = new Person(); + person.setName("world"); + Person resultPerson = + template.postForObject(cseUrlPrefix + "/compute/sayhello", person, Person.class); + TestMgr.check("hello world", resultPerson.getName()); + + HttpHeaders headers = new HttpHeaders(); + headers.add("prefix", "haha"); + HttpEntity reqEntity = new HttpEntity<>(person, headers); + TestMgr.check("haha world", + template.postForObject(cseUrlPrefix + "/compute/saysomething", reqEntity, String.class)); + } + + private static void testPut(RestOperations template, String cseUrlPrefix) { + template.put(cseUrlPrefix + "/compute/sayhi/{name}", null, "world"); + } + + private static void testDelete(RestOperations template, String cseUrlPrefix) { + Map params = new HashMap<>(); + params.put("name", "world"); + template.delete(cseUrlPrefix + "/compute/sayhei/?name={name}", params); + } + + private static void testExchange(RestOperations template, String cseUrlPrefix) { + HttpHeaders headers = new HttpHeaders(); + headers.add("Accept", MediaType.APPLICATION_JSON); + Person person = new Person(); + person.setName("world"); + HttpEntity requestEntity = new HttpEntity<>(person, headers); + ResponseEntity resEntity = template.exchange(cseUrlPrefix + "/compute/sayhello", + HttpMethod.POST, + requestEntity, + Person.class); + TestMgr.check("hello world", resEntity.getBody()); + + ResponseEntity resEntity2 = + template.exchange(cseUrlPrefix + "/compute/addstring?s=abc&s=def", HttpMethod.DELETE, null, String.class); + TestMgr.check("abcdef", resEntity2.getBody()); + } + + private static void testRawJsonParam(RestOperations template, String cseUrlPrefix) throws Exception { + Map person = new HashMap<>(); + person.put("name", "Tom"); + String jsonPerson = RestObjectMapperFactory.getRestObjectMapper().writeValueAsString(person); + TestMgr.check("hello Tom", + template.postForObject(cseUrlPrefix + "/compute/testrawjson", jsonPerson, String.class)); + } + + @SuppressWarnings({"rawtypes"}) + private static void testValidatorAddFail(RestOperations template, String cseUrlPrefix) { + Map params = new HashMap<>(); + params.put("a", "5"); + params.put("b", "3"); + boolean isExcep = false; + try { + template.postForObject(cseUrlPrefix + "add", params, Integer.class); + } catch (InvocationException e) { + isExcep = true; + TestMgr.check(400, e.getStatus().getStatusCode()); + TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); + // Message depended on locale, so just check the short part. + // 'must be greater than or equal to 20', propertyPath=add.arg1, rootBeanClass=class org.apache.servicecomb.demo.jaxrs.server.Validator, messageTemplate='{jakarta.validation.constraints.Min.message}'}]] + // ignored + if (e.getErrorData() instanceof CommonExceptionData) { + // highway decode/encode 'Object' with special type information, got runtime type + CommonExceptionData data = (CommonExceptionData) e.getErrorData(); + TestMgr.check("invalid parameters.", data.getMessage()); + TestMgr.check("add.b", + ((Map) ((List) data.getDynamic("validateDetail")).get(0)).get("propertyPath").toString()); + } else { + // rest decode/encode 'Object' using json without type information, got map. Users can got runtime type by adding @JsonTypeInfo to the model. + Map data = (Map) e.getErrorData(); + TestMgr.check("invalid parameters.", data.get("message").toString()); + TestMgr.check("add.b", + ((Map) ((List) data.get("validateDetail")).get(0)).get("propertyPath").toString()); + } + } + + TestMgr.check(true, isExcep); + } + + private static void testValidatorAddSuccess(RestOperations template, String cseUrlPrefix) { + Map params = new HashMap<>(); + params.put("a", "5"); + params.put("b", "20"); + int result = template.postForObject(cseUrlPrefix + "add", params, Integer.class); + TestMgr.check(25, result); + } + + @SuppressWarnings({"rawtypes"}) + private static void testValidatorSayHiFail(RestOperations template, String cseUrlPrefix) { + boolean isExcep = false; + try { + template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, String.class, "te"); + } catch (InvocationException e) { + isExcep = true; + TestMgr.check(400, e.getStatus().getStatusCode()); + TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); + // Message depended on locale, so just check the short part. + if (e.getErrorData() instanceof CommonExceptionData) { + // highway decode/encode 'Object' with special type information, got runtime type + CommonExceptionData data = (CommonExceptionData) e.getErrorData(); + TestMgr.check("invalid parameters.", data.getMessage()); + TestMgr.check("sayHi.name", + ((Map) ((List) data.getDynamic("validateDetail")).get(0)).get("propertyPath").toString()); + } else { + Map data = (Map) e.getErrorData(); + TestMgr.check("invalid parameters.", data.get("message").toString()); + TestMgr.check("sayHi.name", + ((Map) ((List) data.get("validateDetail")).get(0)).get("propertyPath").toString()); + } + } + TestMgr.check(true, isExcep); + } + + private static void testValidatorSayHiSuccess(RestOperations template, String cseUrlPrefix) { + ResponseEntity responseEntity = + template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, String.class, "world"); + TestMgr.check(202, responseEntity.getStatusCode().value()); + TestMgr.check("world sayhi", responseEntity.getBody()); + } + + @SuppressWarnings({"rawtypes"}) + private static void testValidatorExchangeFail(RestOperations template, String cseUrlPrefix) { + HttpHeaders headers = new HttpHeaders(); + headers.add("Accept", MediaType.APPLICATION_JSON); + Student student = new Student(); + student.setName(""); + student.setAge(25); + boolean isExcep = false; + try { + HttpEntity requestEntity = new HttpEntity<>(student, headers); + template.exchange(cseUrlPrefix + "/sayhello", + HttpMethod.POST, + requestEntity, + Student.class); + } catch (InvocationException e) { + isExcep = true; + TestMgr.check(400, e.getStatus().getStatusCode()); + TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); + // Message depended on locale, so just check the short part. + if (e.getErrorData() instanceof CommonExceptionData) { + // highway decode/encode 'Object' with special type information, got runtime type + CommonExceptionData data = (CommonExceptionData) e.getErrorData(); + TestMgr.check("invalid parameters.", data.getMessage()); + TestMgr.check("sayHello.student.age", + ((Map) ((List) data.getDynamic("validateDetail")).get(0)).get("propertyPath").toString()); + } else { + Map data = (Map) e.getErrorData(); + TestMgr.check("invalid parameters.", data.get("message").toString()); + TestMgr.check("sayHello.student.age", + ((Map) ((List) data.get("validateDetail")).get(0)).get("propertyPath").toString()); + } + } + TestMgr.check(true, isExcep); + } + + private static void testValidatorExchangeSuccess(RestOperations template, String cseUrlPrefix) { + Student student = new Student(); + student.setName("test"); + student.setAge(15); + Student result = template.postForObject(cseUrlPrefix + "sayhello", student, Student.class); + TestMgr.check("hello test 15", result); + } + + private static void testSpringMvcDefaultValuesJavaPrimitiveRest(RestOperations template) { + String microserviceName = "jaxrs"; + String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap map = new LinkedMultiValueMap<>(); + HttpEntity> request = new HttpEntity<>(map, headers); + + //default values with primitive + String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", request, String.class); + // TODO: form default values support +// TestMgr.check("Hello 0bobo", result); + TestMgr.check("Hello 0null", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", request, String.class); + TestMgr.check("Hello 0.0false", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", request, String.class); + TestMgr.check("Hello", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", request, String.class); + TestMgr.check("Hello nullnull", result); + + result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); + TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); + } + + private static void testSpringMvcDefaultValuesJavaPrimitiveAllTransport(RestOperations template) { + String microserviceName = "jaxrs"; + for (String transport : DemoConst.transports) { + CategorizedTestCaseRunner.changeTransport(microserviceName, transport); + + String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap map = new LinkedMultiValueMap<>(); + HttpEntity> request = new HttpEntity<>(map, headers); + + //default values with primitive + String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", request, String.class); + // TODO: form default values support +// TestMgr.check("Hello 0bobo", result); + TestMgr.check("Hello 0null", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", request, String.class); + TestMgr.check("Hello 0.0false", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", request, String.class); + TestMgr.check("Hello", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", request, String.class); + TestMgr.check("Hello nullnull", result); + + result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); + TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); + } + } +} diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java index b44dd45839e..66c5ab958b4 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CodeFirstRestTemplateJaxrs.java @@ -17,107 +17,46 @@ package org.apache.servicecomb.demo.jaxrs.client; -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -import javax.ws.rs.core.MediaType; - -import org.apache.commons.io.FileUtils; import org.apache.servicecomb.demo.CodeFirstRestTemplate; import org.apache.servicecomb.demo.TestMgr; -import org.springframework.core.io.FileSystemResource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; +@Component public class CodeFirstRestTemplateJaxrs extends CodeFirstRestTemplate { @Override - protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) { + protected void testAllTransport(String microserviceName, RestOperations template, String cseUrlPrefix) { testDefaultPath(template, cseUrlPrefix); test404(template); super.testAllTransport(microserviceName, template, cseUrlPrefix); } - private void testDefaultPath(RestTemplate template, String cseUrlPrefix) { + private void testDefaultPath(RestOperations template, String cseUrlPrefix) { int result = template.getForObject(cseUrlPrefix.substring(0, cseUrlPrefix.length() - 1), Integer.class); TestMgr.check(100, result); } @Override - protected void testOnlyRest(String microserviceName, RestTemplate template, String cseUrlPrefix) { - try { - testUpload(template, cseUrlPrefix); - } catch (IOException e) { - throw new IllegalStateException(e); - } + protected void testOnlyRest(String microserviceName, RestOperations template, String cseUrlPrefix) { super.testOnlyRest(microserviceName, template, cseUrlPrefix); } - private void testUpload(RestTemplate template, String cseUrlPrefix) throws IOException { - String file1Content = "Hello World"; - File file1 = File.createTempFile("jaxrstest1", ".txt"); - FileUtils.writeStringToFile(file1, file1Content, StandardCharsets.UTF_8, false); - - testFileUpload(template, cseUrlPrefix, file1, file1Content); - testFileAndStringUpload(template, cseUrlPrefix, file1, file1Content); - } - - private void testFileUpload(RestTemplate template, String cseUrlPrefix, File file1, String file1Content) - throws IOException { - Map map = new HashMap<>(); - map.put("file1", new FileSystemResource(file1)); - String file2Content = "Hello EveryOne"; - File file2 = File.createTempFile("测试2", ".txt"); - FileUtils.writeStringToFile(file2, file2Content, StandardCharsets.UTF_8, false); - map.put("file2", new FileSystemResource(file2)); - - String result1 = template.postForObject(cseUrlPrefix + "/upload1", new HttpEntity<>(new HashMap<>()), String.class); - TestMgr.check("null file", result1); - - String expect = String.format("%s:%s:%s\n" + "%s:%s:%s", - file1.getName(), - MediaType.TEXT_PLAIN, - file1Content, - file2.getName(), - MediaType.TEXT_PLAIN, - file2Content); - String result2 = template.postForObject(cseUrlPrefix + "/upload1", new HttpEntity<>(map), String.class); - TestMgr.check(expect, result2); - } - - private void testFileAndStringUpload(RestTemplate template, String cseUrlPrefix, File file1, String file1Content) { - Map map = new HashMap<>(); - String message = "hi"; - map.put("file1", new FileSystemResource(file1)); - map.put("message", message); - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA); - String expect = String.format("%s:%s:%s:%s", - file1.getName(), - MediaType.TEXT_PLAIN, - file1Content, - message); - String result = template.postForObject(cseUrlPrefix + "/upload2", new HttpEntity<>(map, headers), String.class); - TestMgr.check(expect, result); - } - private void test404(RestTemplate template) { + private void test404(RestOperations template) { HttpClientErrorException exception = null; try { template.getForEntity("http://127.0.0.1:8080/aPathNotExist", String.class); + TestMgr.check("expect throw but not", ""); } catch (RestClientException e) { if (e instanceof HttpClientErrorException) { exception = (HttpClientErrorException) e; } } - TestMgr.check(404, exception.getRawStatusCode()); - TestMgr.check("404 Not Found: [{\"message\":\"Not Found\"}]", exception.getMessage()); + TestMgr.check(404, exception.getStatusCode().value()); + TestMgr.check(true, exception.getMessage().contains("404 Not Found")); } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java index d6986123657..9614164a05f 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/CustomLoadbalanceExtensionsFactory.java @@ -22,46 +22,21 @@ import org.apache.servicecomb.loadbalance.RuleExt; import org.springframework.stereotype.Component; -import com.netflix.client.DefaultLoadBalancerRetryHandler; -import com.netflix.client.RetryHandler; -import com.netflix.client.Utils; - @Component public class CustomLoadbalanceExtensionsFactory implements ExtensionsFactory { - class MyCustomRule extends RoundRobinRuleExt { - - } - - class MyCustomHandler extends DefaultLoadBalancerRetryHandler { - @Override - public boolean isRetriableException(Throwable e, boolean sameServer) { - if (retryEnabled) { - return Utils.isPresentAsCause(e, getRetriableExceptions()); - } - return false; - } + static class MyCustomRule extends RoundRobinRuleExt { - public MyCustomHandler(int retrySameServer, int retryNextServer, boolean retryEnabled) { - super(retrySameServer, retryNextServer, retryEnabled); - } } @Override public boolean isSupport(String key, String value) { return (Configuration.RULE_STRATEGY_NAME.equals(key) && - "mycustomrule".equals(value)) - || (Configuration.RETRY_HANDLER.equals(key) && - "mycustomhandler".equals(value)); + "mycustomrule".equals(value)); } @Override public RuleExt createLoadBalancerRule(String ruleName) { return new MyCustomRule(); } - - @Override - public RetryHandler createRetryHandler(String retryName, String microservice) { - return new MyCustomHandler(1, 1, true); - } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java deleted file mode 100644 index 36f63c01434..00000000000 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/JaxrsClient.java +++ /dev/null @@ -1,535 +0,0 @@ -/* - * 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.demo.jaxrs.client; - -import java.util.HashMap; -import java.util.Map; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; - -import org.apache.http.HttpStatus; -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.demo.CategorizedTestCaseRunner; -import org.apache.servicecomb.demo.CodeFirstRestTemplate; -import org.apache.servicecomb.demo.DemoConst; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapperNotWriteNull; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.compute.Person; -import org.apache.servicecomb.demo.jaxrs.client.pojoDefault.DefaultModelServiceClient; -import org.apache.servicecomb.demo.jaxrs.client.validation.ValidationServiceClient; -import org.apache.servicecomb.demo.validator.Student; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -public class JaxrsClient { - private static final Logger LOGGER = LoggerFactory.getLogger(JaxrsClient.class); - - private static RestTemplate templateNew = RestTemplateBuilder.create(); - - public static void main(String[] args) throws Exception { - init(); - - try { - run(); - } catch (Exception e) { - TestMgr.check("success", "failed"); - LOGGER.error("-------------- test failed -------------"); - LOGGER.error("", e); - LOGGER.error("-------------- test failed -------------"); - } - - TestMgr.summary(); - } - - public static void init() throws Exception { - BeanUtils.init(); - RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper()); - RestObjectMapperFactory.setConsumerWriterMapper(new RestObjectMapperWithStringMapperNotWriteNull()); - } - - public static void run() throws Exception { - CategorizedTestCaseRunner.runCategorizedTestCase("jaxrs"); - - CodeFirstRestTemplate codeFirstClient = new CodeFirstRestTemplateJaxrs(); - codeFirstClient.testCodeFirst(templateNew, "jaxrs", "/codeFirstJaxrs/"); - testCompute(templateNew); - testValidator(templateNew); - testJaxRSDefaultValuesAllTransport(templateNew); - testSpringMvcDefaultValuesJavaPrimitiveAllTransport(templateNew); - - DefaultModelServiceClient.run(); - ValidationServiceClient.run(); - - testOnlyRest(templateNew); - } - - private static void testOnlyRest(RestTemplate template) { - String microserviceName = "jaxrs"; - String cseUrlPrefix = "cse://" + microserviceName; - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, "rest"); - - testGetRest(template, cseUrlPrefix); - testSpringMvcDefaultValuesJavaPrimitiveRest(templateNew); - } - - private static void testCompute(RestTemplate template) throws Exception { - String microserviceName = "jaxrs"; - for (String transport : DemoConst.transports) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); - TestMgr.setMsg(microserviceName, transport); - - String cseUrlPrefix = "cse://" + microserviceName; - - testGetAllTransport(template, cseUrlPrefix); - testPost(template, cseUrlPrefix); - testPut(template, cseUrlPrefix); - testDelete(template, cseUrlPrefix); - testExchange(template, cseUrlPrefix); - testRawJsonParam(template, cseUrlPrefix); - } - } - - private static void testValidator(RestTemplate template) { - String microserviceName = "jaxrs"; - for (String transport : DemoConst.transports) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); - TestMgr.setMsg(microserviceName, transport); - - String cseUrlPrefix = "cse://" + microserviceName + "/validator/"; - - testValidatorAddSuccess(template, cseUrlPrefix); - if ("rest".equals(transport)) { - testValidatorAddFail(template, cseUrlPrefix); - testValidatorSayHiFail(template, cseUrlPrefix); - testValidatorExchangeFail(template, cseUrlPrefix); - testJaxRSDefaultValuesRest(template); - } else if ("highway".equals(transport)) { - testValidatorAddFail(template, cseUrlPrefix); - testValidatorSayHiFail(template, cseUrlPrefix); - testValidatorExchangeFail(template, cseUrlPrefix); - } - testValidatorSayHiSuccess(template, cseUrlPrefix); - testValidatorExchangeSuccess(template, cseUrlPrefix); - } - } - - private static void testJaxRSDefaultValuesRest(RestTemplate template) { - String result; - String microserviceName = "jaxrs"; - String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; - boolean failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - - failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(failed, true); - - failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(failed, true); - - result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); - TestMgr.check("Hello 20bobo40302", result); - - failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(failed, true); - } - - private static void testJaxRSDefaultValuesAllTransport(RestTemplate template) { - String microserviceName = "jaxrs"; - for (String transport : DemoConst.transports) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); - TestMgr.setMsg(microserviceName, transport); - - String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; - - //default values - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); - MultiValueMap map = new LinkedMultiValueMap<>(); - HttpEntity> request = new HttpEntity<>(map, headers); - String result = template.postForObject(cseUrlPrefix + "/form", request, String.class); - TestMgr.check("Hello 20bobo", result); - - headers = new HttpHeaders(); - HttpEntity entity = new HttpEntity<>(null, headers); - result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); - TestMgr.check("Hello 20bobo30", result); - - result = template.getForObject(cseUrlPrefix + "/query?d=10", String.class); - TestMgr.check("Hello 20bobo4010", result); - boolean failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - - failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(failed, true); - - failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(failed, true); - - result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); - TestMgr.check("Hello 20bobo40302", result); - - failed = false; - try { - result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(failed, true); - - result = template.getForObject(cseUrlPrefix + "/query3?a=30&b=2", String.class); - TestMgr.check("Hello 302", result); - - result = template.getForObject(cseUrlPrefix + "/query3?a=30", String.class); - TestMgr.check("Hello 30null", result); - - //input values - headers = new HttpHeaders(); - headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); - Map params = new HashMap<>(); - params.put("a", "30"); - params.put("b", "sam"); - HttpEntity> requestPara = new HttpEntity<>(params, headers); - result = template.postForObject(cseUrlPrefix + "/form", requestPara, String.class); - TestMgr.check("Hello 30sam", result); - - headers = new HttpHeaders(); - headers.add("a", "30"); - headers.add("b", "sam"); - headers.add("c", "40"); - entity = new HttpEntity<>(null, headers); - result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); - TestMgr.check("Hello 30sam40", result); - - result = template.getForObject(cseUrlPrefix + "/query?a=3&b=sam&c=5&d=30", String.class); - TestMgr.check("Hello 3sam530", result); - - result = template.getForObject(cseUrlPrefix + "/query2?a=3&b=4&c=5&d=30&e=2", String.class); - TestMgr.check("Hello 345302", result); - } - } - - private static void testGetRest(RestTemplate template, String cseUrlPrefix) { - Map params = new HashMap<>(); - params.put("a", "5"); - params.put("b", "3"); - int result = - template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, params); - TestMgr.check(2, result); - - result = template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, 5, 4); - TestMgr.check(1, result); - - result = template.getForObject(cseUrlPrefix + "/compute/reduce?a=5&b=6", - Integer.class); - TestMgr.check(-1, result); - } - - private static void testGetAllTransport(RestTemplate template, String cseUrlPrefix) { - Map params = new HashMap<>(); - params.put("a", "5"); - params.put("b", "3"); - int result = - template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, params); - TestMgr.check(2, result); - - result = template.getForObject(cseUrlPrefix + "/compute/reduce?a={a}&b={b}", Integer.class, 5, 4); - TestMgr.check(1, result); - - result = template.getForObject(cseUrlPrefix + "/compute/reduce?a=5&b=6", - Integer.class); - TestMgr.check(-1, result); - } - - private static void testPost(RestTemplate template, String cseUrlPrefix) { - Map params = new HashMap<>(); - params.put("a", "5"); - params.put("b", "3"); - int result = - template.postForObject(cseUrlPrefix + "/compute/add", params, Integer.class); - TestMgr.check(8, result); - - Person person = new Person(); - person.setName("world"); - Person resultPerson = - template.postForObject(cseUrlPrefix + "/compute/sayhello", person, Person.class); - TestMgr.check("hello world", resultPerson.getName()); - - HttpHeaders headers = new HttpHeaders(); - headers.add("prefix", "haha"); - HttpEntity reqEntity = new HttpEntity<>(person, headers); - TestMgr.check("haha world", - template.postForObject(cseUrlPrefix + "/compute/saysomething", reqEntity, String.class)); - } - - private static void testPut(RestTemplate template, String cseUrlPrefix) { - template.put(cseUrlPrefix + "/compute/sayhi/{name}", null, "world"); - } - - private static void testDelete(RestTemplate template, String cseUrlPrefix) { - Map params = new HashMap<>(); - params.put("name", "world"); - template.delete(cseUrlPrefix + "/compute/sayhei/?name={name}", params); - } - - private static void testExchange(RestTemplate template, String cseUrlPrefix) { - HttpHeaders headers = new HttpHeaders(); - headers.add("Accept", MediaType.APPLICATION_JSON); - Person person = new Person(); - person.setName("world"); - HttpEntity requestEntity = new HttpEntity<>(person, headers); - ResponseEntity resEntity = template.exchange(cseUrlPrefix + "/compute/sayhello", - HttpMethod.POST, - requestEntity, - Person.class); - TestMgr.check("hello world", resEntity.getBody()); - - ResponseEntity resEntity2 = - template.exchange(cseUrlPrefix + "/compute/addstring?s=abc&s=def", HttpMethod.DELETE, null, String.class); - TestMgr.check("abcdef", resEntity2.getBody()); - } - - private static void testRawJsonParam(RestTemplate template, String cseUrlPrefix) throws Exception { - Map person = new HashMap<>(); - person.put("name", "Tom"); - String jsonPerson = RestObjectMapperFactory.getRestObjectMapper().writeValueAsString(person); - TestMgr.check("hello Tom", - template.postForObject(cseUrlPrefix + "/compute/testrawjson", jsonPerson, String.class)); - } - - @SuppressWarnings({"rawtypes"}) - private static void testValidatorAddFail(RestTemplate template, String cseUrlPrefix) { - Map params = new HashMap<>(); - params.put("a", "5"); - params.put("b", "3"); - boolean isExcep = false; - try { - template.postForObject(cseUrlPrefix + "add", params, Integer.class); - } catch (InvocationException e) { - isExcep = true; - TestMgr.check(400, e.getStatus().getStatusCode()); - TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); - // Message dependends on locale, so just check the short part. - // 'must be greater than or equal to 20', propertyPath=add.arg1, rootBeanClass=class org.apache.servicecomb.demo.jaxrs.server.Validator, messageTemplate='{javax.validation.constraints.Min.message}'}]] - // ignored - if (e.getErrorData() instanceof CommonExceptionData) { - // highway decode/encode 'Object' with special type information, got runtime type - CommonExceptionData data = (CommonExceptionData) e.getErrorData(); - TestMgr.check( - true, data.getMessage().contains("propertyPath=add.b")); - } else { - // rest decode/encode 'Object' using json without type information, got map. Users can got runtime type by adding @JsonTypeInfo to the model. - Map data = (Map) e.getErrorData(); - TestMgr.check( - true, data.get("message").toString().contains("propertyPath=add.b")); - } - } - - TestMgr.check(true, isExcep); - } - - private static void testValidatorAddSuccess(RestTemplate template, String cseUrlPrefix) { - Map params = new HashMap<>(); - params.put("a", "5"); - params.put("b", "20"); - int result = template.postForObject(cseUrlPrefix + "add", params, Integer.class); - TestMgr.check(25, result); - } - - @SuppressWarnings({"rawtypes"}) - private static void testValidatorSayHiFail(RestTemplate template, String cseUrlPrefix) { - boolean isExcep = false; - try { - template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, String.class, "te"); - } catch (InvocationException e) { - isExcep = true; - TestMgr.check(400, e.getStatus().getStatusCode()); - TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); - // Message dependends on locale, so just check the short part. - if (e.getErrorData() instanceof CommonExceptionData) { - // highway decode/encode 'Object' with special type information, got runtime type - CommonExceptionData data = (CommonExceptionData) e.getErrorData(); - TestMgr.check( - true, data.getMessage().contains("propertyPath=sayHi.name")); - } else { - Map data = (Map) e.getErrorData(); - TestMgr.check( - true, data.get("message").toString().contains("propertyPath=sayHi.name")); - } - } - TestMgr.check(true, isExcep); - } - - private static void testValidatorSayHiSuccess(RestTemplate template, String cseUrlPrefix) { - ResponseEntity responseEntity = - template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, String.class, "world"); - TestMgr.check(202, responseEntity.getStatusCodeValue()); - TestMgr.check("world sayhi", responseEntity.getBody()); - } - - @SuppressWarnings({"rawtypes"}) - private static void testValidatorExchangeFail(RestTemplate template, String cseUrlPrefix) { - HttpHeaders headers = new HttpHeaders(); - headers.add("Accept", MediaType.APPLICATION_JSON); - Student student = new Student(); - student.setName(""); - student.setAge(25); - boolean isExcep = false; - try { - HttpEntity requestEntity = new HttpEntity<>(student, headers); - template.exchange(cseUrlPrefix + "/sayhello", - HttpMethod.POST, - requestEntity, - Student.class); - } catch (InvocationException e) { - isExcep = true; - TestMgr.check(400, e.getStatus().getStatusCode()); - TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); - // Message dependends on locale, so just check the short part. - if (e.getErrorData() instanceof CommonExceptionData) { - // highway decode/encode 'Object' with special type information, got runtime type - CommonExceptionData data = (CommonExceptionData) e.getErrorData(); - TestMgr.check( - true, data.getMessage().contains("propertyPath=sayHello.student.age")); - } else { - Map data = (Map) e.getErrorData(); - TestMgr.check( - true, data.get("message").toString().contains("propertyPath=sayHello.student.age")); - } - } - TestMgr.check(true, isExcep); - } - - private static void testValidatorExchangeSuccess(RestTemplate template, String cseUrlPrefix) { - Student student = new Student(); - student.setName("test"); - student.setAge(15); - Student result = template.postForObject(cseUrlPrefix + "sayhello", student, Student.class); - TestMgr.check("hello test 15", result); - } - - private static void testSpringMvcDefaultValuesJavaPrimitiveRest(RestTemplate template) { - String microserviceName = "jaxrs"; - String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); - MultiValueMap map = new LinkedMultiValueMap<>(); - HttpEntity> request = new HttpEntity<>(map, headers); - - //default values with primitive - String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", request, String.class); - TestMgr.check("Hello 0bobo", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", request, String.class); - TestMgr.check("Hello 0.0false", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", request, String.class); - TestMgr.check("Hello", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", request, String.class); - TestMgr.check("Hello nullnull", result); - - result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); - TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); - } - - private static void testSpringMvcDefaultValuesJavaPrimitiveAllTransport(RestTemplate template) { - String microserviceName = "jaxrs"; - for (String transport : DemoConst.transports) { - CategorizedTestCaseRunner.changeTransport(microserviceName, transport); - - String cseUrlPrefix = "cse://" + microserviceName + "/JaxRSDefaultValues/"; - - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED); - MultiValueMap map = new LinkedMultiValueMap<>(); - HttpEntity> request = new HttpEntity<>(map, headers); - - //default values with primitive - String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", request, String.class); - TestMgr.check("Hello 0bobo", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", request, String.class); - TestMgr.check("Hello 0.0false", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", request, String.class); - TestMgr.check("Hello", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", request, String.class); - TestMgr.check("Hello nullnull", result); - - result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); - TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); - } - } -} diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java index c702682df5e..5eba5b94c95 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/MultiErrorCodeServiceClient.java @@ -19,8 +19,6 @@ import java.util.List; import java.util.Map; -import javax.ws.rs.core.Response.Status; - import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; @@ -28,33 +26,24 @@ import org.apache.servicecomb.demo.multiErrorCode.MultiResponse200; import org.apache.servicecomb.demo.multiErrorCode.MultiResponse400; import org.apache.servicecomb.demo.multiErrorCode.MultiResponse500; -import org.apache.servicecomb.foundation.common.net.URIEndpointObject; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.definition.DefinitionConst; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; import io.vertx.core.json.Json; import io.vertx.core.json.JsonObject; +import jakarta.ws.rs.core.Response.Status; @Component public class MultiErrorCodeServiceClient implements CategorizedTestCase { private static final String SERVER = "cse://jaxrs"; - private static String serverDirectURL; - - private static RestTemplate template = RestTemplateBuilder.create(); + private static RestOperations template = RestTemplateBuilder.create(); @Override public void testAllTransport() throws Exception { @@ -67,7 +56,6 @@ public void testAllTransport() throws Exception { @Override public void testRestTransport() throws Exception { - prepareServerDirectURL(); testErrorCodeWrongType(); } @@ -76,54 +64,39 @@ public void testHighwayTransport() throws Exception { } - private static void prepareServerDirectURL() { - Microservice microservice = RegistrationManager.INSTANCE.getMicroservice(); - MicroserviceInstance microserviceInstance = (MicroserviceInstance) DiscoveryManager.INSTANCE - .getAppManager() - .getOrCreateMicroserviceVersionRule(microservice.getAppId(), "jaxrs", DefinitionConst.VERSION_RULE_ALL) - .getVersionedCache() - .mapData() - .values() - .stream() - .findFirst() - .get(); - URIEndpointObject edgeAddress = new URIEndpointObject(microserviceInstance.getEndpoints().get(0)); - serverDirectURL = String.format("http://%s:%d/", edgeAddress.getHostOrIp(), edgeAddress.getPort()); - } private static void testErrorCodeWrongType() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); String body = "{\"message\":\"hello\",\"code\":\"wrongType\""; HttpEntity entity = new HttpEntity<>(body, headers); - ResponseEntity result; try { template - .postForEntity(serverDirectURL + "/MultiErrorCodeService/errorCode", entity, MultiResponse200.class); - } catch (HttpClientErrorException e) { - TestMgr.check(e.getRawStatusCode(), 400); - TestMgr.check(e.getMessage(), - "400 Bad Request: [{\"message\":\"Parameter is not valid for operation " - + "[jaxrs.MultiErrorCodeService.errorCode]. Parameter is [request]. " - + "Processor is [body].\"}]"); + .postForEntity(SERVER + "/MultiErrorCodeService/errorCode", entity, MultiResponse200.class); + TestMgr.fail("expect failed."); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 400); } entity = new HttpEntity<>(null, headers); try { - result = template - .postForEntity(serverDirectURL + "/MultiErrorCodeService/errorCode", entity, MultiResponse200.class); - TestMgr.check(590, 200); - } catch (HttpServerErrorException e) { - TestMgr.check(e.getRawStatusCode(), 500); + template + .postForEntity(SERVER + "/MultiErrorCodeService/errorCode", entity, MultiResponse200.class); + TestMgr.fail("expect failed."); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 400); } - // not recommend + // wrong type body = "{\"message\":\"hello\",\"code\":\"200\"}"; entity = new HttpEntity<>(body, headers); - result = template - .postForEntity(serverDirectURL + "/MultiErrorCodeService/errorCode", entity, MultiResponse200.class); - TestMgr.check(result.getStatusCodeValue(), 200); - TestMgr.check(result.getBody().getMessage(), "success result"); + try { + template + .postForEntity(SERVER + "/MultiErrorCodeService/errorCode", entity, MultiResponse200.class); + TestMgr.fail("expect failed."); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 400); + } } private static void testErrorCode() { @@ -132,7 +105,7 @@ private static void testErrorCode() { request.setCode(200); ResponseEntity result = template .postForEntity(SERVER + "/MultiErrorCodeService/errorCode", request, MultiResponse200.class); - TestMgr.check(result.getStatusCodeValue(), 200); + TestMgr.check(result.getStatusCode().value(), 200); TestMgr.check(result.getBody().getMessage(), "success result"); request.setCode(400); @@ -162,7 +135,7 @@ private static void testErrorCodeWithHeader() { request.setCode(200); ResponseEntity result = template .postForEntity(SERVER + "/MultiErrorCodeService/errorCodeWithHeader", request, MultiResponse200.class); - TestMgr.check(result.getStatusCodeValue(), 200); + TestMgr.check(result.getStatusCode().value(), 200); TestMgr.check(result.getBody().getMessage(), "success result"); TestMgr.check(result.getBody().getCode(), 200); TestMgr.check(result.getHeaders().getFirst("x-code"), 200); @@ -197,7 +170,7 @@ private static void testErrorCodeWithHeaderJAXRS() { request.setMessage("success result"); ResponseEntity result = template .postForEntity(SERVER + "/MultiErrorCodeService/errorCodeWithHeaderJAXRS", request, MultiResponse200.class); - TestMgr.check(result.getStatusCodeValue(), 200); + TestMgr.check(result.getStatusCode().value(), 200); TestMgr.check(result.getBody().getMessage(), "success result"); TestMgr.check(result.getBody().getCode(), 200); TestMgr.check(result.getHeaders().getFirst("x-code"), 200); @@ -236,7 +209,7 @@ private static void testErrorCodeWithHeaderJAXRSUsingRowType() { ResponseEntity result = template .postForEntity(SERVER + "/MultiErrorCodeService/errorCodeWithHeaderJAXRS", requestJson, MultiResponse200.class); - TestMgr.check(result.getStatusCodeValue(), 200); + TestMgr.check(result.getStatusCode().value(), 200); TestMgr.check(result.getBody().getMessage(), "test message"); TestMgr.check(result.getBody().getCode(), 200); TestMgr.check(result.getHeaders().getFirst("x-code"), 200); @@ -249,7 +222,7 @@ private static void testErrorCodeWithHeaderJAXRSUsingRowType() { result = template .postForEntity(SERVER + "/MultiErrorCodeService/errorCodeWithHeaderJAXRS", new JsonObject(stringRequest), MultiResponse200.class); - TestMgr.check(result.getStatusCodeValue(), 200); + TestMgr.check(result.getStatusCode().value(), 200); TestMgr.check(result.getBody().getMessage(), "test message"); TestMgr.check(result.getBody().getCode(), 200); TestMgr.check(result.getHeaders().getFirst("x-code"), 200); @@ -263,7 +236,7 @@ private static void testNoClientErrorCode() { @SuppressWarnings("rawtypes") ResponseEntity listResult = template .postForEntity(SERVER + "/MultiErrorCodeService/noClientErrorCode", requestJson, List.class); - TestMgr.check(listResult.getStatusCodeValue(), 200); + TestMgr.check(listResult.getStatusCode().value(), 200); Map mapResult = RestObjectMapperFactory.getRestObjectMapper().convertValue(listResult.getBody().get(0), Map.class); TestMgr.check(mapResult.get("message"), "test message"); diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java index 486d1e8aaa4..7d8017eb38d 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestClientTimeout.java @@ -23,26 +23,20 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.validator.Student; -import org.apache.servicecomb.loadbalance.ServiceCombLoadBalancerStats; -import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.loadbalance.ServiceCombServerStats; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.cache.InstanceCache; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class TestClientTimeout implements CategorizedTestCase { - private static RestTemplate template = RestTemplateBuilder.create(); + private static RestOperations template = RestTemplateBuilder.create(); public void testAllTransport() throws Exception { testClientTimeOut(template); } - private static void testClientTimeOut(RestTemplate template) { + private static void testClientTimeOut(RestOperations template) { String microserviceName = "jaxrs"; String cseUrlPrefix = "cse://" + microserviceName + "/clientreqtimeout/"; @@ -51,7 +45,7 @@ private static void testClientTimeOut(RestTemplate template) { testClientTimeoutAdd(template, cseUrlPrefix); } - private static void testClientTimeoutSayHi(RestTemplate template, String cseUrlPrefix) { + private static void testClientTimeoutSayHi(RestOperations template, String cseUrlPrefix) { Student student = new Student(); student.setName("timeout"); student.setAge(30); @@ -59,7 +53,7 @@ private static void testClientTimeoutSayHi(RestTemplate template, String cseUrlP TestMgr.check("hello timeout 30", result); } - private static void testClientTimeoutAdd(RestTemplate template, String cseUrlPrefix) { + private static void testClientTimeoutAdd(RestOperations template, String cseUrlPrefix) { Map params = new HashMap<>(); params.put("a", "5"); params.put("b", "20"); @@ -77,24 +71,8 @@ private static void testClientTimeoutAdd(RestTemplate template, String cseUrlPre // Request Timeout or Invocation Timeout TestMgr.check(true, e.getErrorData().toString().contains("Timeout.")); - // TODO: 这个测试用例失败不会影响当前功能。 需要在完成 SCB-2213重试重构、实例统计状态基于事件重构(当前 - // 在LoadbalanceHandler进行实例统计信息更新,应该基于服务执行完成事件更新,重试也应该在调用层重试。) - // 等功能后,才能够启用这个测试用例检查。 - // TestMgr.check(serviceCombServerStats.getContinuousFailureCount(), failures + 1); } TestMgr.check(true, failed); } - - private static ServiceCombServerStats getServiceCombServerStats() { - InstanceCache instanceCache = DiscoveryManager.INSTANCE.getInstanceCacheManager() - .getOrCreate(RegistrationManager.INSTANCE.getAppId(), - "jaxrs", "0+"); - org.apache.servicecomb.registry.api.registry.MicroserviceInstance microserviceInstance = instanceCache - .getInstanceMap().values().iterator().next(); - ServiceCombServer serviceCombServer = ServiceCombLoadBalancerStats.INSTANCE - .getServiceCombServer(microserviceInstance); - return ServiceCombLoadBalancerStats.INSTANCE - .getServiceCombServerStats(serviceCombServer); - } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrs.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrs.java index 5c1e15a011d..4e6cbd97deb 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrs.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrs.java @@ -20,6 +20,7 @@ import java.io.File; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; import org.apache.servicecomb.demo.CategorizedTestCase; @@ -27,6 +28,7 @@ import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart; import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.type.TypeReference; @@ -47,6 +49,40 @@ interface DownloadInf { @Override public void testAllTransport() throws Exception { testCodeFirstJaxrs(); + testResponseLong(); + } + + @Override + public void testHighwayTransport() throws Exception { + // test only once + testInstanceIsolation(); + } + + private void testInstanceIsolation() { + AtomicInteger e503Business = new AtomicInteger(0); + AtomicInteger e503CircuitBreaker = new AtomicInteger(0); + + for (int i = 0; i < 30; i++) { + try { + InvokerUtils.syncInvoke(SERVICE_NAME, SCHEMA_ID, "instanceIsolationTest", null, + String.class); + } catch (InvocationException e) { + if (e.getStatusCode() == 503) { + if ("CommonExceptionData [message=business]".equals(e.getErrorData().toString())) { + e503Business.getAndIncrement(); + } else if ("CommonExceptionData [message=instance isolation circuitBreaker is open.]".equals( + e.getErrorData().toString())) { + e503CircuitBreaker.getAndIncrement(); + } else { + TestMgr.fail("not expected message"); + } + } else { + TestMgr.fail("not expected code"); + } + } + } + TestMgr.check(true, e503Business.get() >= 10); + TestMgr.check(true, e503CircuitBreaker.get() >= 10); } @Override @@ -62,6 +98,12 @@ private void testDeleteAfterFinished() throws Exception { TestMgr.check(file.exists(), false); } + private void testResponseLong() { + Object result = InvokerUtils.syncInvoke(SERVICE_NAME, SCHEMA_ID, "responseLong", null, + Object.class); + TestMgr.check(result, Long.MAX_VALUE); + } + // invoke CodeFirstJaxrs private void testCodeFirstJaxrs() { Map swaggerArguments = new HashMap<>(); diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrsReactive.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrsReactive.java new file mode 100644 index 00000000000..2fdaffe3edb --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestCodeFirstJaxrsReactive.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.jaxrs.client; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class TestCodeFirstJaxrsReactive implements CategorizedTestCase { + interface AddOperation { + CompletableFuture add(int a, int b); + } + + @RpcReference(microserviceName = "jaxrs", schemaId = "codeFirst") + AddOperation addOperation; + + @Override + public void testAllTransport() throws Exception { + final int count = 10; + CountDownLatch latch = new CountDownLatch(count); + AtomicInteger result = new AtomicInteger(0); + + for (int i = 0; i < count; i++) { + new Thread(() -> addOperation.add(1, 2) + .whenComplete((r, e) -> addOperation.add(r, r).whenComplete((r1, e1) -> { + result.addAndGet(r1); + latch.countDown(); + }))).start(); + } + + latch.await(3, TimeUnit.SECONDS); + TestMgr.check(count * 6, result.get()); + } +} diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFileUploadSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFileUploadSchema.java new file mode 100644 index 00000000000..049da2e47f9 --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFileUploadSchema.java @@ -0,0 +1,90 @@ +/* + * 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.demo.jaxrs.client; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.core.MediaType; + +@Component +public class TestFileUploadSchema implements CategorizedTestCase { + @Override + public void testRestTransport() throws Exception { + testUpload(RestTemplateBuilder.create(), "servicecomb://jaxrs/fileUpload"); + } + + private void testUpload(RestOperations template, String cseUrlPrefix) throws IOException { + String file1Content = "Hello World"; + File file1 = File.createTempFile("jaxrstest1", ".txt"); + FileUtils.writeStringToFile(file1, file1Content, StandardCharsets.UTF_8, false); + + testFileUpload(template, cseUrlPrefix, file1, file1Content); + testFileAndStringUpload(template, cseUrlPrefix, file1, file1Content); + } + + private void testFileUpload(RestOperations template, String cseUrlPrefix, File file1, String file1Content) + throws IOException { + String result1 = template.postForObject(cseUrlPrefix + "/upload1", new HttpEntity<>(new HashMap<>()), String.class); + TestMgr.check("null file", result1); + + Map map = new HashMap<>(); + map.put("file1", new FileSystemResource(file1)); + String file2Content = "Hello EveryOne"; + File file2 = File.createTempFile("测试2", ".txt"); + FileUtils.writeStringToFile(file2, file2Content, StandardCharsets.UTF_8, false); + map.put("file2", new FileSystemResource(file2)); + String expect = String.format("%s:%s:%s\n" + "%s:%s:%s", + file1.getName(), + MediaType.TEXT_PLAIN, + file1Content, + file2.getName(), + MediaType.TEXT_PLAIN, + file2Content); + String result2 = template.postForObject(cseUrlPrefix + "/upload1", new HttpEntity<>(map), String.class); + TestMgr.check(expect, result2); + } + + private void testFileAndStringUpload(RestOperations template, String cseUrlPrefix, File file1, String file1Content) { + Map map = new HashMap<>(); + String message = "hi"; + map.put("file1", new FileSystemResource(file1)); + map.put("message", message); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA); + String expect = String.format("%s:%s:%s:%s", + file1.getName(), + MediaType.TEXT_PLAIN, + file1Content, + message); + String result = template.postForObject(cseUrlPrefix + "/upload2", new HttpEntity<>(map, headers), String.class); + TestMgr.check(expect, result); + } +} diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFormRequestSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFormRequestSchema.java index c243c9d1a04..591302058de 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFormRequestSchema.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestFormRequestSchema.java @@ -29,7 +29,7 @@ import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component @@ -37,7 +37,7 @@ public class TestFormRequestSchema implements CategorizedTestCase { private static final Logger LOGGER = LoggerFactory.getLogger(TestFormRequestSchema.class); - private RestTemplate restTemplate = RestTemplateBuilder.create(); + private final RestOperations restTemplate = RestTemplateBuilder.create(); @Override public void testRestTransport() throws Exception { @@ -45,19 +45,16 @@ public void testRestTransport() throws Exception { // testFormRequestFail会关闭连接,防止下个测试用例失败,睡眠2s Thread.sleep(2000); testFormRequestSuccess(); + testFormRequestBufferSize(); } // formSize is less than default maxFormAttributeSize , success - private void testFormRequestSuccess() throws Exception { + private void testFormRequestSuccess() { try { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap formData = new LinkedMultiValueMap<>(); - StringBuffer stringBuffer = new StringBuffer(); - for (int i = 0; i < 512; i++) { - stringBuffer.append("a"); - } - formData.add("formData", stringBuffer.toString()); + formData.add("formData", "a".repeat(512)); HttpEntity> requestEntity = new HttpEntity<>(formData, headers); ResponseEntity responseEntity = restTemplate .postForEntity("cse://jaxrs/form/formRequest", requestEntity, String.class); @@ -69,21 +66,39 @@ private void testFormRequestSuccess() throws Exception { } // formSize is greater than default maxFormAttributeSize , throw exception - private void testFormRequestFail() throws Exception { + private void testFormRequestFail() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); MultiValueMap formData = new LinkedMultiValueMap<>(); - StringBuffer stringBuffer = new StringBuffer(); - for (int i = 0; i < 1688; i++) { - stringBuffer.append("a"); - } - formData.add("formData", String.valueOf(stringBuffer)); + formData.add("formData", "a".repeat(1688)); HttpEntity> requestEntity = new HttpEntity<>(formData, headers); try { restTemplate.postForEntity("cse://jaxrs/form/formRequest", requestEntity, String.class); TestMgr.fail("Size exceed allowed maximum capacity"); } catch (Throwable e) { - TestMgr.check(e.getMessage().contains("Size exceed allowed maximum capacity"), true); + TestMgr.check(e.getMessage().contains("Internal Server Error"), true); + } + } + + private void testFormRequestBufferSize() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap formData = new LinkedMultiValueMap<>(); + // we can not test a situation for form exceed max buffer size, because the netty buffer is very + // big and the trunc can always be decoded and cached buffer size is always 0. + formData.add("F0123456789001234567890012345678900123456789001234567890" + + "0123456789001234567890012345678900123456789001234567890", "a".repeat(1020) + // we can not test a situation for form exceed max buffer size, because the netty buffer is very + // big and the trunc can always be decoded and cached buffer size is always 0. + ); + HttpEntity> requestEntity = new HttpEntity<>(formData, headers); + try { + ResponseEntity responseEntity = + restTemplate.postForEntity("cse://jaxrs/form/formLongName", requestEntity, String.class); + TestMgr.check(responseEntity.getBody(), "formRequest success : 1020"); + } catch (Throwable e) { + LOGGER.error("testFormRequestBufferSize-->", e); + TestMgr.failed("", e); } } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamSchema.java new file mode 100644 index 00000000000..8c0933172a6 --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamSchema.java @@ -0,0 +1,54 @@ +/* + * 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.demo.jaxrs.client; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +@Component +public class TestQueryParamSchema implements CategorizedTestCase { + public interface QueryParamService { + String testQueryEncode(String param); + } + + private final RestOperations restTemplate = RestTemplateBuilder.create(); + + @RpcReference(microserviceName = "jaxrs", schemaId = "QueryParamSchema") + private QueryParamService queryParamService; + + @Override + public void testAllTransport() throws Exception { + testQueryParamEncodingPlus(); + } + + private void testQueryParamEncodingPlus() { + // should encode + + TestMgr.check("a+b", + restTemplate.getForObject("servicecomb://jaxrs/queryParam/testQueryEncode?param={1}", String.class, "a+b")); + // if not encoded, + should be blank + TestMgr.check("a b", + restTemplate.getForObject("servicecomb://jaxrs/queryParam/testQueryEncode?param=a+b", String.class)); + + // rpc should encode + TestMgr.check("a+b", queryParamService.testQueryEncode("a+b")); + } +} diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamWithListSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamWithListSchema.java index 40c9b8d0ebf..19aa1c66ee8 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamWithListSchema.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestQueryParamWithListSchema.java @@ -21,18 +21,17 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class TestQueryParamWithListSchema implements CategorizedTestCase { - private RestTemplate restTemplate = RestTemplateBuilder.create(); + private RestOperations restTemplate = RestTemplateBuilder.create(); @Override public void testAllTransport() throws Exception { testMulti(); testCSV(); testSSV(); - testTSV(); testPipes(); } @@ -41,7 +40,6 @@ public void testRestTransport() throws Exception { testMultiRest(); testCSVRest(); testSSVRest(); - testTSVRest(); testPipesRest(); } @@ -51,7 +49,6 @@ public void testHighwayTransport() throws Exception { testMultiHighway(); testCSVHighway(); testSSVHighway(); - testTSVHighway(); testPipesHighway(); } @@ -66,32 +63,19 @@ private void testCSVRest() { } private void testSSV() { - TestMgr.check("2:[1, 2]", + TestMgr.check("1:[1%202]", restTemplate.getForObject("cse://jaxrs/queryList/queryListSSV?queryList=1%202", String.class)); - TestMgr.check("2:[, ]", + TestMgr.check("1:[%20]", restTemplate.getForObject("cse://jaxrs/queryList/queryListSSV?queryList=%20", String.class)); TestMgr.check("1:[]", restTemplate.getForObject("cse://jaxrs/queryList/queryListSSV?queryList=", String.class)); - } - - private void testTSVHighway() { - TestMgr.check("null", - restTemplate.getForObject("cse://jaxrs/queryList/queryListTSV?", String.class)); - } - private void testTSVRest() { - TestMgr.check("0:[]", - restTemplate.getForObject("cse://jaxrs/queryList/queryListTSV?", String.class)); - } - - private void testTSV() { TestMgr.check("2:[1, 2]", - restTemplate - .getForObject("cse://jaxrs/queryList/queryListTSV?queryList={1}", String.class, "1\t2")); + restTemplate.getForObject("cse://jaxrs/queryList/queryListSSV?queryList={1}", String.class, "1 2")); TestMgr.check("2:[, ]", - restTemplate.getForObject("cse://jaxrs/queryList/queryListTSV?queryList={1}", String.class, "\t")); + restTemplate.getForObject("cse://jaxrs/queryList/queryListSSV?queryList={1}", String.class, " ")); TestMgr.check("1:[]", - restTemplate.getForObject("cse://jaxrs/queryList/queryListTSV?queryList=", String.class)); + restTemplate.getForObject("cse://jaxrs/queryList/queryListSSV?queryList=", String.class)); } private void testPipesHighway() { diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestReactiveSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestReactiveSchema.java index 68d6ca250d4..6126c053ad3 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestReactiveSchema.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestReactiveSchema.java @@ -17,22 +17,28 @@ package org.apache.servicecomb.demo.jaxrs.client; +import java.util.Map; + import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class TestReactiveSchema implements CategorizedTestCase { + @SuppressWarnings("rawtypes") public void testRestTransport() throws Exception { - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); try { - restTemplate.getForObject("cse://jaxrs/reactive/add?a=1&b=2", int.class); + restTemplate.getForObject("cse://jaxrs/reactive/testSyncInvokeInEventLoop?a=1&b=2", int.class); TestMgr.check(true, false); } catch (InvocationException e) { - TestMgr.check(e.getStatusCode(), 490); + TestMgr.check(e.getStatusCode(), 500); + TestMgr.check(((Map) e.getErrorData()).get("message"), + "Unexpected exception when processing jaxrs.ReactiveSchema.testSyncInvokeInEventLoop. " + + "Can not execute sync logic in event loop."); } } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.java index 869f2009334..dd53006df29 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/TestSchemeInterfaceJaxrs.java @@ -23,6 +23,8 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; @@ -52,12 +54,11 @@ public void testAllTransport() throws Exception { try { jaxrs.reduce(1, 3); TestMgr.failed("should throw exception", new Exception()); - } catch (Exception e) { + } catch (InvocationException e) { TestMgr.check( "Consumer method org.apache.servicecomb.demo.jaxrs.client.SchemeInterfaceJaxrs:reduce " - + "not exist in contract, microserviceName=jaxrs, schemaId=SchemeInterfaceJaxrs; " - + "new producer not running or not deployed.", - e.getMessage()); + + "not exist in contract, microserviceName=jaxrs, schemaId=SchemeInterfaceJaxrs.", + ((CommonExceptionData) e.getError()).getMessage()); } } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java index 9e09bc14d88..5f34487335a 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamPojoClient.java @@ -19,6 +19,7 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; @@ -58,9 +59,9 @@ private void testBeanParam() { } private void testUpload() { - BufferedInputStream bufferedInputStream0 = new BufferedInputStream(new ByteArrayInputStream("up0".getBytes())); - BufferedInputStream bufferedInputStream1 = new BufferedInputStream(new ByteArrayInputStream("up1".getBytes())); - BufferedInputStream bufferedInputStream2 = new BufferedInputStream(new ByteArrayInputStream("up2".getBytes())); + BufferedInputStream bufferedInputStream0 = new BufferedInputStream(new ByteArrayInputStream("up0".getBytes(StandardCharsets.UTF_8))); + BufferedInputStream bufferedInputStream1 = new BufferedInputStream(new ByteArrayInputStream("up1".getBytes(StandardCharsets.UTF_8))); + BufferedInputStream bufferedInputStream2 = new BufferedInputStream(new ByteArrayInputStream("up2".getBytes(StandardCharsets.UTF_8))); String result = beanParamTestServiceIntf.beanParameterTestUpload( bufferedInputStream0, "queryTest", bufferedInputStream1, bufferedInputStream2, "ex"); diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java index 69c50576441..decb4a4207f 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/beanParam/BeanParamRestTemplateClient.java @@ -19,6 +19,7 @@ import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -32,11 +33,11 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class BeanParamRestTemplateClient implements CategorizedTestCase { - RestTemplate restTemplate; + RestOperations restTemplate; public BeanParamRestTemplateClient() { restTemplate = RestTemplateBuilder.create(); @@ -76,9 +77,12 @@ private void testBeanParam() { } private void testUpload() { - BufferedInputStream bufferedInputStream0 = new BufferedInputStream(new ByteArrayInputStream("up0".getBytes())); - BufferedInputStream bufferedInputStream1 = new BufferedInputStream(new ByteArrayInputStream("up1".getBytes())); - BufferedInputStream bufferedInputStream2 = new BufferedInputStream(new ByteArrayInputStream("up2".getBytes())); + BufferedInputStream bufferedInputStream0 = new BufferedInputStream( + new ByteArrayInputStream("up0".getBytes(StandardCharsets.UTF_8))); + BufferedInputStream bufferedInputStream1 = new BufferedInputStream( + new ByteArrayInputStream("up1".getBytes(StandardCharsets.UTF_8))); + BufferedInputStream bufferedInputStream2 = new BufferedInputStream( + new ByteArrayInputStream("up2".getBytes(StandardCharsets.UTF_8))); HashMap formData = new HashMap<>(); formData.put("up0", bufferedInputStream0); diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/injectBean/TestInjectBeanSchema.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/injectBean/TestInjectBeanSchema.java index 175701c233d..02d1ee1d97e 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/injectBean/TestInjectBeanSchema.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/injectBean/TestInjectBeanSchema.java @@ -21,11 +21,11 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class TestInjectBeanSchema implements CategorizedTestCase { - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); @Override public void testAllTransport() throws Exception { diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/pojoDefault/DefaultModelServiceClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/pojoDefault/DefaultModelServiceClient.java index 99744957e67..a221853b6a8 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/pojoDefault/DefaultModelServiceClient.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/pojoDefault/DefaultModelServiceClient.java @@ -17,20 +17,20 @@ package org.apache.servicecomb.demo.jaxrs.client.pojoDefault; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.jaxrs.server.pojoDefault.DefaultResponseModel; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; public class DefaultModelServiceClient { - private static RestTemplate template = RestTemplateBuilder.create(); + private static RestOperations template = RestTemplateBuilder.create(); private static String urlPrefix = "cse://jaxrs/DefaultModelService"; public static void run() { // highway do not support this feature - ArchaiusUtils.setProperty("servicecomb.references.transport.jaxrs", "rest"); + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport.jaxrs", "rest"); testDefaultModelService(); } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/validation/ValidationServiceClient.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/validation/ValidationServiceClient.java index 9616b483f5e..4b99fff0359 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/validation/ValidationServiceClient.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/client/validation/ValidationServiceClient.java @@ -19,23 +19,25 @@ import java.util.ArrayList; -import javax.ws.rs.core.Response.Status; - +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.jaxrs.server.validation.ValidationModel; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.demo.validator.Teacher; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.core.Response.Status; public class ValidationServiceClient { - private static RestTemplate template = RestTemplateBuilder.create(); + private static RestOperations template = RestTemplateBuilder.create(); private static String urlPrefix = "cse://jaxrs/ValidationService"; public static void run() { // highway do not support this feature - ArchaiusUtils.setProperty("servicecomb.references.transport.jaxrs", "rest"); + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport.jaxrs", "rest"); testValidation(); } @@ -70,6 +72,15 @@ private static void testValidation() { TestMgr.check(e.getErrorData().toString().contains("propertyPath=errorCode.request.members"), true); } + try { + template.postForObject(urlPrefix + "/validate", null, ValidationModel.class); + TestMgr.check(false, true); + } catch (InvocationException e) { + TestMgr.check(400, e.getStatus().getStatusCode()); + TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); + TestMgr.check(e.getErrorData().toString().contains("propertyPath=errorCode.request"), true); + } + String strResult = template.getForObject(urlPrefix + "/validateQuery?name=a", String.class); TestMgr.check(strResult, "a"); @@ -79,7 +90,27 @@ private static void testValidation() { } catch (InvocationException e) { TestMgr.check(400, e.getStatus().getStatusCode()); TestMgr.check(Status.BAD_REQUEST, e.getReasonPhrase()); - TestMgr.check(e.getErrorData().toString().contains("Parameter is not valid for operation"), true); + TestMgr.check(((CommonExceptionData) e.getErrorData()).getMessage().contains("Parameter is not valid"), true); + } + + Teacher teacher = new Teacher(); + teacher.setName("teacher"); + teacher.setAge("20"); + Teacher response = template.postForObject(urlPrefix + "/sayTeacherInfo", teacher, Teacher.class); + TestMgr.check(response.getName(), "teacher"); + + try { + teacher = new Teacher(); + teacher.setAge("20"); + template.postForObject(urlPrefix + "/sayTeacherInfo", teacher, Teacher.class); + TestMgr.fail("Name should not empty"); + } catch (InvocationException e) { + TestMgr.check(400, e.getStatus().getStatusCode()); + TestMgr.check(e.getErrorData().toString().contains("must not be blank"), true); } + + // jax-rs body default required = false + response = template.postForObject(urlPrefix + "/sayTeacherInfo", null, Teacher.class); + TestMgr.check(null, response); } } diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java index 6c4350a07f4..ea5c2072ff5 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java +++ b/demo/demo-jaxrs/jaxrs-client/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java @@ -17,9 +17,9 @@ package org.apache.servicecomb.demo.jaxrs.server.pojoDefault; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.Null; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Null; public class DefaultResponseModel { @Min(20) diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/resources/log4j2.xml b/demo/demo-jaxrs/jaxrs-client/src/main/resources/log4j2.xml index 6e6586771bb..c51f7ad5036 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/resources/log4j2.xml +++ b/demo/demo-jaxrs/jaxrs-client/src/main/resources/log4j2.xml @@ -38,4 +38,4 @@ - \ No newline at end of file + diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml b/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml index 54b9929c6cd..07493f07ef8 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml +++ b/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml @@ -20,17 +20,26 @@ servicecomb: application: jaxrstest name: jaxrsClient version: 0.0.1 - registry: + registry: + sc: address: http://127.0.0.1:30100 - handler: - chain: - Consumer: - default: bizkeeper-consumer,loadbalance - loadbalance: - strategy: - name: mycustomrule - retryEnabled: true - retryHandler: mycustomhandler + enableSwaggerRegistration: true + + matchGroup: + instanceIsolationTest: | + matches: + - apiPath: + prefix: "/codeFirstJaxrs/instanceIsolationTest" + instanceIsolation: + instanceIsolationTest: | + minimumNumberOfCalls: 10 + slidingWindowSize: 20 + slidingWindowType: COUNT_BASED + failureRateThreshold: 50 + slowCallRateThreshold: 100 + slowCallDurationThreshold: 3000 + waitDurationInOpenState: 200 + permittedNumberOfCallsInHalfOpenState: 10 request: timeout: 30000 @@ -48,6 +57,16 @@ servicecomb: check: enabled: false + # use service center to find schema info + openAPI: + registry: + # enable service center OpenAPI registry, and need set enableSwaggerRegistration: true + registry: + enabled: true + # disable instance OpenAPI registry + instance: + enabled: false + # test configurations. you can choose any implementation. default using local. # using nacos configuration @@ -72,4 +91,4 @@ jaxrstest: low-2.a.high-1.b: 3 low-2.a.high-2.b: 4 -# test configurations. \ No newline at end of file +# test configurations. diff --git a/demo/demo-jaxrs/jaxrs-client/src/test/java/org/apache/servicecomb/demo/jaxrs/JaxrsIT.java b/demo/demo-jaxrs/jaxrs-client/src/test/java/org/apache/servicecomb/demo/jaxrs/JaxrsIT.java index df4d1ab0e70..c1bb351ba5d 100644 --- a/demo/demo-jaxrs/jaxrs-client/src/test/java/org/apache/servicecomb/demo/jaxrs/JaxrsIT.java +++ b/demo/demo-jaxrs/jaxrs-client/src/test/java/org/apache/servicecomb/demo/jaxrs/JaxrsIT.java @@ -17,25 +17,27 @@ package org.apache.servicecomb.demo.jaxrs; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.jaxrs.client.JaxrsClient; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = JaxrsClient.class) public class JaxrsIT { - @Before + @BeforeEach public void setUp() { TestMgr.errors().clear(); } @Test public void clientGetsNoError() throws Exception { - JaxrsClient.main(new String[0]); + JaxrsClient.run(); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-jaxrs/jaxrs-server/pom.xml b/demo/demo-jaxrs/jaxrs-server/pom.xml index 1c24a0cb13a..cc80ad1521c 100644 --- a/demo/demo-jaxrs/jaxrs-server/pom.xml +++ b/demo/demo-jaxrs/jaxrs-server/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb.demo demo-jaxrs - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT jaxrs-server Java Chassis::Demo::JAXRS::Server @@ -32,45 +32,28 @@ org.apache.servicecomb.demo demo-schema - - org.apache.servicecomb - provider-jaxrs - - - org.apache.servicecomb - provider-springmvc - org.glassfish.jersey.core jersey-client + + org.glassfish.jersey.core + jersey-common + org.apache.servicecomb swagger-invocation-validator - org.apache.servicecomb.demo.jaxrs.server.JaxrsServer + org.apache.servicecomb.demo.jaxrs.JaxrsServer - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -78,15 +61,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/JaxrsServer.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/JaxrsServer.java new file mode 100644 index 00000000000..4cd136d0fbc --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/JaxrsServer.java @@ -0,0 +1,35 @@ +/* + * 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.demo.jaxrs; + +import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; +import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper; +import org.apache.servicecomb.demo.RestObjectMapperWithStringMapperNotWriteNull; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class JaxrsServer { + public static void main(String[] args) throws Exception { + new SpringApplicationBuilder(JaxrsServer.class).web(WebApplicationType.NONE).run(args); + + RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper()); + RestObjectMapperFactory.setConsumerWriterMapper(new RestObjectMapperWithStringMapperNotWriteNull()); + } +} diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java index 849243767f7..8626f86087a 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/CodeFirstJaxrs.java @@ -19,67 +19,66 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.Part; -import javax.ws.rs.Consumes; -import javax.ws.rs.CookieParam; -import javax.ws.rs.DELETE; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; - import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.demo.compute.Person; import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore; import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore; -import org.apache.servicecomb.demo.jaxbbean.JAXBPerson; import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.foundation.common.part.FilePart; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody; -import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; - -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ResponseHeader; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.vertx.core.json.JsonObject; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.CookieParam; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response.Status; @RestSchema(schemaId = "codeFirst") @Path("/codeFirstJaxrs") @Produces(MediaType.APPLICATION_JSON) public class CodeFirstJaxrs { - @ApiResponse(code = 200, response = User.class, message = "") - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = User.class)), description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @Path("/cseResponse") @GET public Response cseResponse(InvocationContext c1) { Response response = Response.createSuccess(Status.ACCEPTED, new User()); - response.setHeader("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE)); + response.setHeader("h1", "h1v " + c1.getContext().get(CoreConst.SRC_MICROSERVICE)); InvocationContext c2 = ContextUtils.getInvocationContext(); - response.setHeader("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE)); + response.setHeader("h2", "h2v " + c2.getContext().get(CoreConst.SRC_MICROSERVICE)); return response; } @@ -97,14 +96,6 @@ public String textPlain(String body) { return body; } - @Path("/appXml") - @POST - @Consumes(MediaType.APPLICATION_JSON) - @Produces(MediaType.APPLICATION_XML) - public JAXBPerson appXml(JAXBPerson body) { - return body; - } - @Path("/bytes") @POST public byte[] bytes(byte[] input) { @@ -131,7 +122,7 @@ public int add(@FormParam("a") int a, @FormParam("b") int b) { @Path("/reduce") @GET - @ApiImplicitParams({@ApiImplicitParam(name = "a", dataType = "integer", format = "int32", paramType = "query")}) + @Parameters({@Parameter(name = "a", schema = @Schema(implementation = int.class), in = ParameterIn.QUERY)}) public int reduce(HttpServletRequest request, @CookieParam("b") int b) { int a = Integer.parseInt(request.getParameter("a")); return a - b; @@ -150,7 +141,8 @@ public Person sayHello(Person user) { public String testRawJsonString(String jsonInput) { Map person; try { - person = RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), Map.class); + person = RestObjectMapperFactory.getRestObjectMapper() + .readValue(jsonInput.getBytes(StandardCharsets.UTF_8), Map.class); } catch (Exception e) { e.printStackTrace(); return null; @@ -187,11 +179,11 @@ public boolean isTrue() { @DELETE @Produces(MediaType.TEXT_PLAIN) public String addString(@QueryParam("s") List s) { - String result = ""; + StringBuilder result = new StringBuilder(); for (String x : s) { - result += x; + result.append(x); } - return result; + return result.toString(); } @Path("/ignore") @@ -209,7 +201,8 @@ public OutputModelForTestIgnore testModelWithIgnoreField(InputModelForTestIgnore public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) { Map person; try { - person = RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), Map.class); + person = RestObjectMapperFactory.getRestObjectMapper() + .readValue(jsonInput.getBytes(StandardCharsets.UTF_8), Map.class); } catch (Exception e) { e.printStackTrace(); return null; @@ -220,41 +213,14 @@ public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) { @Path("/traceId") @GET public String getTraceId() { - return ContextUtils.getInvocationContext().getContext(Const.TRACE_ID_NAME); + return ContextUtils.getInvocationContext().getContext(CoreConst.TRACE_ID_NAME); } - @Path("/upload1") - @POST - @Produces(MediaType.TEXT_PLAIN) - public String fileUpload1(@FormParam("file1") Part file1, @FormParam("file2") Part file2) throws IOException { - if (file1 == null || file2 == null) { - return "null file"; - } - try (InputStream is1 = file1.getInputStream(); InputStream is2 = file2.getInputStream()) { - String content1 = IOUtils.toString(is1, StandardCharsets.UTF_8); - String content2 = IOUtils.toString(is2, StandardCharsets.UTF_8); - return String.format("%s:%s:%s\n" + "%s:%s:%s", - file1.getSubmittedFileName(), - file1.getContentType(), - content1, - file2.getSubmittedFileName(), - file2.getContentType(), - content2); - } - } - - @Path("/upload2") - @POST - @Produces(MediaType.TEXT_PLAIN) - public String fileUpload2(@FormParam("file1") Part file1, @FormParam("message") String message) throws IOException { - try (InputStream is1 = file1.getInputStream()) { - String content1 = IOUtils.toString(is1, StandardCharsets.UTF_8); - return String.format("%s:%s:%s:%s", - file1.getSubmittedFileName(), - file1.getContentType(), - content1, - message); - } + @GET + @Path("/responseLong") + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Object.class)), description = "") + public Response responseLong() { + return Response.createSuccess(Long.MAX_VALUE); } @Path("/download/testDeleteAfterFinished") @@ -268,6 +234,12 @@ public Part testDeleteAfterFinished(@QueryParam("name") String name, @QueryParam .setSubmittedFileName(name); } + @Path("/instanceIsolationTest") + @GET + public String instanceIsolationTest() { + throw new InvocationException(503, "", "business"); + } + private File createTempFile(String name, String content) throws IOException { File systemTempFile = new File(System.getProperty("java.io.tmpdir")); File file = new File(systemTempFile, name); diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java index 9797901b0f1..e5735de44fe 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ComputeImpl.java @@ -17,22 +17,9 @@ package org.apache.servicecomb.demo.jaxrs.server; +import java.nio.charset.StandardCharsets; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.DELETE; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.demo.compute.Person; import org.apache.servicecomb.provider.rest.common.RestSchema; @@ -40,6 +27,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.DELETE; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Context; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "compute") @Path("/compute") @Produces(MediaType.APPLICATION_JSON) @@ -54,6 +59,8 @@ public int add(@FormParam("a") int a, @FormParam("b") int b) { @Path("/reduce") @GET + @Parameters(value = {@Parameter(in = ParameterIn.QUERY, name = "a", schema = @Schema(implementation = int.class)), + @Parameter(in = ParameterIn.QUERY, name = "b", schema = @Schema(implementation = int.class))}) public int reduce(@Context HttpServletRequest request) { int a = Integer.parseInt(request.getParameter("a")); int b = Integer.parseInt(request.getParameter("b")); @@ -73,7 +80,8 @@ public Person sayHello(Person user) { public String testRawJsonString(String jsonInput) { Map person; try { - person = RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), Map.class); + person = RestObjectMapperFactory.getRestObjectMapper() + .readValue(jsonInput.getBytes(StandardCharsets.UTF_8), Map.class); } catch (Exception e) { e.printStackTrace(); return null; @@ -116,10 +124,10 @@ public boolean isTrue() { @DELETE @Produces(MediaType.TEXT_PLAIN) public String addString(@QueryParam("s") String[] s) { - String result = ""; + StringBuilder result = new StringBuilder(); for (String x : s) { - result += x; + result.append(x); } - return result; + return result.toString(); } } diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FileUploadSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FileUploadSchema.java new file mode 100644 index 00000000000..dfaac37fa2d --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FileUploadSchema.java @@ -0,0 +1,74 @@ +/* + * 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.demo.jaxrs.server; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.apache.servicecomb.provider.rest.common.RestSchema; + +import jakarta.servlet.http.Part; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +/** + * Test and illustrate JaxRS uploads. + * + * Use @FormParam to annotate a multipart/form-data item. + */ +@RestSchema(schemaId = "FileUploadSchema") +@Path("/fileUpload") +public class FileUploadSchema { + @Path("/upload1") + @POST + @Produces(MediaType.TEXT_PLAIN) + public String fileUpload1(@FormParam("file1") Part file1, @FormParam("file2") Part file2) throws IOException { + if (file1 == null || file2 == null) { + return "null file"; + } + try (InputStream is1 = file1.getInputStream(); InputStream is2 = file2.getInputStream()) { + String content1 = IOUtils.toString(is1, StandardCharsets.UTF_8); + String content2 = IOUtils.toString(is2, StandardCharsets.UTF_8); + return String.format("%s:%s:%s\n" + "%s:%s:%s", + file1.getSubmittedFileName(), + file1.getContentType(), + content1, + file2.getSubmittedFileName(), + file2.getContentType(), + content2); + } + } + + @Path("/upload2") + @POST + @Produces(MediaType.TEXT_PLAIN) + public String fileUpload2(@FormParam("file1") Part file1, @FormParam("message") String message) throws IOException { + try (InputStream is1 = file1.getInputStream()) { + String content1 = IOUtils.toString(is1, StandardCharsets.UTF_8); + return String.format("%s:%s:%s:%s", + file1.getSubmittedFileName(), + file1.getContentType(), + content1, + message); + } + } +} diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FormRequestSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FormRequestSchema.java index 7ceaf74be04..2670681217a 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FormRequestSchema.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/FormRequestSchema.java @@ -17,15 +17,15 @@ package org.apache.servicecomb.demo.jaxrs.server; -import javax.ws.rs.Consumes; -import javax.ws.rs.FormParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.provider.rest.common.RestSchema; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "FormRequestSchema") @Path("/form") @Produces(MediaType.APPLICATION_JSON) @@ -38,4 +38,11 @@ public String formRequestSuccess(@FormParam("formData") String formData) throws return "formRequest success : " + formData.length(); } + @Path("/formLongName") + @POST + @Consumes(MediaType.APPLICATION_FORM_URLENCODED) + public String formLongName(@FormParam("F0123456789001234567890012345678900123456789001234567890" + + "0123456789001234567890012345678900123456789001234567890") String formData) throws Exception { + return "formRequest success : " + formData.length(); + } } diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxRSDefaultValues.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxRSDefaultValues.java index 5a2788e648b..17769d3c291 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxRSDefaultValues.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxRSDefaultValues.java @@ -16,21 +16,21 @@ */ package org.apache.servicecomb.demo.jaxrs.server; -import javax.servlet.http.HttpServletRequest; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.provider.rest.common.RestSchema; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java deleted file mode 100644 index 02584744559..00000000000 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsDemoHttpServerFilter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.demo.jaxrs.server; - -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class JaxrsDemoHttpServerFilter implements HttpServerFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(JaxrsDemoHttpServerFilter.class); - - @Override - public int getOrder() { - return 0; - } - - @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { - return null; - } - - @Override - public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) { - // in 404 situation, invocation is null and a NPE is thrown - LOGGER.info("JaxrsDemoHttpServerFilter is called, operation=[{}]", invocation.getOperationName()); - } -} diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java deleted file mode 100644 index 87b19bd73ee..00000000000 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/JaxrsServer.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.demo.jaxrs.server; - -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapperNotWriteNull; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; - -public class JaxrsServer { - public static void main(String[] args) throws Exception { - RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper()); - RestObjectMapperFactory.setConsumerWriterMapper(new RestObjectMapperWithStringMapperNotWriteNull()); - - BeanUtils.init(); - } -} diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamSchema.java new file mode 100644 index 00000000000..80985d68541 --- /dev/null +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamSchema.java @@ -0,0 +1,34 @@ +/* + * 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.demo.jaxrs.server; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; + +import org.apache.servicecomb.provider.rest.common.RestSchema; + +@RestSchema(schemaId = "QueryParamSchema") +@Path("/queryParam") +public class QueryParamSchema { + @Path("testQueryEncode") + @GET + public String testQueryEncode(@QueryParam("param") String param) { + return param; + } +} diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamWithListSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamWithListSchema.java index c1fcfd9081c..d15849423ac 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamWithListSchema.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/QueryParamWithListSchema.java @@ -19,44 +19,48 @@ import java.util.List; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.QueryParam; - import org.apache.servicecomb.provider.rest.common.RestSchema; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.Explode; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.ParameterStyle; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; @RestSchema(schemaId = "QueryParamWithListSchema") @Path("/queryList") public class QueryParamWithListSchema { @Path("queryListCSV") @GET - public String queryListCSV(@ApiParam(collectionFormat = "csv") @QueryParam("queryList") List queryList) { - return queryList == null ? "null" : queryList.size() + ":" + queryList.toString(); + public String queryListCSV( + @Parameter(name = "queryList", in = ParameterIn.QUERY, style = ParameterStyle.FORM, explode = Explode.FALSE) + @QueryParam("queryList") List queryList) { + return queryList == null ? "null" : queryList.size() + ":" + queryList; } @Path("queryListSSV") @GET - public String queryListSSV(@ApiParam(collectionFormat = "ssv") @QueryParam("queryList") List queryList) { - return queryList == null ? "null" : queryList.size() + ":" + queryList.toString(); - } - - @Path("queryListTSV") - @GET - public String queryListTSV(@ApiParam(collectionFormat = "tsv") @QueryParam("queryList") List queryList) { - return queryList == null ? "null" : queryList.size() + ":" + queryList.toString(); + public String queryListSSV( + @Parameter(name = "queryList", in = ParameterIn.QUERY, style = ParameterStyle.SPACEDELIMITED, explode = Explode.FALSE) + @QueryParam("queryList") List queryList) { + return queryList == null ? "null" : queryList.size() + ":" + queryList; } @Path("queryListPIPES") @GET - public String queryListPIPES(@ApiParam(collectionFormat = "pipes") @QueryParam("queryList") List queryList) { - return queryList == null ? "null" : queryList.size() + ":" + queryList.toString(); + public String queryListPIPES( + @Parameter(name = "queryList", in = ParameterIn.QUERY, style = ParameterStyle.PIPEDELIMITED, explode = Explode.FALSE) + @QueryParam("queryList") List queryList) { + return queryList == null ? "null" : queryList.size() + ":" + queryList; } @Path("queryListMULTI") @GET - public String queryListMULTI(@ApiParam(collectionFormat = "multi") @QueryParam("queryList") List queryList) { - return queryList == null ? "null" : queryList.size() + ":" + queryList.toString(); + public String queryListMULTI( + @Parameter(name = "queryList", in = ParameterIn.QUERY, style = ParameterStyle.FORM, explode = Explode.TRUE) + @QueryParam("queryList") List queryList) { + return queryList == null ? "null" : queryList.size() + ":" + queryList; } } diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ReactiveSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ReactiveSchema.java index 284c1b6a8db..2143d27a04c 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ReactiveSchema.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/ReactiveSchema.java @@ -17,24 +17,25 @@ package org.apache.servicecomb.demo.jaxrs.server; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; @RestSchema(schemaId = "ReactiveSchema") @Path("/reactive") @Produces(MediaType.APPLICATION_JSON) public class ReactiveSchema { - @Path("/add") + // reactive is configured to run in event-loop thread pool + @Path("/testSyncInvokeInEventLoop") @GET - public int add(@QueryParam("a") int a, @QueryParam("b") int b) { - RestTemplate client = RestTemplateBuilder.create(); + public int testSyncInvokeInEventLoop(@QueryParam("a") int a, @QueryParam("b") int b) { + RestOperations client = RestTemplateBuilder.create(); return client.getForObject("cse://jaxrs/compute/reduce?a=1&b=2", int.class); } } diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/RequestClientTimeOut.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/RequestClientTimeOut.java index 387165123d6..2f17c2fc6f8 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/RequestClientTimeOut.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/RequestClientTimeOut.java @@ -17,11 +17,11 @@ package org.apache.servicecomb.demo.jaxrs.server; -import javax.ws.rs.FormParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.demo.validator.Student; import org.apache.servicecomb.provider.rest.common.RestSchema; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java index 8546d2c25eb..c9c9b311535 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrs.java @@ -17,11 +17,11 @@ package org.apache.servicecomb.demo.jaxrs.server; -import javax.validation.constraints.Min; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.RequestParam; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java index 862db168d76..a551644834e 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/SchemeInterfaceJaxrsImpl.java @@ -32,7 +32,7 @@ public int reduce(int a, int b) { } public int add(String a, String b) { - return Integer.valueOf(a) + Integer.valueOf(b); + return Integer.parseInt(a) + Integer.parseInt(b); } @Override diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java index 9f5bef60ae6..a5c5f9b8332 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/Validator.java @@ -17,15 +17,15 @@ package org.apache.servicecomb.demo.jaxrs.server; -import javax.validation.Valid; -import javax.validation.constraints.Min; -import javax.ws.rs.FormParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.demo.validator.Student; import org.apache.servicecomb.provider.rest.common.RestSchema; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java index 1e2a040bc62..8f037cff595 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/BeanParamTestService.java @@ -20,15 +20,15 @@ import java.io.IOException; import java.util.Scanner; -import javax.servlet.http.Part; -import javax.ws.rs.BeanParam; -import javax.ws.rs.Consumes; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.Consumes; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java index 489b29c567d..3ccff412a5e 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameter.java @@ -17,11 +17,11 @@ package org.apache.servicecomb.demo.jaxrs.server.beanParam; -import javax.ws.rs.CookieParam; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; +import jakarta.ws.rs.CookieParam; +import jakarta.ws.rs.DefaultValue; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.PathParam; +import jakarta.ws.rs.QueryParam; import com.fasterxml.jackson.annotation.JsonIgnore; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java index 80530aba63d..b6e3685ef47 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/beanParam/TestBeanParameterWithUpload.java @@ -17,9 +17,9 @@ package org.apache.servicecomb.demo.jaxrs.server.beanParam; -import javax.servlet.http.Part; -import javax.ws.rs.FormParam; -import javax.ws.rs.QueryParam; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.FormParam; +import jakarta.ws.rs.QueryParam; public class TestBeanParameterWithUpload { @QueryParam("query") diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanSchema.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanSchema.java index 14f2ee4c701..59395b02687 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanSchema.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanSchema.java @@ -19,8 +19,8 @@ import java.util.List; -import javax.ws.rs.GET; -import javax.ws.rs.Path; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.provider.rest.common.RestSchema; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanVertxHttpDispatcher.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanVertxHttpDispatcher.java index cda0e1f5b74..347ba9473ab 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanVertxHttpDispatcher.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/injectBean/InjectBeanVertxHttpDispatcher.java @@ -23,9 +23,13 @@ import io.vertx.ext.web.Router; public class InjectBeanVertxHttpDispatcher implements VertxHttpDispatcher { - @Autowired private InjectBean injectBean; + @Autowired + public void setInjectBean(InjectBean injectBean) { + this.injectBean = injectBean; + } + @Override public void init(Router router) { diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java index 7f76e6ac645..9a5c6be64b0 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/multiErrorCode/MultiErrorCodeService.java @@ -20,22 +20,22 @@ import java.util.ArrayList; import java.util.List; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.core.Response.Status; - import org.apache.servicecomb.demo.multiErrorCode.MultiRequest; import org.apache.servicecomb.demo.multiErrorCode.MultiResponse200; import org.apache.servicecomb.demo.multiErrorCode.MultiResponse400; import org.apache.servicecomb.demo.multiErrorCode.MultiResponse500; import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.ResponseHeader; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.core.Response.Status; @RestSchema(schemaId = "MultiErrorCodeService") @Path("MultiErrorCodeService") @@ -43,20 +43,20 @@ public class MultiErrorCodeService { @Path("/errorCode") @POST @ApiResponses({ - @ApiResponse(code = 200, response = MultiResponse200.class, message = ""), - @ApiResponse(code = 400, response = MultiResponse400.class, message = ""), - @ApiResponse(code = 500, response = MultiResponse500.class, message = "")}) + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = MultiResponse200.class)), description = ""), + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(implementation = MultiResponse400.class)), description = ""), + @ApiResponse(responseCode = "500", content = @Content(schema = @Schema(implementation = MultiResponse500.class)), description = "")}) public MultiResponse200 errorCode(MultiRequest request) { if (request.getCode() == 400) { MultiResponse400 r = new MultiResponse400(); r.setCode(400); r.setMessage("bad request"); - throw new InvocationException(javax.ws.rs.core.Response.Status.BAD_REQUEST, r); + throw new InvocationException(jakarta.ws.rs.core.Response.Status.BAD_REQUEST, r); } else if (request.getCode() == 500) { MultiResponse500 r = new MultiResponse500(); r.setCode(500); r.setMessage("internal error"); - throw new InvocationException(javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR, r); + throw new InvocationException(jakarta.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR, r); } else { MultiResponse200 r = new MultiResponse200(); r.setCode(200); @@ -68,10 +68,15 @@ public MultiResponse200 errorCode(MultiRequest request) { @Path("/errorCodeWithHeader") @POST @ApiResponses({ - @ApiResponse(code = 200, response = MultiResponse200.class, message = ""), - @ApiResponse(code = 400, response = MultiResponse400.class, message = ""), - @ApiResponse(code = 500, response = MultiResponse500.class, message = "")}) - @ResponseHeaders({@ResponseHeader(name = "x-code", response = String.class)}) + @ApiResponse(responseCode = "200", headers = { + @Header(name = "x-code", schema = @Schema(implementation = String.class))}, + content = @Content(schema = @Schema(implementation = MultiResponse200.class)), description = ""), + @ApiResponse(responseCode = "400", headers = { + @Header(name = "x-code", schema = @Schema(implementation = String.class))}, + content = @Content(schema = @Schema(implementation = MultiResponse400.class)), description = ""), + @ApiResponse(responseCode = "500", headers = { + @Header(name = "x-code", schema = @Schema(implementation = String.class))}, + content = @Content(schema = @Schema(implementation = MultiResponse500.class)), description = "")}) public Response errorCodeWithHeader(MultiRequest request) { Response response = new Response(); if (request.getCode() == 400) { @@ -106,19 +111,24 @@ public Response errorCodeWithHeader(MultiRequest request) { @Path("/errorCodeWithHeaderJAXRS") @POST @ApiResponses({ - @ApiResponse(code = 200, response = MultiResponse200.class, message = ""), - @ApiResponse(code = 400, response = MultiResponse400.class, message = ""), - @ApiResponse(code = 500, response = MultiResponse500.class, message = "")}) - @ResponseHeaders({@ResponseHeader(name = "x-code", response = String.class)}) - public javax.ws.rs.core.Response errorCodeWithHeaderJAXRS(MultiRequest request) { - javax.ws.rs.core.Response response; + @ApiResponse(responseCode = "200", headers = { + @Header(name = "x-code", schema = @Schema(implementation = String.class))}, + content = @Content(schema = @Schema(implementation = MultiResponse200.class)), description = ""), + @ApiResponse(responseCode = "400", headers = { + @Header(name = "x-code", schema = @Schema(implementation = String.class))}, + content = @Content(schema = @Schema(implementation = MultiResponse400.class)), description = ""), + @ApiResponse(responseCode = "500", headers = { + @Header(name = "x-code", schema = @Schema(implementation = String.class))}, + content = @Content(schema = @Schema(implementation = MultiResponse500.class)), description = "")}) + public jakarta.ws.rs.core.Response errorCodeWithHeaderJAXRS(MultiRequest request) { + jakarta.ws.rs.core.Response response; if (request.getCode() == 400) { MultiResponse400 r = new MultiResponse400(); r.setCode(request.getCode()); r.setMessage(request.getMessage()); // If got many types for different status code, we can only using InvocationException for failed error code like 400-500. // The result for Failed Family(e.g. 400-500), can not set return value as target type directly or will give exception. - response = javax.ws.rs.core.Response.status(Status.BAD_REQUEST) + response = jakarta.ws.rs.core.Response.status(Status.BAD_REQUEST) .entity(new InvocationException(Status.BAD_REQUEST, r)) .header("x-code", "400") .build(); @@ -126,7 +136,7 @@ public javax.ws.rs.core.Response errorCodeWithHeaderJAXRS(MultiRequest request) MultiResponse500 r = new MultiResponse500(); r.setCode(request.getCode()); r.setMessage(request.getMessage()); - response = javax.ws.rs.core.Response.status(Status.INTERNAL_SERVER_ERROR) + response = jakarta.ws.rs.core.Response.status(Status.INTERNAL_SERVER_ERROR) .entity(new InvocationException(Status.INTERNAL_SERVER_ERROR, r)) .header("x-code", "500") .build(); @@ -135,7 +145,7 @@ public javax.ws.rs.core.Response errorCodeWithHeaderJAXRS(MultiRequest request) r.setCode(request.getCode()); r.setMessage(request.getMessage()); // If error code is OK family(like 200), we can use the target type. - response = javax.ws.rs.core.Response.status(Status.OK) + response = jakarta.ws.rs.core.Response.status(Status.OK) .entity(r) .header("x-code", "200") .build(); @@ -146,7 +156,7 @@ public javax.ws.rs.core.Response errorCodeWithHeaderJAXRS(MultiRequest request) @Path("/noClientErrorCode") @POST @ApiResponses({ - @ApiResponse(code = 400, response = NoClientErrorCode400.class, message = "")}) + @ApiResponse(responseCode = "400", content = @Content(schema = @Schema(implementation = NoClientErrorCode400.class)), description = "")}) public List noClientErrorCode(MultiRequest request) { if (request.getCode() == 400) { NoClientErrorCode400 r = new NoClientErrorCode400(); diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultModelService.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultModelService.java index 7296a0970e1..36020868cbd 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultModelService.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultModelService.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.demo.jaxrs.server.pojoDefault; -import javax.ws.rs.POST; -import javax.ws.rs.Path; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; import org.apache.servicecomb.provider.rest.common.RestSchema; diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultRequestModel.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultRequestModel.java index 0cc535703df..b8053ca8086 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultRequestModel.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultRequestModel.java @@ -17,9 +17,9 @@ package org.apache.servicecomb.demo.jaxrs.server.pojoDefault; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.Null; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Null; public class DefaultRequestModel { @Min(20) diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java index bf4288a2869..9c505699866 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/pojoDefault/DefaultResponseModel.java @@ -17,9 +17,9 @@ package org.apache.servicecomb.demo.jaxrs.server.pojoDefault; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.validation.constraints.Null; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.Null; public class DefaultResponseModel { @Min(20) diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationService.java b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationService.java index abb8a0161ed..7b18a4f7322 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationService.java +++ b/demo/demo-jaxrs/jaxrs-server/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationService.java @@ -17,13 +17,15 @@ package org.apache.servicecomb.demo.jaxrs.server.validation; -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.QueryParam; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; +import org.apache.servicecomb.demo.validator.Teacher; import org.apache.servicecomb.provider.rest.common.RestSchema; @RestSchema(schemaId = "ValidationService") @@ -31,7 +33,7 @@ public class ValidationService { @Path("/validate") @POST - public ValidationModel errorCode(@Valid ValidationModel request) { + public ValidationModel errorCode(@NotNull @Valid ValidationModel request) { return request; } @@ -40,4 +42,10 @@ public ValidationModel errorCode(@Valid ValidationModel request) { public String queryValidate(@NotEmpty @QueryParam("name") String name) { return name; } + + @Path("/sayTeacherInfo") + @POST + public Teacher sayTeacherInfo(@Valid Teacher teacher) { + return teacher; + } } diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter deleted file mode 100644 index 5e737d86d70..00000000000 --- a/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.demo.jaxrs.server.JaxrsDemoHttpServerFilter \ No newline at end of file diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher index afff0839503..a3a19c72aa3 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher +++ b/demo/demo-jaxrs/jaxrs-server/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.demo.jaxrs.server.injectBean.InjectBeanVertxHttpDispatcher \ No newline at end of file +org.apache.servicecomb.demo.jaxrs.server.injectBean.InjectBeanVertxHttpDispatcher diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/resources/log4j2.xml b/demo/demo-jaxrs/jaxrs-server/src/main/resources/log4j2.xml index 6e6586771bb..c51f7ad5036 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/resources/log4j2.xml +++ b/demo/demo-jaxrs/jaxrs-server/src/main/resources/log4j2.xml @@ -38,4 +38,4 @@ - \ No newline at end of file + diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml b/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml index f4f585ecc05..475708a55b1 100644 --- a/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml +++ b/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml @@ -20,18 +20,17 @@ servicecomb: application: jaxrstest name: jaxrs version: 0.0.2 - registry: + registry: + sc: address: http://127.0.0.1:30100 + enableSwaggerRegistration: true rest: address: 0.0.0.0:8080 server: - maxFormAttributeSize: 1024 + maxFormAttributeSize: 1024 # for testing, and bigger than netty buffer allocator + maxFormBufferedBytes: 100 highway: address: 0.0.0.0:7070 - handler: - chain: - Provider: - default: bizkeeper-provider uploads: directory: target @@ -43,4 +42,14 @@ servicecomb: invocation: timeout: check: - enabled: false \ No newline at end of file + enabled: false + + # use service center to find schema info + openAPI: + registry: + # enable service center OpenAPI registry, and need set enableSwaggerRegistration: true + registry: + enabled: true + # disable instance OpenAPI registry + instance: + enabled: false diff --git a/demo/demo-jaxrs/pom.xml b/demo/demo-jaxrs/pom.xml index fab996a8096..014baac0318 100644 --- a/demo/demo-jaxrs/pom.xml +++ b/demo/demo-jaxrs/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-jaxrs Java Chassis::Demo::JAXRS @@ -32,10 +32,18 @@ jaxrs-client + + org.apache.servicecomb + solution-basic + org.apache.servicecomb registry-service-center + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + org.apache.servicecomb swagger-generator-spring-data @@ -48,5 +56,13 @@ org.apache.logging.log4j log4j-slf4j-impl + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + diff --git a/demo/demo-local-registry/README.md b/demo/demo-local-registry/README.md index 7ace9bd1d27..a585a17b7ce 100644 --- a/demo/demo-local-registry/README.md +++ b/demo/demo-local-registry/README.md @@ -1,6 +1,5 @@ This demo is an integration test for testing local registration an discovery. -Local registration and discovery is a mechanism that do not using Service Center, -`Microservice` and `MicroserviceInstance` are constructed from configuration file. - +Local registration and discovery is a mechanism that do not using Service Center, +`Microservice` and `MicroserviceInstance` are constructed from configuration file. diff --git a/demo/demo-local-registry/demo-local-registry-client/pom.xml b/demo/demo-local-registry/demo-local-registry-client/pom.xml index 331789b204f..352e0cf26aa 100644 --- a/demo/demo-local-registry/demo-local-registry-client/pom.xml +++ b/demo/demo-local-registry/demo-local-registry-client/pom.xml @@ -25,39 +25,18 @@ org.apache.servicecomb.demo demo-local-registry - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT - org.apache.servicecomb.demo.localRegistryClient.Application + org.apache.servicecomb.demo.localRegistryClient.LocalRegistryClientApplication - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - org.apache.servicecomb.demo demo-schema - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config-local - ${project.version} - - - - - - @@ -66,6 +45,55 @@ demo-local-registry-server + + + + io.fabric8 + docker-maven-plugin + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + /maven/maven/${demo.service.name}-${project.version}.jar + + + ServiceComb is ready + + + 8080 + + + + + + 8080:8080 + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/Application.java b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/Application.java deleted file mode 100644 index c6ed407b0b0..00000000000 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/Application.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.demo.localRegistryClient; - -import org.apache.servicecomb.demo.CategorizedTestCaseRunner; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class Application { - public static void main(final String[] args) throws Exception { - new SpringApplicationBuilder().sources(Application.class).web(WebApplicationType.SERVLET).build().run(args); - - registerSchema(); - - runTest(); - - TestMgr.summary(); - if (!TestMgr.errors().isEmpty()) { - throw new IllegalStateException("tests failed"); - } - } - - private static void registerSchema() { - RegistrationManager.INSTANCE.getSwaggerLoader().registerSwagger("demo-local-registry", - "demo-local-registry-server", - "CodeFirstEndpoint", CodeFirstService.class); - RegistrationManager.INSTANCE.getSwaggerLoader().registerSwagger("demo-local-registry", - "demo-local-registry-server-bean", - "CodeFirstEndpoint", CodeFirstService.class); - } - - private static void runTest() throws Exception { - CategorizedTestCaseRunner.runCategorizedTestCase("demo-local-registry-server"); - } -} diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/CodeFirstService.java b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/CodeFirstService.java index cbe329eb9d2..05973bd18de 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/CodeFirstService.java +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/CodeFirstService.java @@ -17,10 +17,10 @@ package org.apache.servicecomb.demo.localRegistryClient; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.QueryParam; @Path("/register/url/codeFirst") @Produces("application/json") diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryClientApplication.java b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryClientApplication.java new file mode 100644 index 00000000000..76f1f2d570f --- /dev/null +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryClientApplication.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.localRegistryClient; + +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class LocalRegistryClientApplication { + public static void main(final String[] args) throws Exception { + new SpringApplicationBuilder().sources(LocalRegistryClientApplication.class) + .web(WebApplicationType.SERVLET).build() + .run(args); + + registerSchema(); + + runTest(); + + TestMgr.summary(); + if (!TestMgr.errors().isEmpty()) { + throw new IllegalStateException("tests failed"); + } + } + + private static void registerSchema() { + SCBEngine.getInstance().getOpenAPIRegistryManager().registerOpenAPI("demo-local-registry", + "demo-local-registry-server", + "CodeFirstEndpoint", CodeFirstService.class); + SCBEngine.getInstance().getOpenAPIRegistryManager().registerOpenAPI("demo-local-registry", + "demo-local-registry-server-bean", + "CodeFirstEndpoint", CodeFirstService.class); + } + + private static void runTest() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("demo-local-registry-server"); + } +} diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryServerTest.java b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryServerTest.java index 71886be659d..06a24601e03 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryServerTest.java +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryServerTest.java @@ -24,22 +24,42 @@ import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.Microservice; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class LocalRegistryServerTest implements CategorizedTestCase { + // demo-local-registry-server-bean use yaml to register service, and register schema by + // local file loading @RpcReference(microserviceName = "demo-local-registry-server", schemaId = "CodeFirstEndpoint") private CodeFirstService codeFirstService; + @RpcReference(microserviceName = "demo-local-registry-server", schemaId = "ServerEndpoint") + private ServerService serverService; + + // demo-local-registry-server-bean use bean to register service, and register schema part by + // local file loading, part by bean class @RpcReference(microserviceName = "demo-local-registry-server-bean", schemaId = "CodeFirstEndpoint") private CodeFirstService codeFirstServiceBean; + @RpcReference(microserviceName = "demo-local-registry-server-bean", schemaId = "ServerEndpoint") + private ServerService serverServiceBean; + + // demo-local-registry-server-bean2 use bean to register service and schema @RpcReference(microserviceName = "demo-local-registry-server-bean2", schemaId = "CodeFirstEndpoint2") private CodeFirstService codeFirstServiceBean2; - RestTemplate template = RestTemplateBuilder.create(); + @RpcReference(microserviceName = "demo-local-registry-server-bean2", schemaId = "ServerEndpoint") + private ServerService serverServiceBean2; + + private DiscoveryManager discoveryManager; + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } @Override public void testRestTransport() throws Exception { @@ -49,17 +69,18 @@ public void testRestTransport() throws Exception { } private void testGetAllMicroservice() { - List microserviceList = DiscoveryManager.INSTANCE.getAllMicroservices(); - int expectedCount = 0; - - for (Microservice m : microserviceList) { - if (m.getServiceName().equals("demo-local-registry-client") - || m.getServiceName().equals("demo-local-registry-server") - || m.getServiceName().equals("demo-local-registry-server-bean")) { - expectedCount++; - } - } - TestMgr.check(3, expectedCount); + List microserviceList = discoveryManager + .findServiceInstances("demo-local-registry", "demo-local-registry-client"); + TestMgr.check(1, microserviceList.size()); + microserviceList = discoveryManager + .findServiceInstances("demo-local-registry", "demo-local-registry-server"); + TestMgr.check(1, microserviceList.size()); + microserviceList = discoveryManager + .findServiceInstances("demo-local-registry", "demo-local-registry-server-bean"); + TestMgr.check(1, microserviceList.size()); + microserviceList = discoveryManager + .findServiceInstances("demo-local-registry", "demo-local-registry-server-bean2"); + TestMgr.check(1, microserviceList.size()); } private void testCodeFirstGetName() { @@ -69,12 +90,18 @@ private void testCodeFirstGetName() { } private void testServerGetName() { - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); TestMgr.check("2", template .getForObject("cse://demo-local-registry-server/register/url/prefix/getName?name=2", String.class)); TestMgr.check("2", template .getForObject("cse://demo-local-registry-server-bean/register/url/prefix/getName?name=2", String.class)); + TestMgr.check("2", template + .getForObject("cse://demo-local-registry-server-bean2/register/url/prefix/getName?name=2", + String.class)); + TestMgr.check("2", serverService.getName("2")); + TestMgr.check("2", serverServiceBean.getName("2")); + TestMgr.check("2", serverServiceBean2.getName("2")); } } diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/RegistryBeansConfiguration.java b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/RegistryBeansConfiguration.java index 029d1425745..28c5d3a1f25 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/RegistryBeansConfiguration.java +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/RegistryBeansConfiguration.java @@ -27,6 +27,7 @@ import org.springframework.context.annotation.Configuration; @Configuration +@SuppressWarnings("unused") public class RegistryBeansConfiguration { @Bean public RegistryBean demoLocalRegistryServerBean() { @@ -41,7 +42,7 @@ public RegistryBean demoLocalRegistryServerBean() { .setVersion("0.0.3") .setAppId("demo-local-registry") .addSchemaId("ServerEndpoint") - .addSchemaId("CodeFirstEndpoint") + .addSchemaInterface("CodeFirstEndpoint", CodeFirstService.class) .setInstances(new Instances().setInstances(instances)); } @@ -57,6 +58,7 @@ public RegistryBean demoLocalRegistryServerBean2() { .setId("003") .setVersion("0.0.3") .setAppId("demo-local-registry") + .addSchemaId("ServerEndpoint") .addSchemaInterface("CodeFirstEndpoint2", CodeFirstService.class) .setInstances(new Instances().setInstances(instances)); } diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/ServerService.java b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/ServerService.java new file mode 100644 index 00000000000..f8211fd9a36 --- /dev/null +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/java/org/apache/servicecomb/demo/localRegistryClient/ServerService.java @@ -0,0 +1,21 @@ +/* + * 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.demo.localRegistryClient; + +public interface ServerService { + String getName(String name); +} diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/application.yml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/application.yml index 9dd3836e99c..fcf4bb18309 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/application.yml +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/application.yml @@ -18,14 +18,8 @@ server: port: 8082 -# java-chassis configurations - -APPLICATION_ID: demo-local-registry -service_description: - name: demo-local-registry-client - version: 0.0.1 servicecomb: - handler: - chain: - Consumer: - default: loadbalance \ No newline at end of file + service: + application: demo-local-registry + name: demo-local-registry-client + version: 0.0.1 diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/log4j2.xml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/logback.xml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean/ServerEndpoint.yaml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean/ServerEndpoint.yaml index 78c9d1bca63..2adeb24781c 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean/ServerEndpoint.yaml +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean/ServerEndpoint.yaml @@ -15,29 +15,28 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -swagger: "2.0" +openapi: 3.0.1 info: - version: "1.0.0" - title: "swagger definition for org.apache.servicecomb.demo.registry.ServerEndpoint" - x-java-interface: "gen.swagger.ServerEndpointIntf" -basePath: "/register/url/prefix" -schemes: -- "http" -consumes: -- "application/json" -produces: -- "application/json" + title: swagger definition for org.apache.servicecomb.demo.localRegistryServer.ServerEndpoint + version: 1.0.0 +servers: +- url: /register/url/prefix paths: /getName: get: - operationId: "getName" + operationId: getName parameters: - - name: "name" - in: "query" + - name: name + in: query required: true - type: "string" + schema: + type: string responses: "200": - description: "response of 200" - schema: - type: "string" \ No newline at end of file + description: response of 200 + content: + application/json: + schema: + type: string +components: + schemas: {} diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean2/ServerEndpoint.yaml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean2/ServerEndpoint.yaml new file mode 100644 index 00000000000..2adeb24781c --- /dev/null +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server-bean2/ServerEndpoint.yaml @@ -0,0 +1,42 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.localRegistryServer.ServerEndpoint + version: 1.0.0 +servers: +- url: /register/url/prefix +paths: + /getName: + get: + operationId: getName + parameters: + - name: name + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string +components: + schemas: {} diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server/ServerEndpoint.yaml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server/ServerEndpoint.yaml index 78c9d1bca63..2adeb24781c 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server/ServerEndpoint.yaml +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/microservices/demo-local-registry-server/ServerEndpoint.yaml @@ -15,29 +15,28 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -swagger: "2.0" +openapi: 3.0.1 info: - version: "1.0.0" - title: "swagger definition for org.apache.servicecomb.demo.registry.ServerEndpoint" - x-java-interface: "gen.swagger.ServerEndpointIntf" -basePath: "/register/url/prefix" -schemes: -- "http" -consumes: -- "application/json" -produces: -- "application/json" + title: swagger definition for org.apache.servicecomb.demo.localRegistryServer.ServerEndpoint + version: 1.0.0 +servers: +- url: /register/url/prefix paths: /getName: get: - operationId: "getName" + operationId: getName parameters: - - name: "name" - in: "query" + - name: name + in: query required: true - type: "string" + schema: + type: string responses: "200": - description: "response of 200" - schema: - type: "string" \ No newline at end of file + description: response of 200 + content: + application/json: + schema: + type: string +components: + schemas: {} diff --git a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/registry.yaml b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/registry.yaml index 2ad3c23269f..cb5a3bcd4d9 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/main/resources/registry.yaml +++ b/demo/demo-local-registry/demo-local-registry-client/src/main/resources/registry.yaml @@ -24,4 +24,4 @@ demo-local-registry-server: - CodeFirstEndpoint instances: - endpoints: - - rest://localhost:8080 \ No newline at end of file + - rest://localhost:8080 diff --git a/demo/demo-local-registry/demo-local-registry-client/src/test/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryIT.java b/demo/demo-local-registry/demo-local-registry-client/src/test/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryIT.java index d8faa9da5d5..f8f12fd9cfa 100644 --- a/demo/demo-local-registry/demo-local-registry-client/src/test/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryIT.java +++ b/demo/demo-local-registry/demo-local-registry-client/src/test/java/org/apache/servicecomb/demo/localRegistryClient/LocalRegistryIT.java @@ -17,24 +17,21 @@ package org.apache.servicecomb.demo.localRegistryClient; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.localRegistryClient.Application; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class LocalRegistryIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @Test public void clientGetsNoError() throws Exception { - Application.main(new String[0]); + LocalRegistryClientApplication.main(new String[0]); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-local-registry/demo-local-registry-server/pom.xml b/demo/demo-local-registry/demo-local-registry-server/pom.xml index 4c6c9e32d1f..8832ac2dc8a 100644 --- a/demo/demo-local-registry/demo-local-registry-server/pom.xml +++ b/demo/demo-local-registry/demo-local-registry-server/pom.xml @@ -25,20 +25,16 @@ org.apache.servicecomb.demo demo-local-registry - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT - org.apache.servicecomb.demo.localRegistryServer.ServerApplication + org.apache.servicecomb.demo.localRegistryServer.LocalRegistryServerApplication - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet + jakarta.ws.rs + jakarta.ws.rs-api org.apache.servicecomb.demo @@ -52,19 +48,6 @@ org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -72,15 +55,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/CodeFirstEndpoint.java b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/CodeFirstEndpoint.java index 781eed61c81..06fdf6b7939 100644 --- a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/CodeFirstEndpoint.java +++ b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/CodeFirstEndpoint.java @@ -17,26 +17,21 @@ package org.apache.servicecomb.demo.localRegistryServer; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "CodeFirstEndpoint") @RequestMapping(path = "/register/url/codeFirst", produces = MediaType.APPLICATION_JSON) public class CodeFirstEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(CodeFirstEndpoint.class); - @GetMapping(path = "/getName") public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); return name; } } diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/LocalRegistryServerApplication.java b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/LocalRegistryServerApplication.java new file mode 100644 index 00000000000..e574177a982 --- /dev/null +++ b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/LocalRegistryServerApplication.java @@ -0,0 +1,43 @@ +/* + * 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.demo.localRegistryServer; + +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class LocalRegistryServerApplication { + public static void main(final String[] args) throws Exception { + new SpringApplicationBuilder().sources(LocalRegistryServerApplication.class).web(WebApplicationType.SERVLET).build() + .run(args); + + SelfServiceInvoker invoker = BeanUtils.getBean("SelfServiceInvoker"); + invoker.latch.await(10, TimeUnit.SECONDS); + TestMgr.check(invoker.result, "hello"); + + TestMgr.summary(); + if (!TestMgr.errors().isEmpty()) { + System.exit(1); + } + } +} diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerApplication.java b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerApplication.java deleted file mode 100644 index 525e5624479..00000000000 --- a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerApplication.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.demo.localRegistryServer; - -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class ServerApplication { - public static void main(final String[] args) throws Exception { - new SpringApplicationBuilder().sources(ServerApplication.class).web(WebApplicationType.SERVLET).build().run(args); - - SelfServiceInvoker invoker = BeanUtils.getBean("SelfServiceInvoker"); - invoker.latch.await(10, TimeUnit.SECONDS); - TestMgr.check(invoker.result, "hello"); - - TestMgr.summary(); - if (!TestMgr.errors().isEmpty()) { - System.exit(1); - } - } -} diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerEndpoint.java b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerEndpoint.java index 41a9cd532ff..2db9d87dd05 100644 --- a/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerEndpoint.java +++ b/demo/demo-local-registry/demo-local-registry-server/src/main/java/org/apache/servicecomb/demo/localRegistryServer/ServerEndpoint.java @@ -17,26 +17,21 @@ package org.apache.servicecomb.demo.localRegistryServer; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "ServerEndpoint") @RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) public class ServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ServerEndpoint.class); - @GetMapping(path = "/getName") public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); return name; } } diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/resources/application.yml b/demo/demo-local-registry/demo-local-registry-server/src/main/resources/application.yml index 08015ff93c8..1478383598e 100644 --- a/demo/demo-local-registry/demo-local-registry-server/src/main/resources/application.yml +++ b/demo/demo-local-registry/demo-local-registry-server/src/main/resources/application.yml @@ -19,11 +19,10 @@ server: port: 8080 # java-chassis configurations - -APPLICATION_ID: demo-local-registry -service_description: - name: demo-local-registry-server - version: 0.0.1 servicecomb: + service: + application: demo-local-registry + name: demo-local-registry-server + version: 0.0.1 rest: - address: 0.0.0.0:8080 \ No newline at end of file + address: 0.0.0.0:8080 diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/resources/log4j2.xml b/demo/demo-local-registry/demo-local-registry-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-local-registry/demo-local-registry-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-local-registry/demo-local-registry-server/src/main/resources/logback.xml b/demo/demo-local-registry/demo-local-registry-server/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-local-registry/demo-local-registry-server/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-local-registry/pom.xml b/demo/demo-local-registry/pom.xml index b24a0074a69..c33eebf22e7 100644 --- a/demo/demo-local-registry/pom.xml +++ b/demo/demo-local-registry/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-local-registry Java Chassis::Demo::Local Registry @@ -33,6 +33,10 @@ + + org.apache.servicecomb + solution-basic + org.apache.servicecomb java-chassis-spring-boot-starter-servlet @@ -46,5 +50,17 @@ foundation-test-scaffolding compile + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + diff --git a/demo/demo-multi-registries/README.md b/demo/demo-multi-registries/README.md new file mode 100644 index 00000000000..762bd27eba3 --- /dev/null +++ b/demo/demo-multi-registries/README.md @@ -0,0 +1,4 @@ +# About + +* This demo enables both local-registry and sc-registry. +* This demo using local-registry to call service center api. diff --git a/demo/demo-multi-registries/demo-multi-registries-client/pom.xml b/demo/demo-multi-registries/demo-multi-registries-client/pom.xml index bd83eb28b9a..3577950317f 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/pom.xml +++ b/demo/demo-multi-registries/demo-multi-registries-client/pom.xml @@ -25,39 +25,18 @@ org.apache.servicecomb.demo demo-multi-registries - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT - org.apache.servicecomb.demo.registry.Application + org.apache.servicecomb.demo.registry.MultiRegistriesClientApplication - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - org.apache.servicecomb.demo demo-schema - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - @@ -66,6 +45,83 @@ demo-multi-registries-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/Application.java b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/Application.java deleted file mode 100644 index ffe37565ff1..00000000000 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/Application.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.demo.registry; - -import org.apache.servicecomb.demo.CategorizedTestCaseRunner; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.stereotype.Component; - -@SpringBootApplication -@EnableServiceComb -@Component -public class Application { - - public static void main(final String[] args) throws Exception { - new SpringApplicationBuilder().sources(Application.class).web(WebApplicationType.SERVLET).build().run(args); - - runTest(); - } - - public static void runTest() throws Exception { - CategorizedTestCaseRunner.runCategorizedTestCase("demo-multi-registries-server"); - - TestMgr.summary(); - if (!TestMgr.errors().isEmpty()) { - throw new IllegalStateException("tests failed"); - } - } -} diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/IServerEndpoint.java b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/IServerEndpoint.java index 4d38e9ef8fe..b4ac30465d0 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/IServerEndpoint.java +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/IServerEndpoint.java @@ -18,5 +18,5 @@ package org.apache.servicecomb.demo.registry; public interface IServerEndpoint { - public String getName(String name); + String getName(String name); } diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesClientApplication.java b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesClientApplication.java new file mode 100644 index 00000000000..87efbff570a --- /dev/null +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesClientApplication.java @@ -0,0 +1,46 @@ +/* + * 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.demo.registry; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.stereotype.Component; + +@SpringBootApplication +@Component +public class MultiRegistriesClientApplication { + + public static void main(final String[] args) throws Exception { + new SpringApplicationBuilder().sources(MultiRegistriesClientApplication.class) + .web(WebApplicationType.SERVLET).build().run(args); + + runTest(); + } + + public static void runTest() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("demo-multi-registries-server"); + + TestMgr.summary(); + if (!TestMgr.errors().isEmpty()) { + throw new IllegalStateException("tests failed"); + } + } +} diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerTestCase.java b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerTestCase.java index 3ca2ef174d9..abbd66a3d1b 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerTestCase.java +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerTestCase.java @@ -17,21 +17,27 @@ package org.apache.servicecomb.demo.registry; -import java.util.HashSet; import java.util.List; -import java.util.Set; import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.Microservice; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class MultiRegistriesServerTestCase implements CategorizedTestCase { - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); + + private DiscoveryManager discoveryManager; + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } @Override public void testRestTransport() throws Exception { @@ -40,18 +46,18 @@ public void testRestTransport() throws Exception { } private void testGetAllMicroservice() { - List microserviceList = DiscoveryManager.INSTANCE.getAllMicroservices(); - Set names = new HashSet<>(); - - for (Microservice m : microserviceList) { - if (m.getServiceName().equals("demo-multi-registries-client") - || m.getServiceName().equals("demo-multi-registries-server") - || m.getServiceName().equals("thirdParty-service-center") - || m.getServiceName().equals("thirdParty-no-schema-server")) { - names.add(m.getServiceName()); - } - } - TestMgr.check(4, names.size()); + List microserviceList = discoveryManager + .findServiceInstances("demo-multi-registries", "demo-multi-registries-client"); + TestMgr.check(2, microserviceList.size()); // both local and sc has one. + microserviceList = discoveryManager + .findServiceInstances("demo-multi-registries", "demo-multi-registries-server"); + TestMgr.check(1, microserviceList.size()); + microserviceList = discoveryManager + .findServiceInstances("demo-multi-registries", "thirdParty-service-center"); + TestMgr.check(1, microserviceList.size()); + microserviceList = discoveryManager + .findServiceInstances("demo-multi-registries", "thirdParty-no-schema-server"); + TestMgr.check(1, microserviceList.size()); } private void testServerGetName() { diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/SchemaDiscoveryTestCase.java b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/SchemaDiscoveryTestCase.java index 3ed4c1a60e1..0bf58aa7c3f 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/SchemaDiscoveryTestCase.java +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/SchemaDiscoveryTestCase.java @@ -18,19 +18,18 @@ package org.apache.servicecomb.demo.registry; import org.apache.servicecomb.demo.CategorizedTestCase; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.provider.pojo.RpcReference; import org.springframework.stereotype.Component; @Component public class SchemaDiscoveryTestCase implements CategorizedTestCase { - @RpcReference(microserviceName = "thirdParty-no-schema-server", schemaId = "ServerEndpoint") - IServerEndpoint serverEndpoint; + // Do not support this feature any more since 3.0.0 +// @RpcReference(microserviceName = "thirdParty-no-schema-server", schemaId = "ServerEndpoint") +// IServerEndpoint serverEndpoint; @Override public void testRestTransport() throws Exception { // invoke thirdParty-no-schema-server(mocked by demo-multi-registries-server) - TestMgr.check("hello", serverEndpoint.getName("hello")); + // TestMgr.check("hello", serverEndpoint.getName("hello")); } @Override diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/ServiceCenterEndpoint.java b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/ServiceCenterEndpoint.java index ceba6f4309c..491732f92bc 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/ServiceCenterEndpoint.java +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/java/org/apache/servicecomb/demo/registry/ServiceCenterEndpoint.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.demo.registry; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.springframework.web.bind.annotation.GetMapping; diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/application.yml b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/application.yml index 257e90bbcb3..e440ff6c897 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/application.yml +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/application.yml @@ -18,17 +18,18 @@ server: port: 8082 -# java-chassis configurations - -APPLICATION_ID: demo-multi-registries -service_description: - name: demo-multi-registries-client - version: 0.0.1 servicecomb: service: - registry: + application: demo-multi-registries + name: demo-multi-registries-client + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 - handler: - chain: - Consumer: - default: loadbalance \ No newline at end of file + demo-multi-registries: + thirdParty-service-center: + enabled: false + local: + demo-multi-registries: + demo-multi-registries-server: + enabled: false diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/log4j2.xml b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/logback.xml b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/microservices/thirdParty-service-center/ServiceCenterEndpoint.yaml b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/microservices/thirdParty-service-center/ServiceCenterEndpoint.yaml index 8ba87fadd56..88332e3259a 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/microservices/thirdParty-service-center/ServiceCenterEndpoint.yaml +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/microservices/thirdParty-service-center/ServiceCenterEndpoint.yaml @@ -3,57 +3,60 @@ ## 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 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, +## 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. ## --------------------------------------------------------------------------- -swagger: "2.0" +openapi: 3.0.1 info: - version: "1.0.0" - title: "swagger definition for org.apache.servicecomb.demo.registry.ServiceCenterEndpoint" - x-java-interface: "gen.swagger.ServiceCenterEndpointIntf" -basePath: "/v4/default/registry" -schemes: - - "http" -consumes: - - "application/json" -produces: - - "application/json" + title: swagger definition for org.apache.servicecomb.demo.localRegistryServer.ServerEndpoint + version: 1.0.0 +servers: + - url: /v4/default/registry paths: /instances: get: - operationId: "getInstances" + operationId: getInstances parameters: - - name: "appId" - in: "query" + - name: appId + in: query required: true - type: "string" - - name: "serviceName" - in: "query" + schema: + type: string + - name: serviceName + in: query required: true - type: "string" - - name: "global" - in: "query" + schema: + type: string + - name: global + in: query required: true - type: "string" - - name: "version" - in: "query" + schema: + type: string + - name: version + in: query required: true - type: "string" - - name: "x-domain-name" - in: "header" + schema: + type: string + - name: x-domain-name + in: header required: true - type: "string" - responses: - "200": - description: "response of 200" schema: - type: "object" \ No newline at end of file + type: string + responses: + 200: + description: response of 200 + content: + application/json: + schema: + type: object +components: + schemas: {} diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/registry.yaml b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/registry.yaml index 3bc2c1e4438..9d39b1b8bd1 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/registry.yaml +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/main/resources/registry.yaml @@ -29,7 +29,7 @@ thirdParty-no-schema-server: version: "4.0.0" appid: demo-multi-registries schemaIds: - - ServerEndpoint # not in local , discovery from demo-multi-registries-server + - ServerEndpoint # not in local , discovery from demo-multi-registries-server. Not supported since 3.0.0 instances: - endpoints: - - rest://localhost:8080 # actually will invoke to demo-multi-registries-server \ No newline at end of file + - rest://localhost:8080 # actually will invoke to demo-multi-registries-server diff --git a/demo/demo-multi-registries/demo-multi-registries-client/src/test/java/org/apache/servicecomb/demo/registry/MultiRegistriesIT.java b/demo/demo-multi-registries/demo-multi-registries-client/src/test/java/org/apache/servicecomb/demo/registry/MultiRegistriesIT.java index e50d92ab3c6..1c716783c2d 100644 --- a/demo/demo-multi-registries/demo-multi-registries-client/src/test/java/org/apache/servicecomb/demo/registry/MultiRegistriesIT.java +++ b/demo/demo-multi-registries/demo-multi-registries-client/src/test/java/org/apache/servicecomb/demo/registry/MultiRegistriesIT.java @@ -17,23 +17,21 @@ package org.apache.servicecomb.demo.registry; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class MultiRegistriesIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @Test public void clientGetsNoError() throws Exception { - Application.main(new String[0]); + MultiRegistriesClientApplication.main(new String[0]); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-multi-registries/demo-multi-registries-server/pom.xml b/demo/demo-multi-registries/demo-multi-registries-server/pom.xml index 57cbc2c3986..4a0b37f4433 100644 --- a/demo/demo-multi-registries/demo-multi-registries-server/pom.xml +++ b/demo/demo-multi-registries/demo-multi-registries-server/pom.xml @@ -25,20 +25,16 @@ org.apache.servicecomb.demo demo-multi-registries - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT - org.apache.servicecomb.demo.registry.ServerApplication + org.apache.servicecomb.demo.registry.MultiRegistriesServerApplication - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet + jakarta.ws.rs + jakarta.ws.rs-api org.apache.servicecomb.demo @@ -52,19 +48,6 @@ org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -72,15 +55,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerApplication.java b/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerApplication.java new file mode 100644 index 00000000000..afacef1155c --- /dev/null +++ b/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/MultiRegistriesServerApplication.java @@ -0,0 +1,43 @@ +/* + * 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.demo.registry; + +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class MultiRegistriesServerApplication { + public static void main(final String[] args) throws Exception { + new SpringApplicationBuilder().sources(MultiRegistriesServerApplication.class) + .web(WebApplicationType.SERVLET).build().run(args); + + SelfServiceInvoker invoker = BeanUtils.getBean("SelfServiceInvoker"); + invoker.latch.await(10, TimeUnit.SECONDS); + TestMgr.check(invoker.result, "hello"); + + TestMgr.summary(); + if (!TestMgr.errors().isEmpty()) { + System.exit(1); + } + } +} diff --git a/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerApplication.java b/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerApplication.java deleted file mode 100644 index 7d533030131..00000000000 --- a/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerApplication.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.demo.registry; - -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class ServerApplication { - public static void main(final String[] args) throws Exception { - new SpringApplicationBuilder().sources(ServerApplication.class).web(WebApplicationType.SERVLET).build().run(args); - - SelfServiceInvoker invoker = BeanUtils.getBean("SelfServiceInvoker"); - invoker.latch.await(10, TimeUnit.SECONDS); - TestMgr.check(invoker.result, "hello"); - - TestMgr.summary(); - if (!TestMgr.errors().isEmpty()) { - System.exit(1); - } - } -} diff --git a/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerEndpoint.java b/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerEndpoint.java index 595997f99e1..eb594aaba57 100644 --- a/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerEndpoint.java +++ b/demo/demo-multi-registries/demo-multi-registries-server/src/main/java/org/apache/servicecomb/demo/registry/ServerEndpoint.java @@ -17,26 +17,21 @@ package org.apache.servicecomb.demo.registry; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "ServerEndpoint") @RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) public class ServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ServerEndpoint.class); - @GetMapping(path = "/getName") public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); return name; } } diff --git a/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/application.yml b/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/application.yml index 76583151d0a..1104cebdbd7 100644 --- a/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/application.yml +++ b/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/application.yml @@ -18,15 +18,13 @@ server: port: 8080 -# java-chassis configurations - -APPLICATION_ID: demo-multi-registries -service_description: - name: demo-multi-registries-server - version: 0.0.2 servicecomb: service: - registry: + application: demo-multi-registries + name: demo-multi-registries-server + version: 0.0.2 + registry: + sc: address: http://127.0.0.1:30100 rest: - address: 0.0.0.0:8080 \ No newline at end of file + address: 0.0.0.0:8080 diff --git a/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/log4j2.xml b/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/logback.xml b/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-multi-registries/demo-multi-registries-server/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-multi-registries/pom.xml b/demo/demo-multi-registries/pom.xml index b754c804c0c..13f34c9c7af 100644 --- a/demo/demo-multi-registries/pom.xml +++ b/demo/demo-multi-registries/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-multi-registries Java Chassis::Demo::Multi Registry @@ -35,15 +35,15 @@ org.apache.servicecomb - java-chassis-spring-boot-starter-servlet + solution-basic org.apache.servicecomb - registry-local + java-chassis-spring-boot-starter-servlet org.apache.servicecomb - registry-schema-discovery + registry-local org.apache.servicecomb @@ -54,5 +54,17 @@ foundation-test-scaffolding compile + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/pom.xml b/demo/demo-multi-service-center/demo-multi-service-center-client/pom.xml index 9c82bcce58c..2669f28a874 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/pom.xml +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/pom.xml @@ -25,7 +25,7 @@ org.apache.servicecomb.demo demo-multi-service-center - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT @@ -33,10 +33,6 @@ - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - org.apache.servicecomb service-center-client @@ -106,8 +102,7 @@ alias - -Dservicecomb.service.registry.address=http://service30100:30100 - -Dservicecomb.service.publishAddress=${docker.hostname} + -Dservicecomb.registry.sc.address=http://service30100:30100 /maven/maven/demo-multi-service-center-servera-${project.version}.jar @@ -115,7 +110,7 @@ service30100:service30100 - Register microservice instance success + ServiceComb is ready 8080 @@ -135,8 +130,7 @@ alias - -Dservicecomb.service.registry.address=http://service40100:30100 - -Dservicecomb.service.publishAddress=${docker.hostname} + -Dservicecomb.registry.sc.address=http://service40100:30100 /maven/maven/demo-multi-service-center-serverb-${project.version}.jar @@ -144,7 +138,7 @@ service40100:service40100 - Register microservice instance success + ServiceComb is ready 8082 @@ -183,45 +177,6 @@ io.fabric8 docker-maven-plugin - - org.codehaus.gmaven - gmaven-plugin - - - add-default-properties - initialize - - execute - - - - project.properties.setProperty('docker.hostname', 'localhost') - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.19.1 - - - http://${docker.hostname}:30100 - - - ${jacoco.failsafe.argLine} - - - - - integration-test - verify - - - - diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/Application.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/Application.java index 30e4b5b5538..4264651164e 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/Application.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/Application.java @@ -23,14 +23,12 @@ import org.apache.servicecomb.demo.CategorizedTestCaseRunner; import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.stereotype.Component; @SpringBootApplication -@EnableServiceComb @Component public class Application { @@ -43,7 +41,6 @@ public static void main(final String[] args) throws Exception { public static void runTest() throws Exception { CategorizedTestCaseRunner.runCategorizedTestCase("demo-multi-service-center-serverA"); - testRegistryThreads(); testTransportThreads(); TestMgr.summary(); if (!TestMgr.errors().isEmpty()) { @@ -55,41 +52,20 @@ private static void testTransportThreads() throws Exception { Set threadSet = Thread.getAllStackTraces().keySet(); List expectedThread = new ArrayList<>(); threadSet.forEach(thread -> { - if (thread.getName().contains("transport-")) { + if (thread.getName().startsWith("transport-vert.x-eventloop-thread")) { expectedThread.add(thread.getName()); } }); + // After SSL improvements https://github.com/eclipse-vertx/vert.x/pull/4468 introduced in 4.3.4 + // SSL helper will use `internal-blocking` thread init ssl engine + // transport-vert.x-eventloop-thread-0 + // transport-vert.x-eventloop-thread-1 + // transport-vert.x-eventloop-thread-2 + // transport-vert.x-eventloop-thread-3 + // transport-vert.x-eventloop-thread-4 + // transport-vert.x-eventloop-thread-5 + // transport-vert.x-internal-blocking-0 + // transport-vert.x-internal-blocking-1 TestMgr.check(6, expectedThread.size()); } - - private static void testRegistryThreads() throws Exception { - Set threadSet = Thread.getAllStackTraces().keySet(); - List expectedThread = new ArrayList<>(); - threadSet.forEach(thread -> { - if (thread.getName().contains("registry-")) { - expectedThread.add(thread.getName()); - } - }); - //registry-watch-vert.x-eventloop-thread-3(option) - //registry-watch-vert.x-eventloop-thread-2(option) - //registry-watch-vert.x-eventloop-thread-1 - //registry-watch-vert.x-eventloop-thread-0 - //registry-watch-serverB-vert.x-eventloop-thread-3(option) - //registry-watch-serverB-vert.x-eventloop-thread-2(option) - //registry-watch-serverB-vert.x-eventloop-thread-1 - //registry-watch-serverB-vert.x-eventloop-thread-0 - //registry-watch-pool-worker-service-center-watch-1 - //registry-watch-pool-worker-service-center-watch-0 - //registry-watch-serverB-pool-worker-service-center-watch-1 - //registry-watch-serverB-pool-worker-service-center-watch-0 - //registry-vert.x-eventloop-thread-3(option) - //registry-vert.x-eventloop-thread-2(option) - //registry-vert.x-eventloop-thread-1 - //registry-vert.x-eventloop-thread-0 - //registry-serverB-vert.x-eventloop-thread-3(option) - //registry-serverB-vert.x-eventloop-thread-2(option) - //registry-serverB-vert.x-eventloop-thread-1 - //registry-serverB-vert.x-eventloop-thread-0 - TestMgr.check(expectedThread.size() >= 12, expectedThread.size() <= 20); - } } diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java index ef523b21af1..3b11e0582d8 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/RegistryClientTest.java @@ -28,8 +28,7 @@ import org.apache.servicecomb.foundation.common.event.SimpleEventBus; import org.apache.servicecomb.http.client.auth.DefaultRequestAuthHeaderProvider; import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; -import org.apache.servicecomb.service.center.client.AddressManager; -import org.apache.servicecomb.service.center.client.DiscoveryEvents.InstanceChangedEvent; +import org.apache.servicecomb.service.center.client.ServiceCenterAddressManager; import org.apache.servicecomb.service.center.client.RegistrationEvents; import org.apache.servicecomb.service.center.client.RegistrationEvents.HeartBeatEvent; import org.apache.servicecomb.service.center.client.RegistrationEvents.MicroserviceInstanceRegistrationEvent; @@ -43,6 +42,8 @@ import org.apache.servicecomb.service.center.client.model.MicroserviceInstance; import org.apache.servicecomb.service.center.client.model.SchemaInfo; import org.apache.servicecomb.service.center.client.model.ServiceCenterConfiguration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.stereotype.Component; import com.google.common.base.Charsets; @@ -56,20 +57,24 @@ public class RegistryClientTest implements CategorizedTestCase { private CountDownLatch registrationCounter = new CountDownLatch(1); - private CountDownLatch discoveryCounter = new CountDownLatch(1); - - private List instances; - // auto test only tests 'hasRegistered=false', can run this client many times to test 'hasRegistered=true' private boolean hasRegistered = true; + private final Environment environment; + + @Autowired + public RegistryClientTest(Environment environment) { + this.environment = environment; + } + @Override public void testRestTransport() throws Exception { - AddressManager addressManager = new AddressManager("default", Arrays.asList("http://127.0.0.1:30100")); + ServiceCenterAddressManager addressManager = new ServiceCenterAddressManager("default", + Arrays.asList("http://127.0.0.1:30100"), new EventBus(), "", ""); SSLProperties sslProperties = new SSLProperties(); sslProperties.setEnabled(false); ServiceCenterClient serviceCenterClient = new ServiceCenterClient(addressManager, sslProperties, - new DefaultRequestAuthHeaderProvider(), "default", null); + new DefaultRequestAuthHeaderProvider(), "default", null, environment); EventBus eventBus = new SimpleEventBus(); ServiceCenterConfiguration serviceCenterConfiguration = new ServiceCenterConfiguration(); ServiceCenterRegistration serviceCenterRegistration = new ServiceCenterRegistration(serviceCenterClient, @@ -133,8 +138,9 @@ public void testRestTransport() throws Exception { ServiceCenterDiscovery discovery = new ServiceCenterDiscovery(serviceCenterClient, eventBus); discovery.updateMyselfServiceId(microservice.getServiceId()); discovery.startDiscovery(); - discovery.registerIfNotPresent(new SubscriptionKey(microservice.getAppId(), microservice.getServiceName())); - discoveryCounter.await(30000, TimeUnit.MILLISECONDS); + SubscriptionKey subscriptionKey = new SubscriptionKey(microservice.getAppId(), microservice.getServiceName()); + discovery.registerIfNotPresent(subscriptionKey); + List instances = discovery.getInstanceCache(subscriptionKey); TestMgr.check(instances != null, true); TestMgr.check(instances.size(), 1); discovery.stop(); @@ -163,10 +169,4 @@ public void onHeartBeatEvent(HeartBeatEvent event) { events.add(event); registrationCounter.countDown(); } - - @Subscribe - public void onInstanceChangedEvent(InstanceChangedEvent event) { - instances = event.getInstances(); - discoveryCounter.countDown(); - } } diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java new file mode 100644 index 00000000000..db7fc11df06 --- /dev/null +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Configuration.java @@ -0,0 +1,69 @@ +/* + * 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.demo.multiServiceCenterClient; + +import java.util.List; + +import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; +import org.apache.servicecomb.registry.sc.SCClientUtils; +import org.apache.servicecomb.registry.sc.SCConfigurationProperties; +import org.apache.servicecomb.registry.sc.SCConst; +import org.apache.servicecomb.service.center.client.ServiceCenterClient; +import org.apache.servicecomb.service.center.client.ServiceCenterWatch; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class SC2Configuration { + @Bean + @ConfigurationProperties(prefix = SCConst.SC_REGISTRY_PREFIX + "2") + public SCConfigurationProperties scConfigurationProperties2() { + return new SCConfigurationProperties(); + } + + @Bean + public ServiceCenterWatch serviceCenterWatch2( + @Qualifier("scConfigurationProperties2") SCConfigurationProperties scConfigurationProperties2, + List authHeaderProviders, Environment environment) { + return SCClientUtils.serviceCenterWatch(scConfigurationProperties2, authHeaderProviders, environment); + } + + @Bean + public ServiceCenterClient serviceCenterClient2( + @Qualifier("scConfigurationProperties2") SCConfigurationProperties scConfigurationProperties2, + Environment environment) { + return SCClientUtils.serviceCenterClient(scConfigurationProperties2, environment); + } + + @Bean + public SC2Discovery sc2Discovery( + @Qualifier("scConfigurationProperties2") SCConfigurationProperties scConfigurationProperties2, + @Qualifier("serviceCenterClient2") ServiceCenterClient serviceCenterClient2) { + return new SC2Discovery(scConfigurationProperties2, serviceCenterClient2); + } + + @Bean + public SC2Registration sc2Registration( + @Qualifier("scConfigurationProperties2") SCConfigurationProperties scConfigurationProperties2, + @Qualifier("serviceCenterClient2") ServiceCenterClient serviceCenterClient2, + @Qualifier("serviceCenterWatch2") ServiceCenterWatch serviceCenterWatch2) { + return new SC2Registration(scConfigurationProperties2, serviceCenterClient2, serviceCenterWatch2); + } +} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Discovery.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Discovery.java new file mode 100644 index 00000000000..e6669d294ea --- /dev/null +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Discovery.java @@ -0,0 +1,34 @@ +/* + * 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.demo.multiServiceCenterClient; + +import org.apache.servicecomb.registry.sc.SCConfigurationProperties; +import org.apache.servicecomb.registry.sc.SCConst; +import org.apache.servicecomb.registry.sc.SCDiscovery; +import org.apache.servicecomb.service.center.client.ServiceCenterClient; + +public class SC2Discovery extends SCDiscovery { + public SC2Discovery(SCConfigurationProperties configurationProperties, + ServiceCenterClient serviceCenterClient) { + super(configurationProperties, serviceCenterClient); + } + + @Override + public String name() { + return SCConst.SC_REGISTRY_NAME + "2"; + } +} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Registration.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Registration.java new file mode 100644 index 00000000000..7fd22f03616 --- /dev/null +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/SC2Registration.java @@ -0,0 +1,35 @@ +/* + * 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.demo.multiServiceCenterClient; + +import org.apache.servicecomb.registry.sc.SCConfigurationProperties; +import org.apache.servicecomb.registry.sc.SCConst; +import org.apache.servicecomb.registry.sc.SCRegistration; +import org.apache.servicecomb.service.center.client.ServiceCenterClient; +import org.apache.servicecomb.service.center.client.ServiceCenterWatch; + +public class SC2Registration extends SCRegistration { + public SC2Registration(SCConfigurationProperties configurationProperties, + ServiceCenterClient serviceCenterClient, ServiceCenterWatch serviceCenterWatch) { + super(configurationProperties, serviceCenterClient, serviceCenterWatch); + } + + @Override + public String name() { + return SCConst.SC_REGISTRY_NAME + 2; + } +} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBRegistryHttpClientOptionsSPI.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBRegistryHttpClientOptionsSPI.java deleted file mode 100644 index 003a9624e9a..00000000000 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBRegistryHttpClientOptionsSPI.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.demo.multiServiceCenterClient; - -import org.apache.servicecomb.serviceregistry.client.http.RegistryHttpClientOptionsSPI; - -public class ServerBRegistryHttpClientOptionsSPI extends RegistryHttpClientOptionsSPI { - public static final String CLIENT_NAME = "registry-serverB"; - - @Override - public String clientName() { - return CLIENT_NAME; - } - - @Override - public String getConfigTag() { - return "sc.serverB.consumer"; - } - - @Override - public boolean isSsl() { - return false; - } -} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBRegistryWatchHttpClientOptionsSPI.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBRegistryWatchHttpClientOptionsSPI.java deleted file mode 100644 index 5c25d0194e6..00000000000 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBRegistryWatchHttpClientOptionsSPI.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.demo.multiServiceCenterClient; - -import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig; - -import com.netflix.config.DynamicPropertyFactory; - -public class ServerBRegistryWatchHttpClientOptionsSPI extends ServerBRegistryHttpClientOptionsSPI { - public static final String CLIENT_NAME = "registry-watch-serverB"; - - private ServiceRegistryConfig serviceRegistryConfig = ServiceRegistryConfig.INSTANCE; - - @Override - public String clientName() { - return CLIENT_NAME; - } - - @Override - public int getOrder() { - // low priority than registry - return super.getOrder() + 1; - } - - @Override - public boolean enabled() { - return serviceRegistryConfig.isWatch(); - } - - @Override - public boolean isWorker() { - return true; - } - - - @Override - public String getWorkerPoolName() { - return "pool-worker-service-center-watch-serverB"; - } - - @Override - public int getWorkerPoolSize() { - return DynamicPropertyFactory.getInstance() - .getIntProperty(ServiceRegistryConfig.WORKER_POOL_SIZE, 2).get(); - } - - @Override - public boolean isProxyEnable() { - return false; - } -} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBServiceCenterConfiguration.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBServiceCenterConfiguration.java deleted file mode 100644 index d27e9676751..00000000000 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBServiceCenterConfiguration.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.demo.multiServiceCenterClient; - -import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfig; -import org.apache.servicecomb.serviceregistry.config.ServiceRegistryConfigCustomizer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class ServerBServiceCenterConfiguration { - @Bean("serverBServiceCenterConfig") - public ServiceRegistryConfig serverBServiceCenterConfig() { - ServiceRegistryConfig config = ServiceRegistryConfig.buildFromConfiguration(); - return ServiceRegistryConfigCustomizer.from(config) - .addressListFromConfiguration("servicecomb.service.registry-serverB.address") - // use a different http client instance - .setClientName("registry-serverB") - .setWatchClientName("registry-watch-serverB") - .setRegistryName("server-B") - .get(); - } -} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBTest.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBTest.java index cbb2b42c0e0..f76836d4ef8 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBTest.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/java/org/apache/servicecomb/demo/multiServiceCenterClient/ServerBTest.java @@ -64,4 +64,4 @@ public void testRestTransport() throws Exception { public String getMicroserviceName() { return "demo-multi-service-center-serverB"; } -} \ No newline at end of file +} diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.vertx.client.http.HttpClientOptionsSPI b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.vertx.client.http.HttpClientOptionsSPI deleted file mode 100644 index ea85cbefeb7..00000000000 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.vertx.client.http.HttpClientOptionsSPI +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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.servicecomb.demo.multiServiceCenterClient.ServerBRegistryHttpClientOptionsSPI -org.apache.servicecomb.demo.multiServiceCenterClient.ServerBRegistryWatchHttpClientOptionsSPI \ No newline at end of file diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/application.yml b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/application.yml index 4999ed0238e..6daa76e8dee 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/application.yml +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/application.yml @@ -15,23 +15,17 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -# java-chassis configurations -APPLICATION_ID: demo-multi-service-center -service_description: - name: demo-multi-service-center-client - version: 0.0.2 servicecomb: service: - registry: + application: demo-multi-service-center + name: demo-multi-service-center-client + version: 0.0.2 + registry: + sc: address: http://127.0.0.1:30100 - registry-serverB: + sc2: address: http://127.0.0.1:40100 - handler: - chain: - Consumer: - default: loadbalance - transport: eventloop: - size: 6 \ No newline at end of file + size: 6 diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/log4j2.xml b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multi-service-center/demo-multi-service-center-client/src/test/java/org/apache/servicecomb/demo/multiServiceCenterClient/MultiServiceCenterIT.java b/demo/demo-multi-service-center/demo-multi-service-center-client/src/test/java/org/apache/servicecomb/demo/multiServiceCenterClient/MultiServiceCenterIT.java index e1c9e8e1f04..f7cd5157171 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-client/src/test/java/org/apache/servicecomb/demo/multiServiceCenterClient/MultiServiceCenterIT.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-client/src/test/java/org/apache/servicecomb/demo/multiServiceCenterClient/MultiServiceCenterIT.java @@ -17,15 +17,13 @@ package org.apache.servicecomb.demo.multiServiceCenterClient; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class MultiServiceCenterIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @@ -34,6 +32,6 @@ public void setUp() throws Exception { public void clientGetsNoError() throws Exception { Application.main(new String[0]); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverA/pom.xml b/demo/demo-multi-service-center/demo-multi-service-center-serverA/pom.xml index e338ab4a646..ddfd3570a43 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverA/pom.xml +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverA/pom.xml @@ -25,7 +25,7 @@ org.apache.servicecomb.demo demo-multi-service-center - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT @@ -33,12 +33,8 @@ - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet + jakarta.ws.rs + jakarta.ws.rs-api org.apache.servicecomb.demo @@ -52,19 +48,6 @@ org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -72,15 +55,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerApplication.java b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerApplication.java index ad905c9e947..4515d6c7575 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerApplication.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerApplication.java @@ -17,13 +17,11 @@ package org.apache.servicecomb.demo.multiServiceCenter; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ServerApplication { public static void main(final String[] args) throws Exception { new SpringApplicationBuilder().sources(ServerApplication.class) diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerEndpoint.java b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerEndpoint.java index 2e6efa642b5..16fdb41bdde 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerEndpoint.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/java/org/apache/servicecomb/demo/multiServiceCenter/ServerEndpoint.java @@ -17,26 +17,21 @@ package org.apache.servicecomb.demo.multiServiceCenter; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "ServerEndpoint") @RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) public class ServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ServerEndpoint.class); - @GetMapping(path = "/getName") public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); return name; } } diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/application.yml b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/application.yml index 0ff926920d6..03f54c0db15 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/application.yml +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/application.yml @@ -18,15 +18,13 @@ server: port: 8080 -# java-chassis configurations - -APPLICATION_ID: demo-multi-service-center -service_description: - name: demo-multi-service-center-serverA - version: 0.0.2 servicecomb: service: - registry: + application: demo-multi-service-center + name: demo-multi-service-center-serverA + version: 0.0.2 + registry: + sc: address: http://127.0.0.1:30100 rest: - address: 0.0.0.0:8080 \ No newline at end of file + address: 0.0.0.0:8080 diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/log4j2.xml b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverA/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/pom.xml b/demo/demo-multi-service-center/demo-multi-service-center-serverB/pom.xml index e714920fab6..66dfd58d9b4 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/pom.xml +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/pom.xml @@ -25,7 +25,7 @@ org.apache.servicecomb.demo demo-multi-service-center - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT @@ -33,12 +33,8 @@ - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet + jakarta.ws.rs + jakarta.ws.rs-api org.apache.servicecomb.demo @@ -52,19 +48,6 @@ org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -72,15 +55,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ConfigurationEndpoint.java b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ConfigurationEndpoint.java index ec0b8f4e2ec..edbb116ccca 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ConfigurationEndpoint.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ConfigurationEndpoint.java @@ -19,8 +19,6 @@ import java.util.List; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.provider.rest.common.RestSchema; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,7 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import com.netflix.config.DynamicPropertyFactory; +import jakarta.ws.rs.core.MediaType; @RestSchema(schemaId = "ConfigurationEndpoint") @RequestMapping(path = "/register/url/config", produces = MediaType.APPLICATION_JSON) @@ -39,9 +37,13 @@ public class ConfigurationEndpoint { private static final Logger LOGGER = LoggerFactory.getLogger(ServerEndpoint.class); - @Autowired private Environment environment; + @Autowired + public ConfigurationEndpoint(Environment environment) { + this.environment = environment; + } + @Value("${demo.multi.service.center.serverB.key1}") private String key1; @@ -68,7 +70,7 @@ public String getValue(@RequestParam(name = "key") String key, @RequestParam(nam if (type == 1) { return environment.getProperty(key); } else if (type == 2) { - return DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); + return environment.getProperty(key); } else { switch (key) { case "demo.multi.service.center.serverB.key1": diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerApplication.java b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerApplication.java index 531e8ff7c5b..49106b7b8dd 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerApplication.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerApplication.java @@ -17,13 +17,11 @@ package org.apache.servicecomb.demo.multiServiceCenterServerB; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ServerApplication { public static void main(final String[] args) throws Exception { new SpringApplicationBuilder().sources(ServerApplication.class) diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerEndpoint.java b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerEndpoint.java index af822e86853..d14c1d4a7b0 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerEndpoint.java +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/java/org/apache/servicecomb/demo/multiServiceCenterServerB/ServerEndpoint.java @@ -17,26 +17,21 @@ package org.apache.servicecomb.demo.multiServiceCenterServerB; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "ServerEndpoint") @RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) public class ServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ServerEndpoint.class); - @GetMapping(path = "/getName") public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); return name; } } diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.properties b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.properties index 6072aab4566..121f1aa95c6 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.properties +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.properties @@ -17,4 +17,4 @@ demo.multi.service.center.serverB.actual.key6=key6 demo.multi.service.center.serverB.actual.key7.1=key71 -demo.multi.service.center.serverB.actual.key7.2=key72 \ No newline at end of file +demo.multi.service.center.serverB.actual.key7.2=key72 diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.yml b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.yml index 8303ad5c5e9..e9850bc8c23 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.yml +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/application.yml @@ -18,15 +18,13 @@ server: port: 8082 -# java-chassis configurations - -APPLICATION_ID: demo-multi-service-center -service_description: - name: demo-multi-service-center-serverB - version: 0.0.2 servicecomb: service: - registry: + application: demo-multi-service-center + name: demo-multi-service-center-serverB + version: 0.0.2 + registry: + sc: address: http://127.0.0.1:40100 rest: address: 0.0.0.0:8082 @@ -35,4 +33,3 @@ demo.multi.service.center.serverB: key1: key1-boot key4: key4-boot key5: key5 - diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/log4j2.xml b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/microservice.yaml b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/microservice.yaml index 52cd6c8eab1..2164cf6ac9f 100644 --- a/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/microservice.yaml +++ b/demo/demo-multi-service-center/demo-multi-service-center-serverB/src/main/resources/microservice.yaml @@ -26,4 +26,4 @@ demo.multi.service.center.serverB: key6: ${demo.multi.service.center.serverB.actual.key6} key7: - ${demo.multi.service.center.serverB.actual.key7.1} - - ${demo.multi.service.center.serverB.actual.key7.2} \ No newline at end of file + - ${demo.multi.service.center.serverB.actual.key7.2} diff --git a/demo/demo-multi-service-center/pom.xml b/demo/demo-multi-service-center/pom.xml index 04a1f3fa2cc..cf9c101e496 100644 --- a/demo/demo-multi-service-center/pom.xml +++ b/demo/demo-multi-service-center/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-multi-service-center Java Chassis::Demo::Multi Service Centers @@ -34,6 +34,10 @@ + + org.apache.servicecomb + solution-basic + org.apache.servicecomb java-chassis-spring-boot-starter-servlet @@ -47,5 +51,17 @@ foundation-test-scaffolding compile + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + diff --git a/demo/demo-multiple/a-client/pom.xml b/demo/demo-multiple/a-client/pom.xml index 9664b4bd78b..84131a7909c 100644 --- a/demo/demo-multiple/a-client/pom.xml +++ b/demo/demo-multiple/a-client/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-multiple - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT a-client Java Chassis::Demo::Multiple::A client @@ -30,4 +30,5 @@ org.apache.servicecomb.demo.multiple.a.client.AClientMain + diff --git a/demo/demo-multiple/a-client/src/main/java/org/apache/servicecomb/demo/multiple/a/client/AClientMain.java b/demo/demo-multiple/a-client/src/main/java/org/apache/servicecomb/demo/multiple/a/client/AClientMain.java index c41e154cca9..907df46c2c7 100644 --- a/demo/demo-multiple/a-client/src/main/java/org/apache/servicecomb/demo/multiple/a/client/AClientMain.java +++ b/demo/demo-multiple/a-client/src/main/java/org/apache/servicecomb/demo/multiple/a/client/AClientMain.java @@ -19,12 +19,12 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.builder.SpringApplicationBuilder; public class AClientMain { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(AClientMain.class).web(WebApplicationType.NONE).run(args); AClient client = BeanUtils.getContext().getBean(AClient.class); client.run(); diff --git a/demo/demo-multiple/a-client/src/main/resources/log4j2.xml b/demo/demo-multiple/a-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multiple/a-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multiple/a-client/src/main/resources/microservice.yaml b/demo/demo-multiple/a-client/src/main/resources/microservice.yaml index 9a8ea2d7fe7..81a782bafc2 100644 --- a/demo/demo-multiple/a-client/src/main/resources/microservice.yaml +++ b/demo/demo-multiple/a-client/src/main/resources/microservice.yaml @@ -16,11 +16,12 @@ ## --------------------------------------------------------------------------- a-server.name: a-server -APPLICATION_ID: multiple -service_description: - name: a-client - version: 0.0.1 + servicecomb: service: - registry: + application: multiple + name: a-client + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 diff --git a/demo/demo-multiple/a-server/pom.xml b/demo/demo-multiple/a-server/pom.xml index b97433fb4da..d38b12d8d62 100644 --- a/demo/demo-multiple/a-server/pom.xml +++ b/demo/demo-multiple/a-server/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-multiple - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT a-server Java Chassis::Demo::Multiple::A server @@ -31,4 +31,5 @@ org.apache.servicecomb.demo.multiple.a.server.AServerMain + diff --git a/demo/demo-multiple/a-server/src/main/java/org/apache/servicecomb/demo/multiple/a/server/AServerMain.java b/demo/demo-multiple/a-server/src/main/java/org/apache/servicecomb/demo/multiple/a/server/AServerMain.java index 8f750c499a5..40c96981c7a 100644 --- a/demo/demo-multiple/a-server/src/main/java/org/apache/servicecomb/demo/multiple/a/server/AServerMain.java +++ b/demo/demo-multiple/a-server/src/main/java/org/apache/servicecomb/demo/multiple/a/server/AServerMain.java @@ -17,12 +17,11 @@ package org.apache.servicecomb.demo.multiple.a.server; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.builder.SpringApplicationBuilder; public class AServerMain { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(AServerMain.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-multiple/a-server/src/main/resources/log4j2.xml b/demo/demo-multiple/a-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multiple/a-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multiple/a-server/src/main/resources/microservice.yaml b/demo/demo-multiple/a-server/src/main/resources/microservice.yaml index b24d620d4bb..d916c594f79 100644 --- a/demo/demo-multiple/a-server/src/main/resources/microservice.yaml +++ b/demo/demo-multiple/a-server/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: multiple -service_description: - name: a-server - version: 0.0.1 servicecomb: service: - registry: + application: multiple + name: a-server + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8080 diff --git a/demo/demo-multiple/b-client/pom.xml b/demo/demo-multiple/b-client/pom.xml index fdf6f2860c9..4ab02a66f1b 100644 --- a/demo/demo-multiple/b-client/pom.xml +++ b/demo/demo-multiple/b-client/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-multiple - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT b-client Java Chassis::Demo::Multiple::B client @@ -30,4 +30,5 @@ org.apache.servicecomb.demo.multiple.b.client.BClientMain + diff --git a/demo/demo-multiple/b-client/src/main/java/org/apache/servicecomb/demo/multiple/b/client/BClientMain.java b/demo/demo-multiple/b-client/src/main/java/org/apache/servicecomb/demo/multiple/b/client/BClientMain.java index 7c9939a843f..a6400d91a4e 100644 --- a/demo/demo-multiple/b-client/src/main/java/org/apache/servicecomb/demo/multiple/b/client/BClientMain.java +++ b/demo/demo-multiple/b-client/src/main/java/org/apache/servicecomb/demo/multiple/b/client/BClientMain.java @@ -19,12 +19,12 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.builder.SpringApplicationBuilder; public class BClientMain { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(BClientMain.class).web(WebApplicationType.NONE).run(args); BClient client = BeanUtils.getContext().getBean(BClient.class); client.run(); diff --git a/demo/demo-multiple/b-client/src/main/resources/log4j2.xml b/demo/demo-multiple/b-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multiple/b-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multiple/b-client/src/main/resources/microservice.yaml b/demo/demo-multiple/b-client/src/main/resources/microservice.yaml index ea9f8a88776..8445ed3f4d8 100644 --- a/demo/demo-multiple/b-client/src/main/resources/microservice.yaml +++ b/demo/demo-multiple/b-client/src/main/resources/microservice.yaml @@ -16,11 +16,12 @@ ## --------------------------------------------------------------------------- b-server.name: b-server -APPLICATION_ID: multiple -service_description: - name: b-client - version: 0.0.1 + servicecomb: service: - registry: + application: multiple + name: b-client + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 diff --git a/demo/demo-multiple/b-server/pom.xml b/demo/demo-multiple/b-server/pom.xml index f49306efb7e..e33e750d8e4 100644 --- a/demo/demo-multiple/b-server/pom.xml +++ b/demo/demo-multiple/b-server/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-multiple - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT b-server diff --git a/demo/demo-multiple/b-server/src/main/java/org/apache/servicecomb/demo/multiple/b/server/BServerMain.java b/demo/demo-multiple/b-server/src/main/java/org/apache/servicecomb/demo/multiple/b/server/BServerMain.java index 28d964df945..267925aceae 100644 --- a/demo/demo-multiple/b-server/src/main/java/org/apache/servicecomb/demo/multiple/b/server/BServerMain.java +++ b/demo/demo-multiple/b-server/src/main/java/org/apache/servicecomb/demo/multiple/b/server/BServerMain.java @@ -17,12 +17,11 @@ package org.apache.servicecomb.demo.multiple.b.server; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.builder.SpringApplicationBuilder; public class BServerMain { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(BServerMain.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-multiple/b-server/src/main/resources/log4j2.xml b/demo/demo-multiple/b-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multiple/b-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multiple/b-server/src/main/resources/microservice.yaml b/demo/demo-multiple/b-server/src/main/resources/microservice.yaml index 814dbfae3b2..695ed8f50a8 100644 --- a/demo/demo-multiple/b-server/src/main/resources/microservice.yaml +++ b/demo/demo-multiple/b-server/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: multiple -service_description: - name: b-server - version: 0.0.1 servicecomb: service: - registry: + application: multiple + name: b-server + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8080 diff --git a/demo/demo-multiple/multiple-client/pom.xml b/demo/demo-multiple/multiple-client/pom.xml index 447799e1cc5..7dcbb6f14f2 100644 --- a/demo/demo-multiple/multiple-client/pom.xml +++ b/demo/demo-multiple/multiple-client/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-multiple - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT multiple-client Java Chassis::Demo::Multiple::Client @@ -40,23 +40,6 @@ org.apache.servicecomb.demo.multiple.client.MultipleClient - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - @@ -65,6 +48,83 @@ multiple-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-multiple/multiple-client/src/main/java/org/apache/servicecomb/demo/multiple/client/MultipleClient.java b/demo/demo-multiple/multiple-client/src/main/java/org/apache/servicecomb/demo/multiple/client/MultipleClient.java index c46a0ee6296..ae804ad8bea 100644 --- a/demo/demo-multiple/multiple-client/src/main/java/org/apache/servicecomb/demo/multiple/client/MultipleClient.java +++ b/demo/demo-multiple/multiple-client/src/main/java/org/apache/servicecomb/demo/multiple/client/MultipleClient.java @@ -20,13 +20,22 @@ import org.apache.servicecomb.demo.multiple.a.client.AClient; import org.apache.servicecomb.demo.multiple.b.client.BClient; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ComponentScan; +@SpringBootApplication +@ComponentScan(basePackages = {"org.apache.servicecomb.demo.multiple.a.client", + "org.apache.servicecomb.demo.multiple.b.client"}) public class MultipleClient { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(MultipleClient.class).web(WebApplicationType.NONE).run(args); + runTest(); + } + + public static void runTest() { AClient aClient = BeanUtils.getContext().getBean(AClient.class); BClient bClient = BeanUtils.getContext().getBean(BClient.class); diff --git a/demo/demo-multiple/multiple-client/src/main/resources/log4j2.xml b/demo/demo-multiple/multiple-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multiple/multiple-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multiple/multiple-client/src/main/resources/microservice.yaml b/demo/demo-multiple/multiple-client/src/main/resources/microservice.yaml index f06dd95db94..1ece43eac98 100644 --- a/demo/demo-multiple/multiple-client/src/main/resources/microservice.yaml +++ b/demo/demo-multiple/multiple-client/src/main/resources/microservice.yaml @@ -18,7 +18,9 @@ servicecomb-config-order: 1000 a-server.name: merged-server b-server.name: merged-server -APPLICATION_ID: multiple -service_description: - name: merged-client - version: 0.0.1 + +servicecomb: + service: + application: multiple + name: merged-client + version: 0.0.1 diff --git a/demo/demo-multiple/multiple-client/src/test/java/org/apache/servicecomb/demo/multiple/client/MultipleIT.java b/demo/demo-multiple/multiple-client/src/test/java/org/apache/servicecomb/demo/multiple/client/MultipleIT.java new file mode 100644 index 00000000000..c5c839ae651 --- /dev/null +++ b/demo/demo-multiple/multiple-client/src/test/java/org/apache/servicecomb/demo/multiple/client/MultipleIT.java @@ -0,0 +1,43 @@ +/* + * 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.demo.multiple.client; + +import org.apache.servicecomb.demo.TestMgr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = MultipleClient.class) +public class MultipleIT { + + @BeforeEach + public void setUp() { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() throws Exception { + MultipleClient.runTest(); + + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/demo-multiple/multiple-server/pom.xml b/demo/demo-multiple/multiple-server/pom.xml index 28247df90d2..18c7ae19069 100644 --- a/demo/demo-multiple/multiple-server/pom.xml +++ b/demo/demo-multiple/multiple-server/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-multiple - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT multiple-server Java Chassis::Demo::Multiple::Server @@ -40,26 +40,13 @@ org.apache.servicecomb.demo.multiple.server.MultipleServer + - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin - @@ -67,15 +54,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-multiple/multiple-server/src/main/java/org/apache/servicecomb/demo/multiple/server/MultipleServer.java b/demo/demo-multiple/multiple-server/src/main/java/org/apache/servicecomb/demo/multiple/server/MultipleServer.java index 9c1113380a5..5b830e46e83 100644 --- a/demo/demo-multiple/multiple-server/src/main/java/org/apache/servicecomb/demo/multiple/server/MultipleServer.java +++ b/demo/demo-multiple/multiple-server/src/main/java/org/apache/servicecomb/demo/multiple/server/MultipleServer.java @@ -16,12 +16,16 @@ */ package org.apache.servicecomb.demo.multiple.server; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ComponentScan; +@SpringBootApplication +@ComponentScan(basePackages = {"org.apache.servicecomb.demo.multiple.a.server", + "org.apache.servicecomb.demo.multiple.b.server"}) public class MultipleServer { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(MultipleServer.class).web(WebApplicationType.NONE).run(args); } } diff --git a/demo/demo-multiple/multiple-server/src/main/resources/log4j2.xml b/demo/demo-multiple/multiple-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-multiple/multiple-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-multiple/multiple-server/src/main/resources/microservice.yaml b/demo/demo-multiple/multiple-server/src/main/resources/microservice.yaml index 94fb8d2bc30..b1eeade93d7 100644 --- a/demo/demo-multiple/multiple-server/src/main/resources/microservice.yaml +++ b/demo/demo-multiple/multiple-server/src/main/resources/microservice.yaml @@ -16,7 +16,9 @@ ## --------------------------------------------------------------------------- servicecomb-config-order: 1000 -APPLICATION_ID: multiple -service_description: - name: merged-server - version: 0.0.1 + +servicecomb: + service: + application: multiple + name: merged-server + version: 0.0.1 diff --git a/demo/demo-multiple/pom.xml b/demo/demo-multiple/pom.xml index f5e0bfd3fca..7496a2050d7 100644 --- a/demo/demo-multiple/pom.xml +++ b/demo/demo-multiple/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-multiple Java Chassis::Demo::Multiple @@ -72,15 +72,19 @@ org.apache.servicecomb - provider-pojo + java-chassis-spring-boot-starter-standalone - log4j - log4j + org.apache.logging.log4j + log4j-slf4j-impl - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core diff --git a/demo/demo-nacos/README.md b/demo/demo-nacos/README.md new file mode 100644 index 00000000000..9165cac5687 --- /dev/null +++ b/demo/demo-nacos/README.md @@ -0,0 +1,5 @@ +# Notice + +This integration tests is designed for Nacos registry and configuration. And extra test cases include: + +* Test cases related to JAX-RS annotations that demo-jaxrs can not cover. diff --git a/demo/demo-nacos/consumer/pom.xml b/demo/demo-nacos/consumer/pom.xml new file mode 100644 index 00000000000..6dfe326f6a5 --- /dev/null +++ b/demo/demo-nacos/consumer/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-nacos + 3.4.0-SNAPSHOT + + + nacos-consumer + Java Chassis::Demo::NACOS::CONSUMER + jar + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + registry-nacos + + + + + + + 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-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java new file mode 100644 index 00000000000..3e7a2a0e285 --- /dev/null +++ b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.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 ConsumerApplication { + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ConsumerApplication.class).run(args); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java new file mode 100644 index 00000000000..437f88bfafd --- /dev/null +++ b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java @@ -0,0 +1,42 @@ +/* + * 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.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@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("/authIncludePath") + public String authIncludePath() { + return providerService.authIncludePath(); + } +} diff --git a/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java new file mode 100644 index 00000000000..aed6894f941 --- /dev/null +++ b/demo/demo-nacos/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.IHeaderParamWithListSchema; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.rest.common.RestSchema; + +@RestSchema(schemaId = "ConsumerHeaderParamWithListSchema", schemaInterface = IHeaderParamWithListSchema.class) +public class ConsumerHeaderParamWithListSchema implements IHeaderParamWithListSchema { + @RpcReference(microserviceName = "provider", schemaId = "HeaderParamWithListSchema") + private IHeaderParamWithListSchema 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-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java new file mode 100644 index 00000000000..ee62a110625 --- /dev/null +++ b/demo/demo-nacos/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java @@ -0,0 +1,24 @@ +/* + * 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 authIncludePath(); +} diff --git a/demo/demo-nacos/consumer/src/main/resources/application.yml b/demo/demo-nacos/consumer/src/main/resources/application.yml new file mode 100644 index 00000000000..ce6025722a5 --- /dev/null +++ b/demo/demo-nacos/consumer/src/main/resources/application.yml @@ -0,0 +1,35 @@ +# +## --------------------------------------------------------------------------- +## 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-nacos + version: 0.0.1 + name: consumer + registry: + nacos: + serverAddr: ${PAAS_CSE_NACOS_ENDPOINT:http://127.0.0.1:8848} + metadata: + group: red + + rest: + address: 0.0.0.0:9092 + + publicKey: + accessControl: + enabled: true + excludePathPatterns: '/*' diff --git a/demo/demo-nacos/consumer/src/main/resources/log4j2.xml b/demo/demo-nacos/consumer/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-nacos/consumer/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-nacos/gateway/pom.xml b/demo/demo-nacos/gateway/pom.xml new file mode 100644 index 00000000000..f76d407973a --- /dev/null +++ b/demo/demo-nacos/gateway/pom.xml @@ -0,0 +1,107 @@ + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-nacos + 3.4.0-SNAPSHOT + + + nacos-gateway + Java Chassis::Demo::NACOS::GATEWAY + jar + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + edge-core + + + org.apache.servicecomb + registry-nacos + + + + + + 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-nacos/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-nacos/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java new file mode 100644 index 00000000000..7d58caafd9d --- /dev/null +++ b/demo/demo-nacos/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-nacos/gateway/src/main/resources/application.yml b/demo/demo-nacos/gateway/src/main/resources/application.yml new file mode 100644 index 00000000000..3bf90e50b73 --- /dev/null +++ b/demo/demo-nacos/gateway/src/main/resources/application.yml @@ -0,0 +1,44 @@ +# +## --------------------------------------------------------------------------- +## 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-nacos + version: 0.0.1 + name: gateway + registry: + nacos: + enabled: true + serverAddr: ${PAAS_CSE_NACOS_ENDPOINT:http://127.0.0.1:8848} + + rest: + address: 0.0.0.0:9090?sslEnabled=false + + http: + dispatcher: + edge: + default: + enabled: false + url: + enabled: true + pattern: /(.*) + mappings: + consumer: + prefixSegmentCount: 0 + path: "/.*" + microserviceName: consumer + versionRule: 0.0.0+ diff --git a/demo/demo-nacos/gateway/src/main/resources/log4j2.xml b/demo/demo-nacos/gateway/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-nacos/gateway/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-nacos/pom.xml b/demo/demo-nacos/pom.xml new file mode 100644 index 00000000000..a37e292de1d --- /dev/null +++ b/demo/demo-nacos/pom.xml @@ -0,0 +1,61 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-parent + 3.4.0-SNAPSHOT + + demo-nacos + Java Chassis::Demo::NACOS + 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-nacos/provider/pom.xml b/demo/demo-nacos/provider/pom.xml new file mode 100644 index 00000000000..a23bc1bb06f --- /dev/null +++ b/demo/demo-nacos/provider/pom.xml @@ -0,0 +1,108 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-nacos + 3.4.0-SNAPSHOT + + + nacos-provider + Java Chassis::Demo::NACOS::PROVIDER + jar + + + + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + registry-nacos + + + + + + + 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-nacos/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java b/demo/demo-nacos/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java new file mode 100644 index 00000000000..a4475d80bda --- /dev/null +++ b/demo/demo-nacos/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.IHeaderParamWithListSchema; +import org.apache.servicecomb.provider.rest.common.RestSchema; + +@RestSchema(schemaId = "HeaderParamWithListSchema", schemaInterface = IHeaderParamWithListSchema.class) +public class HeaderParamWithListSchema implements IHeaderParamWithListSchema { + @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-nacos/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-nacos/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java new file mode 100644 index 00000000000..fde6f36b2e3 --- /dev/null +++ b/demo/demo-nacos/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.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 ProviderApplication { + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ProviderApplication.class).run(args); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/demo/demo-nacos/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-nacos/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java new file mode 100644 index 00000000000..0076440d232 --- /dev/null +++ b/demo/demo-nacos/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java @@ -0,0 +1,38 @@ +/* + * 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.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@RestSchema(schemaId = "ProviderController") +@RequestMapping(path = "/") +public class ProviderController { + // a very simple service to echo the request parameter + @GetMapping("/sayHello") + public String sayHello(@RequestParam("name") String name) { + return "Hello " + name; + } + + @GetMapping("/authIncludePath") + public String authIncludePath() { + return "success."; + } +} diff --git a/demo/demo-nacos/provider/src/main/resources/application.yml b/demo/demo-nacos/provider/src/main/resources/application.yml new file mode 100644 index 00000000000..ae6e029b701 --- /dev/null +++ b/demo/demo-nacos/provider/src/main/resources/application.yml @@ -0,0 +1,42 @@ +# +## --------------------------------------------------------------------------- +## 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-nacos + version: 0.0.1 + name: provider + registry: + nacos: + enabled: true + serverAddr: ${PAAS_CSE_NACOS_ENDPOINT:http://127.0.0.1:8848} + metadata: + group: green + + rest: + address: 0.0.0.0:9094 + + publicKey: + accessControl: + enabled: true + includePathPatterns: '/authIncludePath' + black: + authPath: + category: property + propertyName: serviceName + rule: consumer* diff --git a/demo/demo-nacos/provider/src/main/resources/log4j2.xml b/demo/demo-nacos/provider/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-nacos/provider/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-nacos/test-client/pom.xml b/demo/demo-nacos/test-client/pom.xml new file mode 100644 index 00000000000..103aeb24d94 --- /dev/null +++ b/demo/demo-nacos/test-client/pom.xml @@ -0,0 +1,200 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-nacos + 3.4.0-SNAPSHOT + + + nacos-test-client + Java Chassis::Demo::NACOS::TEST-CLIENT + jar + + + + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb.demo + demo-schema + + + org.apache.servicecomb + registry-local + + + + + + docker + + + + + io.fabric8 + docker-maven-plugin + + + + nacos/nacos-server:v2.1.2-slim + nacos-server + + alias + + standalone + hostname + + + Tomcat started on port + + + 8848 + + + + + + nacos-server.port:8848 + + + + + nacos-provider:${project.version} + nacos-provider + + alias + + + -Dservicecomb.registry.nacos.serverAddr=http://nacos-server:8848 + + /maven/maven/nacos-provider-${project.version}.jar + + + nacos-server:nacos-server + + + Nacos is ready + + + 9094 + + + + + + 9094:9094 + + + + + nacos-consumer:${project.version} + nacos-consumer + + alias + + + -Dservicecomb.registry.nacos.serverAddr=http://nacos-server:8848 + + /maven/maven/nacos-consumer-${project.version}.jar + + + nacos-server:nacos-server + + + Nacos is ready + + + 9092 + + + + + + 9092:9092 + + + + + nacos-gateway:${project.version} + nacos-gateway + + alias + + + -Dservicecomb.registry.nacos.serverAddr=http://nacos-server:8848 + + /maven/maven/nacos-gateway-${project.version}.jar + + + nacos-server:nacos-server + + + Nacos 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-nacos/test-client/src/main/java/org/apache/servicecomb/samples/Config.java b/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/Config.java new file mode 100644 index 00000000000..2e9105cdd4a --- /dev/null +++ b/demo/demo-nacos/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-nacos/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java b/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java new file mode 100644 index 00000000000..1b129acc2c6 --- /dev/null +++ b/demo/demo-nacos/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-nacos/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java new file mode 100644 index 00000000000..ad9460753a8 --- /dev/null +++ b/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.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 org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.springframework.stereotype.Component; +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(); + testAuthIncludePath(); + } + + private void testHelloWorld() { + String result = template + .getForObject(Config.GATEWAY_URL + "/sayHello?name=World", String.class); + TestMgr.check("Hello World", result); + } + + private void testAuthIncludePath() { + String result = ""; + try { + result = template.getForObject(Config.GATEWAY_URL + "/authIncludePath", String.class); + } catch (Exception e) { + result = "failed"; + } + TestMgr.check("failed", result); + } +} diff --git a/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java new file mode 100644 index 00000000000..26a2a491bbe --- /dev/null +++ b/demo/demo-nacos/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java @@ -0,0 +1,49 @@ +/* + * 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.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class TestClientApplication { + private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(TestClientApplication.class).run(args); + + run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("consumer"); + } +} diff --git a/demo/demo-nacos/test-client/src/main/resources/application.yml b/demo/demo-nacos/test-client/src/main/resources/application.yml new file mode 100644 index 00000000000..2e8b29356b3 --- /dev/null +++ b/demo/demo-nacos/test-client/src/main/resources/application.yml @@ -0,0 +1,25 @@ +# +## --------------------------------------------------------------------------- +## 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-nacos + name: test-client + version: 0.0.1 + + rest: + address: 0.0.0.0:9097 # should be same with server.port to use web container diff --git a/demo/demo-nacos/test-client/src/main/resources/log4j2.xml b/demo/demo-nacos/test-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-nacos/test-client/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-nacos/test-client/src/test/java/org/apache/servicecomb/samples/NocasIT.java b/demo/demo-nacos/test-client/src/test/java/org/apache/servicecomb/samples/NocasIT.java new file mode 100644 index 00000000000..bc7b5a6b9ba --- /dev/null +++ b/demo/demo-nacos/test-client/src/test/java/org/apache/servicecomb/samples/NocasIT.java @@ -0,0 +1,43 @@ +/* + * 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.TestMgr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = TestClientApplication.class) +public class NocasIT { + + @BeforeEach + public void setUp() { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() throws Exception { + TestClientApplication.run(); + + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/demo-pojo/pojo-client/pom.xml b/demo/demo-pojo/pojo-client/pom.xml index 9e79b4ddbc9..582c8c8f511 100644 --- a/demo/demo-pojo/pojo-client/pom.xml +++ b/demo/demo-pojo/pojo-client/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-pojo - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT pojo-client Java Chassis::Demo::POJO::Client @@ -32,10 +32,6 @@ org.apache.servicecomb.demo demo-schema - - org.apache.servicecomb - provider-pojo - org.apache.servicecomb metrics-core @@ -50,32 +46,7 @@ org.apache.servicecomb.demo.pojo.client.PojoClient - - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - + docker @@ -83,6 +54,83 @@ pojo-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/BeanRpcTest.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/BeanRpcTest.java index 69e7f0cbba2..caadd95efe7 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/BeanRpcTest.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/BeanRpcTest.java @@ -20,7 +20,7 @@ import org.apache.servicecomb.provider.pojo.RpcReference; public class BeanRpcTest { - @RpcReference(microserviceName = "pojo") + @RpcReference(microserviceName = "pojo", schemaId = "server") private Test test; public BeanRpcTest() { @@ -28,27 +28,25 @@ public BeanRpcTest() { } public void init() { - new Thread() { - public void run() { - while (true) { + new Thread(() -> { + while (true) { + try { + System.out.println("XXXXXXXXXXXXXXXXXXXXXXXX" + test.getTestString(null)); + break; + } catch (Exception e) { + e.printStackTrace(); try { - System.out.println("XXXXXXXXXXXXXXXXXXXXXXXX" + test.getTestString(null)); - break; - } catch (Exception e) { - e.printStackTrace(); - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - continue; - } catch (Throwable e) { - System.out.println("XXXXXXXXXXXXXXXXXXXXXXXX: teset case error"); - e.printStackTrace(); - System.exit(0); + Thread.sleep(1000); + } catch (InterruptedException e1) { + e1.printStackTrace(); } + continue; + } catch (Throwable e) { + System.out.println("XXXXXXXXXXXXXXXXXXXXXXXX: teset case error"); + e.printStackTrace(); + System.exit(0); } } - }.start(); + }).start(); } } diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/ClientInterfaceForServerTest.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/ClientInterfaceForServerTest.java new file mode 100644 index 00000000000..34399d081d1 --- /dev/null +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/ClientInterfaceForServerTest.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.pojo.client; + +import org.apache.servicecomb.demo.server.TestRequest; +import org.apache.servicecomb.demo.server.User; + +public interface ClientInterfaceForServerTest { + User splitParam(int nameNotIndex, User user); + + User wrapParam(TestRequest nameNotRequest); +} diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClient.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClient.java index dbc1bc2eb1e..601901e5884 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClient.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClient.java @@ -94,7 +94,7 @@ private void testCodeFirstCompletableFuture(CodeFirstPojoIntf codeFirst) { return; } - Vertx vertx = VertxUtils.getOrCreateVertxByName("transport", null); + Vertx vertx = VertxUtils.getOrCreateVertxByName("transport", null, null); CountDownLatch latch = new CountDownLatch(1); // vertx.runOnContext in normal thread is not a good practice // here just a test, not care for this. @@ -107,7 +107,9 @@ private void testCodeFirstCompletableFuture(CodeFirstPojoIntf codeFirst) { .thenCompose(result -> { TestMgr.check("someone sayhi, context k: v", result); - TestMgr.check(true, context == ContextUtils.getInvocationContext()); + // new call need set invocation context implicitly or will not + // inherit parent context + ContextUtils.setInvocationContext(context); return ((CodeFirstPojoClientIntf) codeFirst).sayHiAsync("someone 1"); }) diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java index 0d19638f2a1..0f4b6586163 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/CodeFirstPojoClientIntf.java @@ -20,10 +20,10 @@ import org.apache.servicecomb.demo.CodeFirstPojoIntf; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; public interface CodeFirstPojoClientIntf extends CodeFirstPojoIntf { - @ApiOperation(nickname = "sayHi", value = "") + @Operation(operationId = "sayHi", summary = "") CompletableFuture sayHiAsync(String name); String sayHi2(String name); diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java index 3b69ad036d8..03fafced0ae 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClient.java @@ -18,7 +18,6 @@ package org.apache.servicecomb.demo.pojo.client; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -26,71 +25,63 @@ import java.util.concurrent.ForkJoinPool; import java.util.stream.IntStream; -import javax.inject.Inject; - -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; import org.apache.servicecomb.demo.CategorizedTestCaseRunner; import org.apache.servicecomb.demo.DemoConst; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.server.Test; -import org.apache.servicecomb.demo.server.TestRequest; import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.demo.smartcare.Application; import org.apache.servicecomb.demo.smartcare.Group; import org.apache.servicecomb.demo.smartcare.SmartCare; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ImportResource; -@Component +@SpringBootApplication +@ImportResource(value = "classpath*:META-INF/spring/*.bean.xml") public class PojoClient { private static final Logger LOGGER = LoggerFactory.getLogger(PojoClient.class); - public static final byte buffer[] = new byte[1024]; - // reference a not exist a microservice, and never use it // this should not cause problems @RpcReference(microserviceName = "notExist") public static Test notExist; - @RpcReference(microserviceName = "pojo") + @RpcReference(microserviceName = "pojo", schemaId = "server") public static Test test; public static Test testFromXml; private static SmartCare smartcare; - static { - Arrays.fill(buffer, (byte) 1); - } - public static void setTestFromXml(Test testFromXml) { PojoClient.testFromXml = testFromXml; } public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + new SpringApplicationBuilder(PojoClient.class).web(WebApplicationType.NONE).run(args); try { run(); - } catch (Exception e) { + } catch (Throwable e) { TestMgr.check("success", "failed"); LOGGER.error("-------------- test failed -------------"); LOGGER.error("", e); LOGGER.error("-------------- test failed -------------"); } - TestMgr.summary(); + LOGGER.info("-------------- last time updated checks(maybe more/less): 785 -------------"); } private static void testContextClassLoaderIsNull() throws Exception { @@ -114,20 +105,12 @@ public static void run() throws Exception { String microserviceName = "pojo"; for (String transport : DemoConst.transports) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); TestMgr.setMsg(microserviceName, transport); LOGGER.info("test {}, transport {}", microserviceName, transport); testContextClassLoaderIsNull(); testNull(testFromXml); - testNull(test); - - // This test case shows destroy of WeightedResponseTimeRule timer task. after test finished will not print: - // "Weight adjusting job started" and thread "NFLoadBalancer-serverWeightTimer-unknown" destroyed. - ArchaiusUtils.setProperty("servicecomb.loadbalance.strategy.name", "WeightedResponse"); - testStringArray(test); - ArchaiusUtils.setProperty("servicecomb.loadbalance.strategy.name", "RoundRobin"); - testStringArray(test); boolean checkerDestroyed = true; // Timer cancel may not destroy thread very fast so check for 3 times. @@ -143,41 +126,22 @@ public static void run() throws Exception { } TestMgr.check(checkerDestroyed, true); - testChinese(test); - testStringHaveSpace(test); - testWrapParam(test); - testSplitParam(test); - testInputArray(test); - - testException(test); - testSmartCare(smartcare); testCommonInvoke(transport); if ("rest".equals(transport)) { testTraceIdOnNotSetBefore(); - testNullRest(test); - testExceptionRest(test); - testEmptyRest(test); - } else if ("highway".equals(transport)) { - testNullHighway(test); - testEmptyHighway(test); } - testTraceIdOnContextContainsTraceId(); } } private static void testHttpClientsIsOk() { - TestMgr.check(HttpClients.getClient("registry") != null, true); - TestMgr.check(HttpClients.getClient("registry-watch") != null, false); TestMgr.check(HttpClients.getClient("config-center") != null, false); TestMgr.check(HttpClients.getClient("http-transport-client") != null, false); TestMgr.check(HttpClients.getClient("http2-transport-client") != null, true); - TestMgr.check(HttpClients.getClient("registry", false) != null, true); - TestMgr.check(HttpClients.getClient("registry-watch", false) != null, false); TestMgr.check(HttpClients.getClient("config-center", false) != null, false); TestMgr.check(HttpClients.getClient("http-transport-client", false) != null, false); TestMgr.check(HttpClients.getClient("http2-transport-client", false) != null, true); @@ -194,7 +158,7 @@ private static void testTraceIdOnNotSetBefore() { private static void testTraceIdOnContextContainsTraceId() { InvocationContext context = new InvocationContext(); - context.addContext(Const.TRACE_ID_NAME, String.valueOf(Long.MIN_VALUE)); + context.addContext(CoreConst.TRACE_ID_NAME, String.valueOf(Long.MIN_VALUE)); ContextUtils.setInvocationContext(context); String traceId = test.testTraceId(); TestMgr.check(String.valueOf(Long.MIN_VALUE), traceId); @@ -220,131 +184,34 @@ private static void testSmartCare(SmartCare smartCare) { smartCare.delApplication("app0")); } - private static void testExceptionRest(Test test) { - try { - test.testException(456); - } catch (InvocationException e) { - TestMgr.check("456 error", e.getErrorData()); - } - - try { - test.testException(556); - } catch (InvocationException e) { - TestMgr.check("[556 error]", e.getErrorData()); - } - - try { - test.testException(557); - } catch (InvocationException e) { - TestMgr.check("[[557 error]]", e.getErrorData()); - } - } - - private static void testException(Test test) { - try { - test.testException(456); - } catch (InvocationException e) { - TestMgr.check("456 error", e.getErrorData()); - } - - try { - test.testException(556); - } catch (InvocationException e) { - TestMgr.check("[556 error]", e.getErrorData()); - } - - try { - test.testException(557); - } catch (InvocationException e) { - TestMgr.check("[[557 error]]", e.getErrorData()); - } - } - - private static void testInputArray(Test test) { - String result = test.addString(new String[] {"a", "b"}); - LOGGER.info("input array result:{}", result); - TestMgr.check("[a, b]", result); - } - - private static void testSplitParam(Test test) { - User result = test.splitParam(1, new User()); - LOGGER.info("split param result:{}", result); - TestMgr.check("User [name=nameA, users count:0, age=100, index=1]", result); - } - - @SuppressWarnings({"deprecation"}) + @SuppressWarnings("rawtypes") private static void testCommonInvoke(String transport) { Map arguments = new HashMap<>(); arguments.put("index", 2); arguments.put("user", new User()); - Object result = InvokerUtils.syncInvoke("pojo", "server", "splitParam", arguments); + Map warpArguments = new HashMap<>(); + warpArguments.put("splitParamBody", arguments); + User result = InvokerUtils.syncInvoke("pojo", "server", + "splitParam", warpArguments, User.class); TestMgr.check("User [name=nameA, users count:0, age=100, index=2]", result); arguments = new HashMap<>(); arguments.put("index", 3); arguments.put("user", new User()); + warpArguments = new HashMap<>(); + warpArguments.put("splitParamBody", arguments); result = InvokerUtils.syncInvoke("pojo", - "0.0.4", transport, "server", "splitParam", - arguments); + warpArguments, User.class); TestMgr.check("User [name=nameA, users count:0, age=100, index=3]", result); } - private static void testEmptyHighway(Test test) { - TestMgr.check("code is ''", test.getTestString("")); - } - - private static void testEmptyRest(Test test) { - TestMgr.check("code is ''", test.getTestString("")); - } - - private static void testNullRest(Test test) { - TestMgr.check(null, test.wrapParam(null)); - } - - private static void testNullHighway(Test test) { - TestMgr.check("nameA", test.wrapParam(null).getName()); - } - private static void testNull(Test test) { TestMgr.check("code is 'null'", test.getTestString(null)); TestMgr.check(null, test.postTestStatic(2)); TestMgr.check(null, test.patchTestStatic(2)); } - - private static void testChinese(Test test) { - TestMgr.check("code is '测试'", test.getTestString("测试")); - - User user = new User(); - user.setName("名字"); - User result = test.splitParam(1, user); - TestMgr.check("名字, users count:0", result.getName()); - } - - private static void testStringHaveSpace(Test test) { - TestMgr.check("code is 'a b'", test.getTestString("a b")); - } - - private static void testStringArray(Test test) { - // TestMgr.check("arr is '[a, , b]'", test.testStringArray(new String[] {"a", null, "b"})); - TestMgr.check("arr is '[a, b]'", test.testStringArray(new String[] {"a", "b"})); - } - - private static void testWrapParam(Test test) { - User user = new User(); - - TestRequest request = new TestRequest(); - request.setUser(user); - request.setIndex(0); - request.setData(buffer); - request.getUsers().add(user); - - User result = test.wrapParam(request); - LOGGER.info("wrap param result:{}", result); - - TestMgr.check("User [name=nameA, users count:1, age=100, index=0]", result); - } } diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestFlowControl.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestFlowControl.java index abcd772044c..c076c167297 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestFlowControl.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestFlowControl.java @@ -25,6 +25,7 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; @@ -44,35 +45,37 @@ interface Client { @Override public void testAllTransport() throws Exception { - testFlowControl((num) -> client1.foo(num), true); - testFlowControl((num) -> client1.bar(num), false); - testFlowControl((num) -> client2.foo(num), true); - testFlowControl((num) -> client2.bar(num), false); + testFlowControl((num) -> client1.foo(num), "provider", true); + testFlowControl((num) -> client1.bar(num), "provider", false); + testFlowControl((num) -> client2.foo(num), "consumer", true); + testFlowControl((num) -> client2.bar(num), "consumer", false); } - private void testFlowControl(Function function, boolean expected) throws InterruptedException { + private void testFlowControl(Function function, String role, boolean expected) + throws InterruptedException { AtomicBoolean failed = new AtomicBoolean(false); CountDownLatch countDownLatch = new CountDownLatch(10); for (int i = 0; i < 10; i++) { - new Thread() { - public void run() { - for (int i = 0; i < 10; i++) { - try { - int result = function.apply(10); - if (result != 10) { - TestMgr.failed("", new Exception("not expected")); - } - } catch (InvocationException e) { - TestMgr.check(e.getStatusCode(), 429); - TestMgr.check(e.getMessage(), - "InvocationException: code=429;msg=CommonExceptionData [message=rejected by qps flowcontrol]"); - failed.set(true); - break; + new Thread(() -> { + for (int i1 = 0; i1 < 10; i1++) { + try { + int result = function.apply(10); + if (result != 10) { + TestMgr.failed("", new Exception("not expected")); } + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 429); + TestMgr.check(((CommonExceptionData) e.getErrorData()).getMessage(), + role + " request rejected by flow control."); + failed.set(true); + break; + } catch (Throwable e) { + e.printStackTrace(); + TestMgr.fail("not expected error " + e.getMessage()); } - countDownLatch.countDown(); } - }.start(); + countDownLatch.countDown(); + }).start(); } countDownLatch.await(10, TimeUnit.SECONDS); TestMgr.check(expected, failed.get()); diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestNotRecommendedService.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestNotRecommendedService.java index b1771fac635..59d9a8f92b3 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestNotRecommendedService.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestNotRecommendedService.java @@ -53,9 +53,10 @@ private void testWrappedModel() { data.put(100L, model); List data2 = new ArrayList<>(); + AbstractModel model2 = new DefaultAbstractModel(); model2.setName("hello"); - data2.add(model); + data2.add(model2); WrappedAbstractModel input = new WrappedAbstractModel(); input.setMapModel(data); diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestRpcReferenceMethodInjection.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestRpcReferenceMethodInjection.java new file mode 100644 index 00000000000..92308e6b6cd --- /dev/null +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestRpcReferenceMethodInjection.java @@ -0,0 +1,47 @@ +/* + * 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.demo.pojo.client; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class TestRpcReferenceMethodInjection implements CategorizedTestCase { + + private SchemeInterfacePojo pojo; + + private SchemeInterfacePojo pojoValue; + + @RpcReference(microserviceName = "pojo", schemaId = "SchemeInterfacePojoImpl") + public void setSchemeInterfacePojo(SchemeInterfacePojo pojo) { + this.pojo = pojo; + } + + @RpcReference(microserviceName = "${servicecomb.provider.name}", schemaId = "SchemeInterfacePojoImpl") + public void setSchemeInterfacePojoValue(SchemeInterfacePojo pojoValue) { + this.pojoValue = pojoValue; + } + + @Override + public void testAllTransport() throws Exception { + TestMgr.check(-1, pojo.reduce(1, 2)); + TestMgr.check(-1, pojoValue.reduce(1, 2)); + } +} diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSameService.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSameService.java index 4f36b58f12e..0f735af07c4 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSameService.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSameService.java @@ -22,28 +22,29 @@ import org.apache.servicecomb.provider.pojo.RpcReference; import org.springframework.stereotype.Component; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.servers.Server; @Component public class TestSameService implements CategorizedTestCase { - @SwaggerDefinition(basePath = "/SameInterface1") + @OpenAPIDefinition(servers = {@Server(url = "/SameInterface1")}) public interface SameInterface1 { - public String sayHello(String name); + String sayHello(String name); } - @SwaggerDefinition(basePath = "/SameInterface2") + @OpenAPIDefinition(servers = {@Server(url = "/SameInterface2")}) public interface SameInterface2 { - public String sayHello(String name); + String sayHello(String name); } - @SwaggerDefinition(basePath = "/SameService1") + @OpenAPIDefinition(servers = {@Server(url = "/SameService1")}) public interface SameService1 { - public String sayHello(String name); + String sayHello(String name); } - @SwaggerDefinition(basePath = "/SameService2") + @OpenAPIDefinition(servers = {@Server(url = "/SameService2")}) public interface SameService2 { - public String sayHello(String name); + String sayHello(String name); } @RpcReference(microserviceName = "pojo", schemaId = "SameService1") diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterface.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterface.java index 98c8fdd71dd..7866c3add94 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterface.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterface.java @@ -20,6 +20,8 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; @Component @@ -34,12 +36,11 @@ public void testAllTransport() throws Exception { try { pojo.echoError("hello"); TestMgr.failed("should throw exception", new Exception()); - } catch (Exception e) { + } catch (InvocationException e) { TestMgr.check( "Consumer method org.apache.servicecomb.demo.pojo.client.SchemaInterface:" - + "echoError not exist in contract, microserviceName=pojo, " - + "schemaId=SchemaInterface; new producer not running or not deployed.", - e.getMessage()); + + "echoError not exist in contract, microserviceName=pojo, schemaId=SchemaInterface.", + ((CommonExceptionData) e.getErrorData()).getMessage()); } } } diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java index cd51640c145..18eb0db47db 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestSchemeInterfacePojo.java @@ -20,6 +20,8 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; @Component @@ -34,12 +36,12 @@ public void testAllTransport() throws Exception { try { pojo.add(1, 2); TestMgr.failed("should throw exception", new Exception()); - } catch (Exception e) { + } catch (InvocationException e) { TestMgr.check( "Consumer method org.apache.servicecomb.demo.pojo.client.SchemeInterfacePojo:" + "add not exist in contract, microserviceName=pojo, " - + "schemaId=SchemeInterfacePojoImpl; new producer not running or not deployed.", - e.getMessage()); + + "schemaId=SchemeInterfacePojoImpl.", + ((CommonExceptionData) e.getErrorData()).getMessage()); } } } diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestTestImpl.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestTestImpl.java new file mode 100644 index 00000000000..8b8fabde08e --- /dev/null +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestTestImpl.java @@ -0,0 +1,196 @@ +/* + * 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.demo.pojo.client; + +import java.util.Arrays; + +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.server.Test; +import org.apache.servicecomb.demo.server.TestRequest; +import org.apache.servicecomb.demo.server.User; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class TestTestImpl implements CategorizedTestCase { + private static final Logger LOGGER = LoggerFactory.getLogger(TestTestImpl.class); + + private static final byte[] buffer = new byte[1024]; + + static { + Arrays.fill(buffer, (byte) 1); + } + + @RpcReference(microserviceName = "pojo", schemaId = "server") + private Test test; + + @Override + public void testAllTransport() throws Exception { + testNull(test); + + // This test case shows destroy of WeightedResponseTimeRule timer task. after test finished will not print: + // "Weight adjusting job started" and thread "NFLoadBalancer-serverWeightTimer-unknown" destroyed. + InMemoryDynamicPropertiesSource.update("servicecomb.loadbalance.strategy.name", "WeightedResponse"); + testStringArray(test); + InMemoryDynamicPropertiesSource.update("servicecomb.loadbalance.strategy.name", "RoundRobin"); + testStringArray(test); + + testChinese(test); + testStringHaveSpace(test); + testWrapParam(test); + + testSplitParam(test); + testInputArray(test); + + testException(test); + + testIntArray(test); + } + + @Override + public void testRestTransport() throws Exception { + testNullRest(test); + testExceptionRest(test); + testEmptyRest(test); + } + + @Override + public void testHighwayTransport() throws Exception { + testNullHighway(test); + testEmptyHighway(test); + } + + private static void testIntArray(Test test) { + int[] request = new int[] {5, 11, 4}; + int[] result = test.testIntArray(request); + TestMgr.check(request.length, result.length); + TestMgr.check(request[1], result[1]); + } + + private static void testEmptyHighway(Test test) { + TestMgr.check("code is ''", test.getTestString("")); + } + + private static void testEmptyRest(Test test) { + TestMgr.check("code is ''", test.getTestString("")); + } + + private static void testNullRest(Test test) { + TestMgr.check(null, test.wrapParam(null)); + } + + private static void testNullHighway(Test test) { + TestMgr.check("nameA", test.wrapParam(null).getName()); + } + + private static void testNull(Test test) { + TestMgr.check("code is 'null'", test.getTestString(null)); + TestMgr.check(null, test.postTestStatic(2)); + TestMgr.check(null, test.patchTestStatic(2)); + } + + private static void testChinese(Test test) { + TestMgr.check("code is '测试'", test.getTestString("测试")); + + User user = new User(); + user.setName("名字"); + User result = test.splitParam(1, user); + TestMgr.check("名字, users count:0", result.getName()); + } + + private static void testStringHaveSpace(Test test) { + TestMgr.check("code is 'a b'", test.getTestString("a b")); + } + + private static void testStringArray(Test test) { + // TestMgr.check("arr is '[a, , b]'", test.testStringArray(new String[] {"a", null, "b"})); + TestMgr.check("arr is '[a, b]'", test.testStringArray(new String[] {"a", "b"})); + } + + private static void testWrapParam(Test test) { + User user = new User(); + + TestRequest request = new TestRequest(); + request.setUser(user); + request.setIndex(0); + request.setData(buffer); + request.getUsers().add(user); + + User result = test.wrapParam(request); + LOGGER.info("wrap param result:{}", result); + + TestMgr.check("User [name=nameA, users count:1, age=100, index=0]", result); + } + + + private static void testExceptionRest(Test test) { + try { + test.testException(456); + } catch (InvocationException e) { + TestMgr.check("456 error", e.getErrorData()); + } + + try { + test.testException(556); + } catch (InvocationException e) { + TestMgr.check("[556 error]", e.getErrorData()); + } + + try { + test.testException(557); + } catch (InvocationException e) { + TestMgr.check("[[557 error]]", e.getErrorData()); + } + } + + private static void testException(Test test) { + try { + test.testException(456); + } catch (InvocationException e) { + TestMgr.check("456 error", e.getErrorData()); + } + + try { + test.testException(556); + } catch (InvocationException e) { + TestMgr.check("[556 error]", e.getErrorData()); + } + + try { + test.testException(557); + } catch (InvocationException e) { + TestMgr.check("[[557 error]]", e.getErrorData()); + } + } + + private static void testInputArray(Test test) { + String result = test.addString(new String[] {"a", "b"}); + LOGGER.info("input array result:{}", result); + TestMgr.check("[a, b]", result); + } + + private static void testSplitParam(Test test) { + User result = test.splitParam(1, new User()); + LOGGER.info("split param result:{}", result); + TestMgr.check("User [name=nameA, users count:0, age=100, index=1]", result); + } +} diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java index 8b1e62038cb..eefc0fd1137 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/TestWeakPojo.java @@ -178,7 +178,6 @@ private void testGenerics() { TestMgr.check("hello", nameListResult.get(0).get(0)); } - @SuppressWarnings({"deprecation"}) private void testDiffName() { TestMgr.check(7, diffNames.differentName(2, 3)); TestMgr.check(8, diffNames2.differentName(2, 3)); @@ -187,6 +186,7 @@ private void testDiffName() { args.put("y", 3); Map swaggerArgs = new HashMap<>(); swaggerArgs.put("differentNameBody", args); - TestMgr.check(7, InvokerUtils.syncInvoke("pojo", "WeakPojo", "differentName", swaggerArgs)); + TestMgr.check(7, InvokerUtils.syncInvoke("pojo", "WeakPojo", + "differentName", swaggerArgs, Integer.class)); } } diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/ClientModel.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/ClientModel.java index 52f4bd92ca8..fd699064d46 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/ClientModel.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/ClientModel.java @@ -36,4 +36,4 @@ public int getCode() { public void setCode(int code) { this.code = code; } -} \ No newline at end of file +} diff --git a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/TestInvokerEndpoint.java b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/TestInvokerEndpoint.java index ca74092662b..025e67a0b49 100644 --- a/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/TestInvokerEndpoint.java +++ b/demo/demo-pojo/pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/invoker/TestInvokerEndpoint.java @@ -27,7 +27,7 @@ import org.springframework.stereotype.Component; @Component -@SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) +@SuppressWarnings({"unchecked", "rawtypes"}) public class TestInvokerEndpoint implements CategorizedTestCase { @Override public void testRestTransport() throws Exception { @@ -52,18 +52,19 @@ private void testInvokerUtilsDiffModelHighway() throws Exception { model.setName("hello"); args.put("request", model); - Map result = (Map) InvokerUtils.syncInvoke("pojo", "0+", "highway", "InvokerEndpoint", "model", args); + Map result = InvokerUtils.syncInvoke("pojo", "highway", "InvokerEndpoint", + "model", args, Map.class); TestMgr.check(model.getCode(), result.get("code")); TestMgr.check(model.getName(), result.get("name")); ClientModel modelResult = InvokerUtils - .syncInvoke("pojo", "0+", "highway", "InvokerEndpoint", "model", args, ClientModel.class); + .syncInvoke("pojo", "highway", "InvokerEndpoint", "model", args, ClientModel.class); TestMgr.check(model.getCode(), modelResult.getCode()); TestMgr.check(model.getName(), modelResult.getName()); CountDownLatch countDownLatch = new CountDownLatch(1); InvokerUtils - .reactiveInvoke("pojo", "0+", "highway", "InvokerEndpoint", "model", args, ClientModel.class, response -> { + .reactiveInvoke("pojo", "highway", "InvokerEndpoint", "model", args, ClientModel.class, response -> { ClientModel reactiveResult = response.getResult(); TestMgr.check(model.getCode(), reactiveResult.getCode()); TestMgr.check(model.getName(), reactiveResult.getName()); @@ -80,17 +81,18 @@ private void testInvokerUtilsDiffModelRest() throws Exception { model.setName("hello"); args.put("request", model); - Map result = (Map) InvokerUtils.syncInvoke("pojo", "0+", "rest", "InvokerEndpoint", "model", args); + Map result = InvokerUtils.syncInvoke("pojo", "rest", "InvokerEndpoint", + "model", args, Map.class); TestMgr.check(model.getCode(), result.get("code")); TestMgr.check(model.getName(), result.get("name")); ClientModel modelResult = InvokerUtils - .syncInvoke("pojo", "0+", "rest", "InvokerEndpoint", "model", args, ClientModel.class); + .syncInvoke("pojo", "rest", "InvokerEndpoint", "model", args, ClientModel.class); TestMgr.check(model.getCode(), modelResult.getCode()); TestMgr.check(model.getName(), modelResult.getName()); CountDownLatch countDownLatch = new CountDownLatch(1); - InvokerUtils.reactiveInvoke("pojo", "0+", "rest", "InvokerEndpoint", "model", args, ClientModel.class, response -> { + InvokerUtils.reactiveInvoke("pojo", "rest", "InvokerEndpoint", "model", args, ClientModel.class, response -> { ClientModel reactiveResult = response.getResult(); TestMgr.check(model.getCode(), reactiveResult.getCode()); TestMgr.check(model.getName(), reactiveResult.getName()); @@ -107,7 +109,8 @@ private void testInvokerUtilsDiffModel() throws Exception { model.setName("hello"); args.put("request", model); - Map result = (Map) InvokerUtils.syncInvoke("pojo", "InvokerEndpoint", "model", args); + Map result = InvokerUtils.syncInvoke("pojo", "InvokerEndpoint", + "model", args, Map.class); TestMgr.check(model.getCode(), result.get("code")); TestMgr.check(model.getName(), result.get("name")); @@ -116,7 +119,8 @@ private void testInvokerUtilsDiffModel() throws Exception { TestMgr.check(model.getName(), modelResult.getName()); CountDownLatch countDownLatch = new CountDownLatch(1); - InvokerUtils.reactiveInvoke("pojo", "InvokerEndpoint", "model", args, ClientModel.class, response -> { + InvokerUtils.reactiveInvoke("pojo", "InvokerEndpoint", "model", args, + ClientModel.class, response -> { ClientModel reactiveResult = response.getResult(); TestMgr.check(model.getCode(), reactiveResult.getCode()); TestMgr.check(model.getName(), reactiveResult.getName()); @@ -133,7 +137,7 @@ private void testInvokerUtilsDiffModelMapArgs() throws Exception { model.put("name", "hello"); args.put("request", model); - Map result = (Map) InvokerUtils.syncInvoke("pojo", "InvokerEndpoint", "model", args); + Map result = InvokerUtils.syncInvoke("pojo", "InvokerEndpoint", "model", args, Map.class); TestMgr.check(model.get("code"), result.get("code")); TestMgr.check(model.get("name"), result.get("name")); diff --git a/demo/demo-pojo/pojo-client/src/main/resources/log4j2.xml b/demo/demo-pojo/pojo-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-pojo/pojo-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-pojo/pojo-client/src/main/resources/microservice.yaml b/demo/demo-pojo/pojo-client/src/main/resources/microservice.yaml index 3f68ea60a07..45c62dffcf1 100644 --- a/demo/demo-pojo/pojo-client/src/main/resources/microservice.yaml +++ b/demo/demo-pojo/pojo-client/src/main/resources/microservice.yaml @@ -15,27 +15,18 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: pojotest -service_description: - name: pojoClient - version: 0.0.1 servicecomb: service: - registry: + application: pojotest + name: pojoClient + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 - instance: - healthCheck: - interval: 2 - watch: false - empty: - protection: true rest.client.enabled: false # using only http2 swagger: disableDataTypeCheck: true - handler: - chain: - Consumer: - default: qps-flowcontrol-consumer,auth-consumer,bizkeeper-consumer,loadbalance + isolation: Consumer: enabled: false @@ -46,10 +37,13 @@ servicecomb: window_time: 12000 publisher.defaultLog.enabled: false # when in testing , can turn on flowcontrol: + enabled: true Consumer: qps: limit: pojo: FlowControlClientSchema: foo: 3 - bar: 3000 \ No newline at end of file + bar: 3000 + provider: + name: pojo diff --git a/demo/demo-pojo/pojo-client/src/test/java/org/apache/servicecomb/demo/pojo/PojoIT.java b/demo/demo-pojo/pojo-client/src/test/java/org/apache/servicecomb/demo/pojo/PojoIT.java index 8385ca03033..c0c4f7542c3 100644 --- a/demo/demo-pojo/pojo-client/src/test/java/org/apache/servicecomb/demo/pojo/PojoIT.java +++ b/demo/demo-pojo/pojo-client/src/test/java/org/apache/servicecomb/demo/pojo/PojoIT.java @@ -17,25 +17,28 @@ package org.apache.servicecomb.demo.pojo; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.pojo.client.PojoClient; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = PojoClient.class) public class PojoIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @Test public void clientGetsNoError() throws Exception { - PojoClient.main(new String[0]); + PojoClient.run(); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-pojo/pojo-server/pom.xml b/demo/demo-pojo/pojo-server/pom.xml index 9159d0dde69..b0b673ef47e 100644 --- a/demo/demo-pojo/pojo-server/pom.xml +++ b/demo/demo-pojo/pojo-server/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-pojo - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT pojo-server Java Chassis::Demo::POJO::Server @@ -32,33 +32,18 @@ org.apache.servicecomb.demo demo-schema - - org.apache.servicecomb - provider-pojo - org.apache.servicecomb.demo.pojo.server.PojoServer + true + - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -66,15 +51,51 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/CodeFirstPojo.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/CodeFirstPojo.java index 0beb9e6b4d9..680d7981d05 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/CodeFirstPojo.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/CodeFirstPojo.java @@ -32,11 +32,12 @@ import org.apache.servicecomb.provider.pojo.RpcSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.servers.Server; @RpcSchema() -@SwaggerDefinition(basePath = "/pojo/rest") +@OpenAPIDefinition(servers = {@Server(url = "/pojo/rest")}) public class CodeFirstPojo implements CodeFirstPojoIntf { @Override public ParseResponse parse(ParseRequest request) { @@ -128,7 +129,7 @@ public String sayHi(String name) { : ContextUtils.getInvocationContext().getContext("k")); } - @ApiOperation(nickname = "sayHi2", value = "") + @Operation(operationId = "sayHi2", summary = "") public CompletableFuture sayHi2Async(String name) { CompletableFuture future = new CompletableFuture<>(); future.complete(name + " sayhi 2"); @@ -140,10 +141,10 @@ public boolean isTrue() { } public String addString(List s) { - String result = ""; + StringBuilder result = new StringBuilder(); for (String x : s) { - result += x; + result.append(x); } - return result; + return result.toString(); } } diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/PojoServer.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/PojoServer.java index b13f18f166e..1ae04e578ee 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/PojoServer.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/PojoServer.java @@ -17,12 +17,19 @@ package org.apache.servicecomb.demo.pojo.server; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ImportResource; +@SpringBootApplication +@ImportResource(value = "classpath*:META-INF/spring/*.bean.xml") public class PojoServer { public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); + try { + new SpringApplicationBuilder(PojoServer.class).web(WebApplicationType.NONE).run(args); + } catch (Throwable e) { + e.printStackTrace(); + } } } diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java index be1bacab11d..230dfd804fe 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java @@ -20,7 +20,7 @@ import java.util.Arrays; import java.util.List; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.demo.server.Test; import org.apache.servicecomb.demo.server.TestRequest; import org.apache.servicecomb.demo.server.User; @@ -37,7 +37,7 @@ public String testStringArray(String[] arr) { @Override public String getTestString(String code) { - return String.format("code is '%s'", String.valueOf(code)); + return String.format("code is '%s'", code); } @Override @@ -103,6 +103,11 @@ public String addString(String[] strArr) { @Override public String testTraceId() { - return ContextUtils.getInvocationContext().getContext(Const.TRACE_ID_NAME); + return ContextUtils.getInvocationContext().getContext(CoreConst.TRACE_ID_NAME); + } + + @Override + public int[] testIntArray(int[] request) { + return request; } } diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java index fc82bf108ae..962952531d0 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/WeakPojo.java @@ -22,13 +22,13 @@ import org.apache.servicecomb.demo.server.GenericsModel; import org.apache.servicecomb.provider.pojo.RpcSchema; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; @RpcSchema(schemaId = "WeakPojo") public class WeakPojo { - @ApiOperation(value = "differentName", nickname = "differentName") - public int diffNames(@ApiParam(name = "x") int a, @ApiParam(name = "y") int b) { + @Operation(summary = "differentName", operationId = "differentName") + public int diffNames(@Parameter(name = "x") int a, @Parameter(name = "y") int b) { return a * 2 + b; } diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameInterface.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameInterface.java index d6d58e78194..340ddf355eb 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameInterface.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameInterface.java @@ -17,9 +17,10 @@ package org.apache.servicecomb.demo.pojo.server.same.pk1; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.servers.Server; -@SwaggerDefinition(basePath = "/SameInterface1") +@OpenAPIDefinition(servers = {@Server(url = "/SameInterface1")}) public interface SameInterface { - public String sayHello(String name); + String sayHello(String name); } diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameService.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameService.java index 08540e1b7a7..9a59104e99c 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameService.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk1/SameService.java @@ -20,11 +20,12 @@ import org.apache.servicecomb.provider.pojo.RpcSchema; import org.springframework.stereotype.Component; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.servers.Server; @RpcSchema(schemaId = "SameService1") @Component("SameService1") -@SwaggerDefinition(basePath = "/SameService1") +@OpenAPIDefinition(servers = {@Server(url = "/SameService1")}) public class SameService { public String sayHello(String name) { return "pk1-svc-" + name; diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameInterface.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameInterface.java index 45c99e059da..7410776ef65 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameInterface.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameInterface.java @@ -17,9 +17,10 @@ package org.apache.servicecomb.demo.pojo.server.same.pk2; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.servers.Server; -@SwaggerDefinition(basePath = "/SameInterface2") +@OpenAPIDefinition(servers = {@Server(url = "/SameInterface2")}) public interface SameInterface { - public String sayHello(String name); + String sayHello(String name); } diff --git a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameService.java b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameService.java index 6ebade7c012..38fc544681c 100644 --- a/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameService.java +++ b/demo/demo-pojo/pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/same/pk2/SameService.java @@ -20,11 +20,12 @@ import org.apache.servicecomb.provider.pojo.RpcSchema; import org.springframework.stereotype.Component; -import io.swagger.annotations.SwaggerDefinition; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.servers.Server; @RpcSchema(schemaId = "SameService2") @Component("SameService2") -@SwaggerDefinition(basePath = "/SameService2") +@OpenAPIDefinition(servers = {@Server(url = "/SameService2")}) public class SameService { public String sayHello(String name) { return "pk2-svc-" + name; diff --git a/demo/demo-pojo/pojo-server/src/main/resources/log4j2.xml b/demo/demo-pojo/pojo-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-pojo/pojo-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml b/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml index 4645aa097f3..0fe723a06ff 100644 --- a/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml +++ b/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml @@ -15,13 +15,13 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: pojotest -service_description: - name: pojo - version: 0.0.4 servicecomb: service: - registry: + application: pojotest + name: pojo + version: 0.0.4 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8080?protocol=http2 @@ -32,11 +32,9 @@ servicecomb: address: 0.0.0.0:7070 swagger: disableDataTypeCheck: true - handler: - chain: - Provider: - default: qps-flowcontrol-provider,auth-provider + flowcontrol: + enabled: true Provider: qps: limit: @@ -44,4 +42,3 @@ servicecomb: FlowControlSchema: foo: 3 bar: 3000 - diff --git a/demo/demo-pojo/pom.xml b/demo/demo-pojo/pom.xml index 361d79cd7a6..96217173a03 100644 --- a/demo/demo-pojo/pom.xml +++ b/demo/demo-pojo/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-pojo Java Chassis::Demo::POJO @@ -32,6 +32,10 @@ pojo-client + + org.apache.servicecomb + solution-basic + org.apache.servicecomb registry-service-center @@ -41,12 +45,20 @@ handler-publickey-auth - log4j - log4j + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-core diff --git a/demo/demo-register-url-prefix/README.md b/demo/demo-register-url-prefix/README.md index 416a098a41b..e0b2df4db0b 100644 --- a/demo/demo-register-url-prefix/README.md +++ b/demo/demo-register-url-prefix/README.md @@ -1,4 +1,4 @@ -This demo is an integration test for testing +This demo is an integration test for testing ```yaml servicecomb: @@ -7,7 +7,7 @@ servicecomb: registerUrlPrefix: true ``` -When this configuration is enabled, web context path is added to swagger, and consumer can +When this configuration is enabled, web context path is added to swagger, and consumer can invoke with context path ```yaml diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-client/pom.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-client/pom.xml index 5ac24a299db..1b7fc782cd1 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-client/pom.xml +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-client/pom.xml @@ -21,43 +21,22 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 demo-register-url-prefix-client - Java Chassis::Demo::Spring Boot::Transport::Register URL Prefix client + Java Chassis::Demo::Register URL Prefix client org.apache.servicecomb.demo demo-register-url-prefix - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.servicecomb.demo.prefix.Application - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - org.apache.servicecomb.demo demo-schema - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - @@ -66,6 +45,83 @@ demo-register-url-prefix-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/java/org/apache/servicecomb/demo/prefix/Application.java b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/java/org/apache/servicecomb/demo/prefix/Application.java index 3c7a03f309e..8b53c6c6bd4 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/java/org/apache/servicecomb/demo/prefix/Application.java +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/java/org/apache/servicecomb/demo/prefix/Application.java @@ -19,14 +19,12 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @SpringBootApplication -@EnableServiceComb public class Application { public static void main(final String[] args) throws Exception { new SpringApplicationBuilder().sources(Application.class).web(WebApplicationType.SERVLET).build().run(args); @@ -35,7 +33,7 @@ public static void main(final String[] args) throws Exception { } public static void runTest() { - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); TestMgr.check("2", template .getForObject("cse://demo-register-url-prefix-server/hellodemo/register/url/prefix/getName?name=2", String.class)); diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/application.yml b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/application.yml index 4516d6cd260..65b87064740 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/application.yml +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/application.yml @@ -18,17 +18,15 @@ server: port: 8082 -# java-chassis configurations - -APPLICATION_ID: demo-register-url-prefix -service_description: - name: demo-register-url-prefix-client - version: 0.0.1 servicecomb: service: - registry: + application: demo-register-url-prefix + name: demo-register-url-prefix-client + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 handler: chain: Consumer: - default: loadbalance \ No newline at end of file + default: loadbalance diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/log4j2.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/logback.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/test/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixIT.java b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/test/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixIT.java index 3ec07ca41db..e4ae70fad6c 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/test/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixIT.java +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-client/src/test/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixIT.java @@ -17,16 +17,14 @@ package org.apache.servicecomb.demo.prefix; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.boot.SpringApplication; public class RegisterUrlPrefixIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @@ -37,6 +35,6 @@ public void clientGetsNoError() throws Exception { Application.runTest(); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/pom.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-server/pom.xml index c1d079bb739..2d34ae62051 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/pom.xml +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-server/pom.xml @@ -21,11 +21,11 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 4.0.0 demo-register-url-prefix-server - Java Chassis::Demo::Spring Boot::Transport::Register URL Prefix Server + Java Chassis::Demo::Register URL Prefix Server org.apache.servicecomb.demo demo-register-url-prefix - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT @@ -33,22 +33,9 @@ - org.apache.servicecomb - registry-service-center + jakarta.ws.rs + jakarta.ws.rs-api - - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - - - org.apache.servicecomb - inspector - - @@ -56,19 +43,6 @@ org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -76,15 +50,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/AccessLogHandler.java b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/AccessLogHandler.java deleted file mode 100644 index 7f47b3e7ebc..00000000000 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/AccessLogHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.demo.prefix; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -// demonstrate access log using handler and using Invocation logger to log trace id -public class AccessLogHandler implements Handler { - private static final Logger LOGGER - = LoggerFactory.getLogger(AccessLogHandler.class); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - invocation.getTraceIdLogger().info(LOGGER, "request for operation {} begin", invocation.getInvocationQualifiedName()); - invocation.next((resp) -> { - invocation.getTraceIdLogger().info(LOGGER, "request for operation {} end", invocation.getInvocationQualifiedName()); - asyncResp.complete(resp); - }); - } -} diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/PrefixApplication.java b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/PrefixApplication.java index f92b8d39742..2fc02f7adbd 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/PrefixApplication.java +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/PrefixApplication.java @@ -17,13 +17,11 @@ package org.apache.servicecomb.demo.prefix; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class PrefixApplication { public static void main(final String[] args) throws Exception { new SpringApplicationBuilder().sources(PrefixApplication.class).web(WebApplicationType.SERVLET).build().run(args); diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixEndpoint.java b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixEndpoint.java index e383b0b8620..dae91a50f49 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixEndpoint.java +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/java/org/apache/servicecomb/demo/prefix/RegisterUrlPrefixEndpoint.java @@ -17,26 +17,21 @@ package org.apache.servicecomb.demo.prefix; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.ws.rs.core.MediaType; + @RestSchema(schemaId = "RegisterUrlPrefixEndpoint") @RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) public class RegisterUrlPrefixEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(RegisterUrlPrefixEndpoint.class); - @GetMapping(path = "/getName") public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); return name; } } diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/application.yml b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/application.yml index 81dcb3ee956..8a4140eeced 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/application.yml +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/application.yml @@ -20,21 +20,14 @@ server: context-path: /hellodemo port: 8080 -# java-chassis configurations - -APPLICATION_ID: demo-register-url-prefix -service_description: - name: demo-register-url-prefix-server - version: 0.0.1 servicecomb: service: - registry: + application: demo-register-url-prefix + name: demo-register-url-prefix-server + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 - registerUrlPrefix: true + registerUrlPrefix: true rest: address: 0.0.0.0:8080 - - handler: - chain: - Provider: - default: custom-access-log \ No newline at end of file diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/config/cse.handler.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/config/cse.handler.xml deleted file mode 100644 index f3950317880..00000000000 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/log4j2.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/logback.xml b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/logback.xml index 0d627f2a24d..cc214e46e64 100644 --- a/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/logback.xml +++ b/demo/demo-register-url-prefix/demo-register-url-prefix-server/src/main/resources/logback.xml @@ -17,27 +17,7 @@ --> - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - %d [%level] [%thread] - %msg (%F:%L\)%n @@ -45,6 +25,5 @@ - - \ No newline at end of file + diff --git a/demo/demo-register-url-prefix/pom.xml b/demo/demo-register-url-prefix/pom.xml index c740a6baaaf..e51630b5397 100644 --- a/demo/demo-register-url-prefix/pom.xml +++ b/demo/demo-register-url-prefix/pom.xml @@ -22,10 +22,10 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-register-url-prefix - Java Chassis::Demo::Spring Boot::Register URL Prefix + Java Chassis::Demo::Register URL Prefix pom demo-register-url-prefix-server @@ -33,6 +33,10 @@ + + org.apache.servicecomb + solution-basic + org.apache.servicecomb registry-service-center @@ -41,6 +45,18 @@ org.apache.servicecomb java-chassis-spring-boot-starter-servlet + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + org.apache.servicecomb foundation-test-scaffolding diff --git a/demo/demo-schema/pom.xml b/demo/demo-schema/pom.xml index 3fd831ffd1f..b17f345111b 100644 --- a/demo/demo-schema/pom.xml +++ b/demo/demo-schema/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-schema Java Chassis::Demo::Schema @@ -30,46 +30,13 @@ org.apache.servicecomb - handler-bizkeeper - - - org.apache.servicecomb - handler-loadbalance - - - org.apache.servicecomb - transport-highway - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - transport-rest-servlet - - - jakarta.servlet - jakarta.servlet-api - compile - - - org.apache.servicecomb - handler-flowcontrol-qps - - - org.apache.servicecomb - swagger-generator-springmvc + solution-basic org.apache.servicecomb foundation-test-scaffolding compile - - org.apache.servicecomb - inspector - diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CategorizedTestCaseRunner.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CategorizedTestCaseRunner.java index 47dd8b973bf..acb82190374 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CategorizedTestCaseRunner.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CategorizedTestCaseRunner.java @@ -19,8 +19,8 @@ import java.util.Map; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,17 +49,14 @@ public static void runCategorizedTestCase(String microserviceName) throws Except LOGGER.error("run categorized test case " + testCase.getClass().getName() + " failed.", e); - TestMgr.failed("run categorized test case " + - testCase.getClass().getName() + - " failed, reason " + e.getMessage(), - e); + throw e; } } } } public static void changeTransport(String microserviceName, String transport) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); TestMgr.setMsg(microserviceName, transport); } } diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java index b9dee8b5d2c..ee2bf395847 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CodeFirstRestTemplate.java @@ -21,40 +21,46 @@ import java.util.HashMap; import java.util.Map; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessorManager; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.demo.compute.Person; import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore; import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore; -import org.apache.servicecomb.demo.jaxbbean.JAXBJob; -import org.apache.servicecomb.demo.jaxbbean.JAXBPerson; import org.apache.servicecomb.demo.server.User; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.RegistrationManager; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.env.Environment; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; +import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; import io.vertx.core.json.JsonObject; public class CodeFirstRestTemplate { + protected Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + protected void changeTransport(String microserviceName, String transport) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); TestMgr.setMsg(microserviceName, transport); } - public void testCodeFirst(RestTemplate template, String microserviceName, String basePath) { + public void testCodeFirst(RestOperations template, String microserviceName, String basePath) { String cseUrlPrefix = "cse://" + microserviceName + basePath; changeTransport(microserviceName, "highway"); testOnlyHighway(template, cseUrlPrefix); - changeTransport(microserviceName, Const.RESTFUL); + changeTransport(microserviceName, CoreConst.RESTFUL); testOnlyRest(microserviceName, template, cseUrlPrefix); for (String transport : DemoConst.transports) { @@ -63,10 +69,9 @@ public void testCodeFirst(RestTemplate template, String microserviceName, String } } - protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) { + protected void testAllTransport(String microserviceName, RestOperations template, String cseUrlPrefix) { testCodeFirstUserMap(template, cseUrlPrefix); testCodeFirstTextPlain(template, cseUrlPrefix); - testCodeFirstAppXml(template, cseUrlPrefix); testCodeFirstBytes(template, cseUrlPrefix); testCseResponse(microserviceName, template, cseUrlPrefix); testCodeFirstAddDate(template, cseUrlPrefix); @@ -85,14 +90,13 @@ protected void testAllTransport(String microserviceName, RestTemplate template, testRawJson(template, cseUrlPrefix); } - protected void testOnlyHighway(RestTemplate template, String cseUrlPrefix) { + protected void testOnlyHighway(RestOperations template, String cseUrlPrefix) { } - protected void testOnlyRest(String microserviceName, RestTemplate template, String cseUrlPrefix) { + protected void testOnlyRest(String microserviceName, RestOperations template, String cseUrlPrefix) { testCodeFirstUserMap(template, cseUrlPrefix); testCodeFirstTextPlain(template, cseUrlPrefix); - testCodeFirstAppXml(template, cseUrlPrefix); testCodeFirstBytes(template, cseUrlPrefix); testCseResponse(microserviceName, template, cseUrlPrefix); testCodeFirstAddDate(template, cseUrlPrefix); @@ -105,7 +109,7 @@ protected void testOnlyRest(String microserviceName, RestTemplate template, Stri testTraceIdOnNotSetBefore(template, cseUrlPrefix); } - private void testCodeFirstUserMap(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstUserMap(RestOperations template, String cseUrlPrefix) { User user1 = new User(); user1.setNames(new String[] {"u1", "u2"}); @@ -116,10 +120,16 @@ private void testCodeFirstUserMap(RestTemplate template, String cseUrlPrefix) { userMap.put("u1", user1); userMap.put("u2", user2); - @SuppressWarnings("unchecked") - Map result = template.postForObject(cseUrlPrefix + "testUserMap", - userMap, - Map.class); + // TODO: shall we support this usage? Seams not valid, cause result should be Map and type not defined. +// @SuppressWarnings("unchecked") +// Map result = template.postForObject(cseUrlPrefix + "testUserMap", +// userMap, +// Map.class); + + Map result = template.exchange(cseUrlPrefix + "testUserMap", HttpMethod.POST, + new HttpEntity<>(userMap), + new ParameterizedTypeReference>() { + }).getBody(); TestMgr.check("u1", result.get("u1").getNames()[0]); TestMgr.check("u2", result.get("u1").getNames()[1]); @@ -127,7 +137,7 @@ private void testCodeFirstUserMap(RestTemplate template, String cseUrlPrefix) { TestMgr.check("u4", result.get("u2").getNames()[1]); } - private void testCodeFirstTextPlain(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstTextPlain(RestOperations template, String cseUrlPrefix) { String body = "a=1"; String result = template.postForObject(cseUrlPrefix + "textPlain", body, @@ -135,22 +145,7 @@ private void testCodeFirstTextPlain(RestTemplate template, String cseUrlPrefix) TestMgr.check(body, result); } - private void testCodeFirstAppXml(RestTemplate template, String cseUrlPrefix) { - JAXBPerson person = new JAXBPerson("jake", 22, "it", "60kg"); - person.setJob(new JAXBJob("developer", "coding")); - HttpHeaders headers = new HttpHeaders(); - headers.add("Accept", MediaType.APPLICATION_XML_VALUE); - headers.add("Content-Type", MediaType.APPLICATION_JSON_VALUE); - HttpEntity requestEntity = new HttpEntity<>(person, headers); - ResponseEntity resEntity = template.exchange(cseUrlPrefix + "appXml", - HttpMethod.POST, - requestEntity, - JAXBPerson.class); - TestMgr.check(-1, ProduceProcessorManager.INSTANCE.findProcessor(MediaType.APPLICATION_XML_VALUE, null).getOrder()); - TestMgr.check(person, resEntity.getBody()); - } - - private void testCodeFirstBytes(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstBytes(RestOperations template, String cseUrlPrefix) { byte[] body = new byte[] {0, 1, 2}; byte[] result = template.postForObject(cseUrlPrefix + "bytes", body, @@ -161,13 +156,13 @@ private void testCodeFirstBytes(RestTemplate template, String cseUrlPrefix) { TestMgr.check(2, result[2]); } - protected void checkStatusCode(String microserviceName, int expectStatusCode, HttpStatus httpStatus) { + protected void checkStatusCode(String microserviceName, int expectStatusCode, HttpStatusCode httpStatus) { TestMgr.check(expectStatusCode, httpStatus.value()); } - private void testCseResponse(String targetMicroserviceName, RestTemplate template, + private void testCseResponse(String targetMicroserviceName, RestOperations template, String cseUrlPrefix) { - String srcMicroserviceName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); + String srcMicroserviceName = BootStrapProperties.readServiceName(environment); ResponseEntity responseEntity = template.exchange(cseUrlPrefix + "cseResponse", HttpMethod.GET, null, User.class); @@ -177,7 +172,7 @@ private void testCseResponse(String targetMicroserviceName, RestTemplate templat checkStatusCode(targetMicroserviceName, 202, responseEntity.getStatusCode()); } - private void testCodeFirstAddDate(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstAddDate(RestOperations template, String cseUrlPrefix) { Map body = new HashMap<>(); Date date = new Date(); body.put("date", date); @@ -190,7 +185,7 @@ private void testCodeFirstAddDate(RestTemplate template, String cseUrlPrefix) { TestMgr.check(new Date(date.getTime() + seconds * 1000), result); } - private void testCodeFirstAddString(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstAddString(RestOperations template, String cseUrlPrefix) { ResponseEntity responseEntity = template.exchange(cseUrlPrefix + "addstring?s=a&s=b", HttpMethod.DELETE, @@ -199,25 +194,25 @@ private void testCodeFirstAddString(RestTemplate template, String cseUrlPrefix) TestMgr.check("ab", responseEntity.getBody()); } - private void testCodeFirstIsTrue(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstIsTrue(RestOperations template, String cseUrlPrefix) { boolean result = template.getForObject(cseUrlPrefix + "istrue", boolean.class); TestMgr.check(true, result); } - private void testCodeFirstSayHi2(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstSayHi2(RestOperations template, String cseUrlPrefix) { ResponseEntity responseEntity = template.exchange(cseUrlPrefix + "sayhi/{name}/v2", HttpMethod.PUT, null, String.class, "world"); TestMgr.check("world sayhi 2", responseEntity.getBody()); } - private void testCodeFirstSayHi(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstSayHi(RestOperations template, String cseUrlPrefix) { ResponseEntity responseEntity = template.exchange(cseUrlPrefix + "sayhi/{name}", HttpMethod.PUT, null, String.class, "world"); - TestMgr.check(202, responseEntity.getStatusCodeValue()); + TestMgr.check(202, responseEntity.getStatusCode().value()); TestMgr.check("world sayhi", responseEntity.getBody()); } - private void testCodeFirstSaySomething(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstSaySomething(RestOperations template, String cseUrlPrefix) { Person person = new Person(); person.setName("person name"); @@ -230,7 +225,7 @@ private void testCodeFirstSaySomething(RestTemplate template, String cseUrlPrefi TestMgr.check("prefix prefix person name", result); } - private void testCodeFirstSayHello(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstSayHello(RestOperations template, String cseUrlPrefix) { Map persionFieldMap = new HashMap<>(); persionFieldMap.put("name", "person name from map"); Person result = template.postForObject(cseUrlPrefix + "sayhello", persionFieldMap, Person.class); @@ -242,7 +237,7 @@ private void testCodeFirstSayHello(RestTemplate template, String cseUrlPrefix) { TestMgr.check("hello person name from Object", result); } - private void testCodeFirstAdd(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstAdd(RestOperations template, String cseUrlPrefix) { Map params = new HashMap<>(); params.put("a", "5"); params.put("b", "3"); @@ -251,7 +246,7 @@ private void testCodeFirstAdd(RestTemplate template, String cseUrlPrefix) { TestMgr.check(8, result); } - private void testCodeFirstReduce(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstReduce(RestOperations template, String cseUrlPrefix) { Map params = new HashMap<>(); params.put("a", "5"); @@ -264,7 +259,7 @@ private void testCodeFirstReduce(RestTemplate template, String cseUrlPrefix) { TestMgr.check(2, result.getBody()); } - private void testModelFieldIgnore(RestTemplate template, String cseUrlPrefix) { + private void testModelFieldIgnore(RestOperations template, String cseUrlPrefix) { InputModelForTestIgnore input = new InputModelForTestIgnore("input_id_rest", "input_id_content", new Person("inputSomeone"), new JsonObject("{\"InputJsonKey\" : \"InputJsonValue\"}"), () -> { }); @@ -284,22 +279,22 @@ private void testModelFieldIgnore(RestTemplate template, String cseUrlPrefix) { TestMgr.check(null, output.getOutputObject()); } - private void testRawJson(RestTemplate template, String cseUrlPrefix) { + private void testRawJson(RestOperations template, String cseUrlPrefix) { String input = "{\"name\" : \"zyy\"}"; String output = template.postForObject(cseUrlPrefix + "rawJsonAnnotation", input, String.class); TestMgr.check("hello zyy", output); } - private void testTraceIdOnNotSetBefore(RestTemplate template, String cseUrlPrefix) { + private void testTraceIdOnNotSetBefore(RestOperations template, String cseUrlPrefix) { String traceIdUrl = cseUrlPrefix + "traceId"; String result = template.getForObject(traceIdUrl, String.class); TestMgr.checkNotEmpty(result); } - private void testTraceIdOnContextContainsTraceId(RestTemplate template, String cseUrlPrefix) { + private void testTraceIdOnContextContainsTraceId(RestOperations template, String cseUrlPrefix) { String traceIdUrl = cseUrlPrefix + "traceId"; InvocationContext invocationContext = new InvocationContext(); - invocationContext.addContext(Const.TRACE_ID_NAME, String.valueOf(Long.MIN_VALUE)); + invocationContext.addContext(CoreConst.TRACE_ID_NAME, String.valueOf(Long.MIN_VALUE)); ContextUtils.setInvocationContext(invocationContext); String result = template.getForObject(traceIdUrl, String.class); TestMgr.check(String.valueOf(Long.MIN_VALUE), result); diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java index eef63ec006b..550f9e5adaf 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java @@ -22,7 +22,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; @RequestMapping("/CommonSchemaInterface") public interface CommonSchemaInterface { @@ -30,7 +30,7 @@ public interface CommonSchemaInterface { String testInvocationTimeout(@RequestParam("timeout") long timeout, @RequestParam("name") String name); @GetMapping(path = "testInvocationTimeoutWithInvocation") - @ApiOperation(value = "testInvocationTimeoutWithInvocation", nickname = "testInvocationTimeoutWithInvocation") + @Operation(summary = "testInvocationTimeoutWithInvocation", operationId = "testInvocationTimeoutWithInvocation") String testInvocationTimeout(InvocationContext context, @RequestParam("timeout") long timeout, @RequestParam("name") String name); diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoConst.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoConst.java index c76d4c81a33..84018a5254b 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoConst.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoConst.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.demo; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; public interface DemoConst { - String[] transports = new String[] {"highway", "rest", Const.ANY_TRANSPORT}; + String[] transports = new String[] {"rest", "highway", CoreConst.ANY_TRANSPORT}; } diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoSSLCustom.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoSSLCustom.java index 42601cc1692..ee8e5fd918b 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoSSLCustom.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/DemoSSLCustom.java @@ -18,7 +18,6 @@ package org.apache.servicecomb.demo; import java.io.File; -import java.net.URL; import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.foundation.ssl.SSLCustom; diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java index eb80dc6efd7..c90fe8bc1a5 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java @@ -21,9 +21,9 @@ import java.util.List; import java.util.concurrent.atomic.AtomicLong; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; public class TestMgr { private static final Logger LOGGER = LoggerFactory.getLogger(TestMgr.class); @@ -32,7 +32,7 @@ public class TestMgr { private static String msg = ""; - private static AtomicLong checkes = new AtomicLong(0); + private static final AtomicLong checks = new AtomicLong(0); public static void setMsg(String msg) { TestMgr.msg = msg; @@ -47,7 +47,7 @@ public static void check(Object expect, Object real) { } public static void check(Object expect, Object real, Throwable error) { - checkes.incrementAndGet(); + checks.incrementAndGet(); if (expect == real) { return; @@ -66,7 +66,7 @@ public static void check(Object expect, Object real, Throwable error) { } public static void checkNotEmpty(String real) { - checkes.incrementAndGet(); + checks.incrementAndGet(); if (StringUtils.isEmpty(real)) { errorList.add(new Error(msg + " | unexpected null result, method is " + getCaller())); @@ -78,11 +78,11 @@ public static void fail(String desc) { } public static void failed(String desc, Throwable e) { - checkes.incrementAndGet(); + checks.incrementAndGet(); Error error = new Error(msg + " | " + desc + ", method is " + getCaller()); if (e != null) { - error.setStackTrace(error.getStackTrace()); + error.setStackTrace(e.getStackTrace()); } errorList.add(error); } @@ -94,12 +94,12 @@ public static boolean isSuccess() { public static void summary() { if (errorList.isEmpty()) { LOGGER.info("............. test finished ............"); - LOGGER.info("............. total checks : " + checkes.get()); + LOGGER.info("............. total checks : " + checks.get()); return; } LOGGER.info("............. test not finished ............"); - LOGGER.info("............. total checks : " + checkes.get()); + LOGGER.info("............. total checks : " + checks.get()); LOGGER.info("............. total errors : " + errorList.size()); LOGGER.info("............. error details: "); for (Throwable e : errorList) { diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/api/IHeaderParamWithListSchema.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/api/IHeaderParamWithListSchema.java new file mode 100644 index 00000000000..8ee60ff27dd --- /dev/null +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/api/IHeaderParamWithListSchema.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.api; + +import java.util.List; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.Explode; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.ParameterStyle; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.HeaderParam; +import jakarta.ws.rs.Path; + +@Path("/headerList") +public interface IHeaderParamWithListSchema { + @Path("headerListDefault") + @GET + String headerListDefault( + @HeaderParam("headerList") List headerList); + + @Path("headerListCSV") + @GET + String headerListCSV( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.FORM, explode = Explode.FALSE) + List headerList); + + @Path("headerListMULTI") + @GET + String headerListMULTI( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.FORM, explode = Explode.TRUE) + List headerList); + + @Path("headerListSSV") + @GET + String headerListSSV( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.SPACEDELIMITED, explode = Explode.FALSE) + List headerList); + + @Path("headerListPIPES") + @GET + String headerListPIPES( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.PIPEDELIMITED, explode = Explode.FALSE) + List headerList); +} diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/api/IHeaderParamWithListSchemaSpringMvc.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/api/IHeaderParamWithListSchemaSpringMvc.java new file mode 100644 index 00000000000..75875f8790c --- /dev/null +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/api/IHeaderParamWithListSchemaSpringMvc.java @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.api; + + +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.Explode; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.enums.ParameterStyle; + +@RequestMapping("/headerList") +public interface IHeaderParamWithListSchemaSpringMvc { + @GetMapping("headerListDefault") + String headerListDefault( + @RequestHeader("headerList") List headerList); + + @GetMapping("headerListCSV") + String headerListCSV( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.FORM, explode = Explode.FALSE) + List headerList); + + @GetMapping("headerListMULTI") + String headerListMULTI( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.FORM, explode = Explode.TRUE) + List headerList); + + @GetMapping("headerListSSV") + String headerListSSV( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.SPACEDELIMITED, explode = Explode.FALSE) + List headerList); + + @GetMapping("headerListPIPES") + String headerListPIPES( + @Parameter(name = "headerList", in = ParameterIn.HEADER, style = ParameterStyle.PIPEDELIMITED, explode = Explode.FALSE) + List headerList); +} diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/Controller.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/Controller.java index f8752fb84dc..b82cd345a52 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/Controller.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/Controller.java @@ -27,4 +27,6 @@ public interface Controller { String sayHi(String name); String sayHei(String name); + + String sayHello1(String name); } diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/PersonAlias.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/PersonAlias.java new file mode 100644 index 00000000000..a1766eb29c2 --- /dev/null +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/controller/PersonAlias.java @@ -0,0 +1,35 @@ +/* + * 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.demo.controller; + +public class PersonAlias { + private String name; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + @Override + public String toString() { + return name; + } +} diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java index a84ac020671..d9b35305ae6 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java @@ -18,7 +18,7 @@ package org.apache.servicecomb.demo.helloworld.greeter; public interface Hello { - public String SayHello(String name); + String SayHello(String name); - public String SayHelloAgain(String name); + String SayHelloAgain(String name); } diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java index 620879803ab..797833437a7 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBJob.java @@ -16,11 +16,12 @@ */ package org.apache.servicecomb.demo.jaxbbean; -import javax.xml.bind.annotation.XmlAccessOrder; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorOrder; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlRootElement; + +import jakarta.xml.bind.annotation.XmlAccessOrder; +import jakarta.xml.bind.annotation.XmlAccessType; +import jakarta.xml.bind.annotation.XmlAccessorOrder; +import jakarta.xml.bind.annotation.XmlAccessorType; +import jakarta.xml.bind.annotation.XmlRootElement; @XmlRootElement(name = "job") @XmlAccessorType(XmlAccessType.FIELD) diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java index bd66e9dbd9f..450ebacabe8 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxbbean/JAXBPerson.java @@ -18,13 +18,13 @@ import java.io.Serializable; -import javax.xml.bind.annotation.XmlAccessOrder; -import javax.xml.bind.annotation.XmlAccessorOrder; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; -import javax.xml.bind.annotation.XmlType; +import jakarta.xml.bind.annotation.XmlAccessOrder; +import jakarta.xml.bind.annotation.XmlAccessorOrder; +import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.XmlTransient; +import jakarta.xml.bind.annotation.XmlType; @XmlType(propOrder = {"name", "role", "job"}) @XmlRootElement(name = "person") diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationModel.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationModel.java index 09e26129b7e..7a99260c393 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationModel.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/jaxrs/server/validation/ValidationModel.java @@ -19,7 +19,7 @@ import java.util.List; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.NotNull; public class ValidationModel { @NotNull diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java index 26ea1951f5d..17659cfed21 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/ProduceAppXmlProcessor.java @@ -18,8 +18,9 @@ import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; import org.apache.servicecomb.demo.utils.JAXBUtils; @@ -40,7 +41,7 @@ public int getOrder() { @Override public void doEncodeResponse(OutputStream output, Object result) throws Exception { - output.write(JAXBUtils.convertToXml(result).getBytes()); + output.write(JAXBUtils.convertToXml(result).getBytes(StandardCharsets.UTF_8)); } @Override diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java index 45acf3af2cc..aebe13eb116 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/produceprocessor/override/ProduceAppXmlProcessor.java @@ -18,8 +18,9 @@ import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; import org.apache.servicecomb.demo.utils.JAXBUtils; @@ -40,7 +41,7 @@ public int getOrder() { @Override public void doEncodeResponse(OutputStream output, Object result) throws Exception { - output.write(JAXBUtils.convertToXml(result).getBytes()); + output.write(JAXBUtils.convertToXml(result).getBytes(StandardCharsets.UTF_8)); } @Override diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/server/Test.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/server/Test.java index 0afa62a6434..0369d576073 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/server/Test.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/server/Test.java @@ -35,4 +35,6 @@ public interface Test { String addString(String[] strArr); String testTraceId(); + + int[] testIntArray(int[] request); } diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java index 671260f049f..7ff2518e8a3 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/utils/JAXBUtils.java @@ -20,9 +20,6 @@ import java.io.StringWriter; import java.nio.charset.StandardCharsets; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.Marshaller; -import javax.xml.bind.Unmarshaller; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.Source; import javax.xml.transform.sax.SAXSource; @@ -33,6 +30,10 @@ import com.fasterxml.jackson.databind.JavaType; +import jakarta.xml.bind.JAXBContext; +import jakarta.xml.bind.Marshaller; +import jakarta.xml.bind.Unmarshaller; + public class JAXBUtils { private static final Logger LOGGER = LoggerFactory.getLogger(JAXBUtils.class); @@ -55,7 +56,7 @@ public static String convertToXml(Object obj, String encoding) { marshaller.marshal(obj, writer); result = writer.toString(); } catch (Exception e) { - LOGGER.error("Bean convert to xml failed, error message: {}", e.getMessage()); + LOGGER.error("Bean convert to xml failed, error message: {}", e.getMessage(), e); } return result; } diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java index 65feea2ec7f..3117c5e1f82 100644 --- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Student.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.demo.validator; -import javax.validation.constraints.Max; -import javax.validation.constraints.NotNull; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotNull; public class Student { @NotNull diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Teacher.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Teacher.java new file mode 100644 index 00000000000..b7015e2920e --- /dev/null +++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/validator/Teacher.java @@ -0,0 +1,49 @@ +/* + * 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.demo.validator; + +import jakarta.validation.constraints.NotBlank; + +public class Teacher { + + @NotBlank(message = "must not be blank") + private String name; + + private String age; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAge() { + return age; + } + + public void setAge(String age) { + this.age = age; + } + + @Override + public String toString() { + return name + " " + age; + } +} diff --git a/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor b/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor index ff9a6cb9a54..acd03890620 100644 --- a/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor +++ b/demo/demo-schema/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor @@ -16,4 +16,4 @@ # org.apache.servicecomb.demo.produceprocessor.ProduceAppXmlProcessor -org.apache.servicecomb.demo.produceprocessor.override.ProduceAppXmlProcessor \ No newline at end of file +org.apache.servicecomb.demo.produceprocessor.override.ProduceAppXmlProcessor diff --git a/demo/demo-schema/src/main/resources/config/log4j.eclipse.properties b/demo/demo-schema/src/main/resources/config/log4j.eclipse.properties deleted file mode 100644 index 8d7c9ffb587..00000000000 --- a/demo/demo-schema/src/main/resources/config/log4j.eclipse.properties +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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. -# - -paas.logs.dir=../../../../cse-demo-bin/logs/ -log4j.appender.stdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS/zzz}][%t][%p]%m %l%n diff --git a/demo/demo-schema/src/main/resources/config/log4j.properties b/demo/demo-schema/src/main/resources/config/log4j.properties deleted file mode 100644 index 94010942506..00000000000 --- a/demo/demo-schema/src/main/resources/config/log4j.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# 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. -# - -paas.logs.dir=../target/logs/ -paas.logs.file=cse.log - -log4j.rootLogger=INFO,paas,stdout -log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF -log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-schema/src/main/resources/microservice.yaml b/demo/demo-schema/src/main/resources/microservice.yaml index 97db791f559..28df63a4323 100644 --- a/demo/demo-schema/src/main/resources/microservice.yaml +++ b/demo/demo-schema/src/main/resources/microservice.yaml @@ -16,15 +16,14 @@ ## --------------------------------------------------------------------------- servicecomb-config-order: -1 -cse: - test: - duplicate1: older - -servicecomb: - test: - duplicate2: older - demo.multi.service.center.serverB: key1: key1 key2: key2 - key3: key3 \ No newline at end of file + key3: key3 + +servicecomb: + # verbose exceptions information + invocation: + exception: + print-stack-trace: true + print-rate-limit: true diff --git a/demo/demo-schema/src/main/resources/microservices/jaxrs/compute.yaml b/demo/demo-schema/src/main/resources/microservices/jaxrs/compute.yaml deleted file mode 100644 index 6606be573ae..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/jaxrs/compute.yaml +++ /dev/null @@ -1,201 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: rest test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.compute.Compute - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /compute -produces: - - application/json - -paths: - /add: - post: - operationId: add - parameters: - - name: a - in: formData - required: true - type: integer - format: int32 - - name: b - in: formData - required: true - type: integer - format: int32 - responses: - "200": - description: add numer - schema: - type: integer - format: int32 - /reduce: - get: - operationId: reduce - parameters: - - name: a - in: query - required: true - type: integer - format: int32 - - name: b - in: query - required: true - type: integer - format: int32 - responses: - "200": - description: reduce - schema: - type: integer - format: int32 - /sayhello: - post: - operationId: sayHello - parameters: - - name: user - in: body - required: true - schema: - $ref: '#/definitions/Person' - responses: - "200": - description: say hello - schema: - $ref: '#/definitions/Person' - /testrawjson: - post: - operationId: testRawJsonString - parameters: - - name: jsonInput - in: body - required: true - x-raw-json: true - schema: - type: string - responses: - "200": - description: test RawJson String - schema: - type: string - /saysomething: - post: - operationId: saySomething - parameters: - - name: prefix - in: header - required: true - type: string - - name: user - in: body - required: true - schema: - $ref: '#/definitions/Person' - responses: - "200": - description: say something - schema: - type: string - /sayhi/{name}: - put: - operationId: sayHi - parameters: - - name: name - in: path - required: true - type: string - responses: - "200": - description: say hi - schema: - type: string - 202: - description: say hi - schema: - type: string - /sayhi/{name}/v2: - put: - operationId: sayHi2 - parameters: - - name: name - in: path - required: true - type: string - responses: - "200": - description: say hi - schema: - type: string - /sayhei: - delete: - operationId: sayHei - parameters: - - name: name - in: query - required: true - type: string - responses: - "200": - description: say hi - schema: - type: string - /istrue: - get: - operationId: isTrue - responses: - "200": - description: is true - schema: - type: boolean - /addstring: - delete: - operationId: addString - produces: - - text/plain - parameters: - - name: s - in: query - required: true - type: array - items: - type: string - responses: - "200": - description: add string - schema: - type: string - -definitions: - Person: - type: object - properties: - name: - type: string - x-java-class: "org.apache.servicecomb.demo.compute.Person" diff --git a/demo/demo-schema/src/main/resources/microservices/no-use/cse.basic.Basic/main.idl b/demo/demo-schema/src/main/resources/microservices/no-use/cse.basic.Basic/main.idl deleted file mode 100644 index 6b5cd765367..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/no-use/cse.basic.Basic/main.idl +++ /dev/null @@ -1,62 +0,0 @@ -// 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 cse.basic; - -message BasicRequest { - required AllBasicTypes request = 1; -} - -message BasicResponse { - required AllBasicTypes request = 1; -} - -message AllBasicTypes { - required double tdouble = 1; - required float tfloat = 2; - required int32 tint32 = 3; - required int64 tint64 = 4; - required uint32 tuint32 = 5; - required uint64 tuint64 = 6; - required sint32 tsint32 = 7; - required sint64 tsint64 = 8; - required fixed32 tfixed32 = 9; - required fixed64 tfixed64 = 10; - required sfixed32 tsfixed32 = 11; - required sfixed64 tsfixed64 = 12; - required bool tbool = 13; - required string tstring = 14; - required bytes tbytes = 15; - - enum EnumType { - ONE = 0; - TWO = 1; - } - required EnumType enumType = 16; - - // map mapType = 17; - //message MapFieldEntry { - //required string key = 1; - //required string value = 2; - //} - //repeated MapFieldEntry mapType = 17; - - repeated string tstringList = 17; -} - -service Basic { - rpc schalarType(BasicRequest) returns(BasicResponse); -} diff --git a/demo/demo-schema/src/main/resources/microservices/no-use/hello/main.idl b/demo/demo-schema/src/main/resources/microservices/no-use/hello/main.idl deleted file mode 100644 index 6a6fd47fd1a..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/no-use/hello/main.idl +++ /dev/null @@ -1,26 +0,0 @@ -// 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. - -service Greeter { - rpc SayHello (HelloRequest) returns (HelloReply) {} -} - -message HelloRequest { - required string name = 1; -} - -message HelloReply { - required string message = 1; -} diff --git a/demo/demo-schema/src/main/resources/microservices/no-use/helloworld.Greeter/main.idl b/demo/demo-schema/src/main/resources/microservices/no-use/helloworld.Greeter/main.idl deleted file mode 100644 index e415db0350e..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/no-use/helloworld.Greeter/main.idl +++ /dev/null @@ -1,29 +0,0 @@ -// 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 helloworld; - -service Greeter { - rpc SayHello (HelloRequest) returns (HelloReply); - rpc SayHelloAgain (HelloRequest) returns (HelloReply); -} - -message HelloRequest { - required string name = 1; -} - -message HelloReply { - required string message = 1; -} diff --git a/demo/demo-schema/src/main/resources/microservices/no-use/helloworld.Standard/main.idl b/demo/demo-schema/src/main/resources/microservices/no-use/helloworld.Standard/main.idl deleted file mode 100644 index 2cf0a7a738a..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/no-use/helloworld.Standard/main.idl +++ /dev/null @@ -1,34 +0,0 @@ -// 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 helloworld; - -message StandardRequest { - required ComplexType args0 = 1; -} - -message StandardResponse { - required ComplexType response = 1; -} - -message ComplexType { - repeated int32 intType = 1; - repeated bool boolType = 2; - repeated string stringType = 3; -} - -service Standard { - rpc sayHelloComplex (StandardRequest) returns (StandardResponse); -} diff --git a/demo/demo-schema/src/main/resources/microservices/no-use/server/main.idl b/demo/demo-schema/src/main/resources/microservices/no-use/server/main.idl deleted file mode 100644 index d60a7a86798..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/no-use/server/main.idl +++ /dev/null @@ -1,97 +0,0 @@ -// 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. - -message TestRequest{ - required int32 index = 1; - required User user = 2; - required bytes data = 3; - //repeated MapFieldEntry friends = 4; -} - -message User{ - required string name = 1; - required int32 age = 2; - required int32 index = 3; - //repeated MapFieldEntry friends = 4; -} - -message MapFieldEntry { - required string key = 1; - required int32 value = 2; -} - -message TestResponse{ - required User user = 1; -} - -enum EnumType { - ONE = 0; - TWO = 1; -} - -message EnumMessage{ - required EnumType enumType = 1; -} - -message Empty{ -} - -message MicroService{ - optional string service_id = 1; - required string app_id = 2; - required string name = 3; - required string version = 4; - optional string description = 5; - optional string level = 6 [default = "front"]; - repeated ServiceDefinition definitions = 7; - optional ServiceStatus status = 8 [default = INSERVICE]; -} - -message ServiceDefinition { - required string name = 1; - required string version = 2; - required string transport = 3; - repeated string schema = 4; - //map properties = 5; -} - -enum ServiceStatus { - INSERVICE = 0; - OUTOFSERVICE = 1; -} - -message MicroServiceWrap{ - required MicroService service = 1; -} - -service server { - rpc splitParam(TestRequest) returns(User); - rpc standard(TestRequest) returns(TestResponse); - rpc sayHello (HelloRequest) returns (HelloReply); - rpc standardSayHello (HelloRequest) returns (HelloReply); - rpc testEnum(EnumMessage) returns(EnumMessage); - rpc testStandardEnum(EnumMessage) returns(EnumMessage); - rpc testEmpty(Empty) returns(Empty); - rpc testMicroService(MicroService) returns(MicroService); - rpc testCreateMicroService(MicroServiceWrap) returns(MicroServiceWrap); -} - -message HelloRequest { - required string name = 1; -} - -message HelloReply { - required string message = 1; -} diff --git a/demo/demo-schema/src/main/resources/microservices/pojo/helloworld.Greeter.yaml b/demo/demo-schema/src/main/resources/microservices/pojo/helloworld.Greeter.yaml deleted file mode 100644 index d503f154ce0..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/pojo/helloworld.Greeter.yaml +++ /dev/null @@ -1,74 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: helloworld.Greeter - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.helloworld.greeter.Hello - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest/helloworld.Greeter -produces: - - application/json - -paths: - /SayHello: - post: - operationId: SayHello - parameters: - - name: name - in: body - required: true - schema: - type: string - responses: - "200": - description: asdf - schema: - type: string - default: - description: asf - schema: - type: string - /SayHelloAgain: - post: - operationId: SayHelloAgain - parameters: - - name: name - in: body - required: true - schema: - type: string - responses: - "200": - description: asdf - schema: - type: string - default: - description: asf - schema: - type: string diff --git a/demo/demo-schema/src/main/resources/microservices/pojo/server.yaml b/demo/demo-schema/src/main/resources/microservices/pojo/server.yaml deleted file mode 100644 index 9c8be9e8400..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/pojo/server.yaml +++ /dev/null @@ -1,221 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: cse test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.server.Test - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest -produces: - - application/json - -paths: - /testStringArray: - get: - operationId: testStringArray - parameters: - - name: arr - in: query - required: true - type: array - items: - type: string - responses: - "200": - description: asdf - schema: - type: string - /testStatic: - get: - operationId: getTestString - parameters: - - name: code - in: query - required: false - type: string - responses: - "200": - description: asdf - schema: - type: string - post: - operationId: postTestStatic - parameters: - - name: code - in: query - required: true - type: integer - format: int32 - responses: - "200": - description: asdf - schema: - type: string - patch: - operationId: patchTestStatic - parameters: - - name: code - in: query - required: true - type: integer - format: int32 - responses: - "200": - description: asdf - schema: - type: string - /testException/{code}: - get: - operationId: testException - parameters: - - name: code - in: path - required: true - type: integer - format: int32 - responses: - "200": - description: asdf - schema: - type: string - 456: - description: asdf - schema: - type: string - 556: - description: asdf - schema: - type: array - items: - type: string - 557: - description: asdf - schema: - type: array - items: - type: array - items: - type: string - /splitParam: - post: - operationId: splitParam - parameters: - - name: index - in: query - required: true - type: integer - format: int32 - - name: user - in: body - schema: - $ref: '#/definitions/User' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - /wrapParam: - post: - operationId: wrapParam - parameters: - - name: request - in: body - required: false - schema: - $ref: '#/definitions/TestRequest' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - /addstring: - delete: - operationId: addString - parameters: - - name: strArr - in: query - required: true - type: array - items: - type: string - responses: - "200": - description: add string - schema: - type: string - /testTraceId: - get: - operationId: testTraceId - responses: - "200": - description: get trace id - schema: - type: string -definitions: - Error: - type: object - x-java-class: org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData - properties: - message: - type: string - TestRequest: - type: object - properties: - index: - type: integer - format: int32 - user: - $ref: '#/definitions/User' - users: - type: array - items: - $ref: '#/definitions/User' - data: - type: string - format: byte - User: - type: object - properties: - name: - type: string - age: - type: integer - format: int32 - index: - type: integer - format: int32 - x-java-class: "org.apache.servicecomb.demo.server.User" diff --git a/demo/demo-schema/src/main/resources/microservices/pojo/smartcare.yaml b/demo/demo-schema/src/main/resources/microservices/pojo/smartcare.yaml deleted file mode 100644 index 0879c3bda2d..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/pojo/smartcare.yaml +++ /dev/null @@ -1,136 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: smartcare test - version: 1.0.0 -# x-java-interface is optional, remove it should works well, but sometimes need to generate more class in memory -# x-java-interface: org.apache.servicecomb.demo.smartcare.SmartCare - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest/plat/meta/v1 -produces: - - application/json - -paths: - /applications: - post: - operationId: addApplication - parameters: - - name: application - in: body - required: true - schema: - $ref: '#/definitions/Application' - responses: - 201: - description: success - schema: - $ref: '#/definitions/Response' - 400: - description: error - schema: - $ref: '#/definitions/Response' - 500: - description: error - schema: - $ref: '#/definitions/Response' - - /applications/{appName}: - delete: - operationId: delApplication - parameters: - - name: appName - in: path - required: true - type: string - responses: - 201: - description: success - schema: - $ref: '#/definitions/Response' - 400: - description: error - schema: - $ref: '#/definitions/Response' - 500: - description: error - schema: - $ref: '#/definitions/Response' - - -definitions: - Application: - type: object - properties: - name: - type: string - labelEN: - type: string - labelCH: - type: string - defaultGroup: - type: string - version: - type: string - dynamicFlag: - type: boolean - groups: - type: array - items: - $ref: '#/definitions/Group' - required: - - name - - defaultGroup - - version - - dynamicFlag - - groups - - Group: - type: object - properties: - name: - type: string - labelEN: - type: string - labelCH: - type: string - required: - - name - - Response: - type: object - x-java-class: org.apache.servicecomb.demo.smartcare.Response - properties: - resultCode: - type: integer - format: int32 - resultMessage: - type: string - required: - - resultCode - diff --git a/demo/demo-schema/src/main/resources/microservices/pojo/tcc-server.yaml b/demo/demo-schema/src/main/resources/microservices/pojo/tcc-server.yaml deleted file mode 100644 index 4af831b88d8..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/pojo/tcc-server.yaml +++ /dev/null @@ -1,108 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: cse test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.tccserver.TestTcc - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest/tcc-server -produces: - - application/json - -paths: - /splitParam: - post: - operationId: splitParam - parameters: - - name: index - in: query - required: true - type: number - - name: user - in: body - schema: - $ref: '#/definitions/User' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - /wrapParam: - post: - operationId: wrapParam - parameters: - - name: TestRequest - in: body - required: true - schema: - $ref: '#/definitions/TestRequest' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - -definitions: - Error: - type: object - x-java-class: org.apache.servicecomb.core.exception.CommonExceptionData - properties: - message: - type: string - TestRequest: - type: object - properties: - index: - type: number - user: - $ref: '#/definitions/User' - users: - type: array - items: - $ref: '#/definitions/User' - data: - type: string - format: byte - User: - type: object - properties: - name: - type: string - age: - type: number - index: - type: number diff --git a/demo/demo-schema/src/main/resources/microservices/springmvc/controller.yaml b/demo/demo-schema/src/main/resources/microservices/springmvc/controller.yaml deleted file mode 100644 index 9bea47b0ff0..00000000000 --- a/demo/demo-schema/src/main/resources/microservices/springmvc/controller.yaml +++ /dev/null @@ -1,123 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: rest test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.controller.Controller - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /springmvc/controller -produces: - - application/json - -paths: - /add: - get: - operationId: add - parameters: - - name: a - in: query - required: true - type: integer - format: int32 - - name: b - in: query - required: true - type: integer - format: int32 - responses: - "200": - description: add numer - schema: - type: integer - format: int32 - - /sayhello/{name}: - post: - operationId: sayHello - parameters: - - name: name - in: path - required: true - type: string - responses: - "200": - description: say hello - schema: - type: string - /saysomething: - post: - operationId: saySomething - parameters: - - name: prefix - in: query - required: true - type: string - - name: user - in: body - required: true - schema: - $ref: '#/definitions/Person' - responses: - "200": - description: say something - schema: - type: string - /sayhi: - get: - operationId: sayHi - parameters: - - name: name - in: query - required: true - type: string - responses: - "200": - description: say hi - schema: - type: string - /sayhei: - get: - operationId: sayHei - parameters: - - name: name - in: header - required: true - type: string - responses: - "200": - description: say hei - schema: - type: string - -definitions: - Person: - type: object - properties: - name: - type: string diff --git a/demo/demo-signature/pom.xml b/demo/demo-signature/pom.xml deleted file mode 100644 index 0f489c15235..00000000000 --- a/demo/demo-signature/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - 4.0.0 - - org.apache.servicecomb.demo - demo-parent - 2.6.0-SNAPSHOT - - demo-signature - Java Chassis::Demo::Signature - - - - org.apache.servicecomb - common-rest - - - org.apache.servicecomb - registry-service-center - - - diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java deleted file mode 100644 index aa715d2bc07..00000000000 --- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ClientSignature.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.demo.signature; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.common.rest.filter.HttpClientFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ClientSignature implements HttpClientFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(ClientSignature.class); - - @Override - public int getOrder() { - return 0; - } - - @Override - public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) { - String signature = SignatureUtils.genSignature(requestEx); - requestEx.setHeader("signature", signature); - } - - @Override - public Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx) { - String signature = SignatureUtils.genSignature(responseEx); - String serverSignature = responseEx.getHeader("signature"); - - if (serverSignature != null) { - LOGGER.debug("check response signature, client: {}, server: {}.", signature, serverSignature); - if (!signature.equals(serverSignature)) { - LOGGER.error("check response signature failed"); - return Response.create(Status.UNAUTHORIZED, "check response signature failed"); - } - } - return null; - } -} diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java deleted file mode 100644 index 8f6e181d363..00000000000 --- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/ServerSignature.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.demo.signature; - -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ServerSignature implements HttpServerFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(ServerSignature.class); - - public ServerSignature() { - } - - @Override - public int getOrder() { - return 0; - } - - @Override - public boolean needCacheRequest(OperationMeta operationMeta) { - return true; - } - - @Override - public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) { -// String signature = SignatureUtils.genSignature(requestEx); -// String clientSignature = requestEx.getHeader("signature"); -// LOGGER.debug("check request signature, client: {}, server: {}.", clientSignature, signature); -// if (!signature.equals(clientSignature)) { -// LOGGER.error("check request signature failed: {}", invocation.getInvocationQualifiedName()); -// return Response -// .create(Status.UNAUTHORIZED, "check request signature failed: " + invocation.getInvocationQualifiedName()); -// } - - return null; - } - - @Override - public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) { - String signature = SignatureUtils.genSignature(responseEx); - responseEx.addHeader("signature", signature); - } -} diff --git a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java b/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java deleted file mode 100644 index 33e485b1f8d..00000000000 --- a/demo/demo-signature/src/main/java/org/apache/servicecomb/demo/signature/SignatureUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.demo.signature; - -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; - -import javax.ws.rs.core.MediaType; - -import org.apache.commons.lang.StringUtils; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; - -import com.google.common.hash.Hasher; -import com.google.common.hash.Hashing; -import com.netflix.config.DynamicStringListProperty; - -public class SignatureUtils { - private static final DynamicStringListProperty PARAM_NAMES_PROPERTY = - new DynamicStringListProperty("servicecomb.demo.signature.param-names", Arrays.asList("userId")); - - private static List paramNames = PARAM_NAMES_PROPERTY.get(); - - static { - PARAM_NAMES_PROPERTY.addCallback(() -> { - List tmpNames = PARAM_NAMES_PROPERTY.get(); - tmpNames.sort(Comparator.naturalOrder()); - paramNames = tmpNames; - }); - } - - public static String genSignature(HttpServletRequestEx requestEx) { - Hasher hasher = Hashing.sha256().newHasher(); - hasher.putString(requestEx.getRequestURI(), StandardCharsets.UTF_8); - for (String paramName : paramNames) { - String paramValue = requestEx.getHeader(paramName); - if (paramValue != null) { - hasher.putString(paramName, StandardCharsets.UTF_8); - hasher.putString(paramValue, StandardCharsets.UTF_8); - System.out.printf("%s %s\n", paramName, paramValue); - } - } - - if (!StringUtils.startsWithIgnoreCase(requestEx.getContentType(), MediaType.APPLICATION_FORM_URLENCODED)) { - byte[] bytes = requestEx.getBodyBytes(); - if (bytes != null) { - hasher.putBytes(bytes, 0, requestEx.getBodyBytesLength()); - } - } - - return hasher.hash().toString(); - } - - public static String genSignature(HttpServletResponseEx responseEx) { - Hasher hasher = Hashing.sha256().newHasher(); - byte[] bytes = responseEx.getBodyBytes(); - if (bytes != null) { - hasher.putBytes(bytes, 0, responseEx.getBodyBytesLength()); - } - - return hasher.hash().toString(); - } -} diff --git a/demo/demo-signature/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter b/demo/demo-signature/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter deleted file mode 100644 index 9533c795685..00000000000 --- a/demo/demo-signature/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.demo.signature.ClientSignature diff --git a/demo/demo-signature/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/demo/demo-signature/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter deleted file mode 100644 index 37d7671228c..00000000000 --- a/demo/demo-signature/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.demo.signature.ServerSignature diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/pom.xml b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/pom.xml deleted file mode 100644 index 8e63915a681..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/pom.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - 4.0.0 - demo-spring-boot-jaxrs-client - Java Chassis::Demo::Spring Boot::JAXRS Client - - org.apache.servicecomb.demo - demo-spring-boot - 2.6.0-SNAPSHOT - - - - org.apache.servicecomb.demo - jaxrs-client - - - org.apache.logging.log4j - log4j-slf4j-impl - - - - - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - - - - docker - - demo-spring-boot-jaxrs-server - - - - - io.fabric8 - docker-maven-plugin - - - - - - diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java deleted file mode 100644 index 89e4d9d27b8..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/java/org/apache/servicecomb/springboot/jaxrs/client/JaxrsClient.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.springboot.jaxrs.client; - -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapperNotWriteNull; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class JaxrsClient { - - public static void main(String[] args) throws Exception { - RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper()); - RestObjectMapperFactory.setConsumerWriterMapper(new RestObjectMapperWithStringMapperNotWriteNull()); - - new SpringApplicationBuilder().sources(JaxrsClient.class).web(WebApplicationType.NONE).build().run(args); - org.apache.servicecomb.demo.jaxrs.client.JaxrsClient.run(); - TestMgr.summary(); - } -} diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/application.yml b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/application.yml deleted file mode 100644 index f0dc3cd7503..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/main/resources/application.yml +++ /dev/null @@ -1,35 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -server: - port: 8999 - -# java-chassis configuration - -servicecomb-config-order: 1 -APPLICATION_ID: spring-boot-jaxrstest -service_description: - name: jaxrsClient - version: 0.0.1 -servicecomb: - service: - registry: - address: http://127.0.0.1:30100 - handler: - chain: - Consumer: - default: bizkeeper-consumer,loadbalance diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/test/java/org/apache/servicecomb/springboot/jaxrs/SpringBootJaxrsIT.java b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/test/java/org/apache/servicecomb/springboot/jaxrs/SpringBootJaxrsIT.java deleted file mode 100644 index 5e9f1f9664c..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-client/src/test/java/org/apache/servicecomb/springboot/jaxrs/SpringBootJaxrsIT.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.springboot.jaxrs; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot.jaxrs.client.JaxrsClient; -import org.junit.Before; -import org.junit.Test; - -public class SpringBootJaxrsIT { - - @Before - public void setUp() throws Exception { - TestMgr.errors().clear(); - } - - @Test - public void clientGetsNoError() throws Exception { - try { - JaxrsClient.main(new String[0]); - - assertThat(TestMgr.errors().isEmpty(), is(true)); - } catch (Throwable e) { - e.printStackTrace(); - fail("test case failed, message=" + e.getMessage()); - } - } -} diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/pom.xml b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/pom.xml deleted file mode 100644 index 95d25087fa3..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/pom.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - 4.0.0 - demo-spring-boot-jaxrs-server - Java Chassis::Demo::Spring Boot::JAXRS Server - - org.apache.servicecomb.demo - demo-spring-boot - 2.6.0-SNAPSHOT - - - org.apache.servicecomb.springboot.jaxrs.server.JaxrsServer - - - - org.apache.servicecomb.demo - jaxrs-server - - - org.apache.logging.log4j - log4j-slf4j-impl - - - - - org.apache.servicecomb - inspector - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - - - - - - - docker - - - - io.fabric8 - docker-maven-plugin - - - org.commonjava.maven.plugins - directory-maven-plugin - - - - - - diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java deleted file mode 100644 index 385c1b0c58d..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/java/org/apache/servicecomb/springboot/jaxrs/server/JaxrsServer.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.springboot.jaxrs.server; - -import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapper; -import org.apache.servicecomb.demo.RestObjectMapperWithStringMapperNotWriteNull; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class JaxrsServer { - public static void main(final String[] args) throws Exception { - RestObjectMapperFactory.setDefaultRestObjectMapper(new RestObjectMapperWithStringMapper()); - RestObjectMapperFactory.setConsumerWriterMapper(new RestObjectMapperWithStringMapperNotWriteNull()); - - new SpringApplicationBuilder().sources(JaxrsServer.class).web(WebApplicationType.NONE).build().run(args); - } -} diff --git a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/application.yml b/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/application.yml deleted file mode 100644 index 6f9757580b3..00000000000 --- a/demo/demo-spring-boot-provider/demo-spring-boot-jaxrs-server/src/main/resources/application.yml +++ /dev/null @@ -1,38 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -server: - port: 0 - -# java-chassis configuration -servicecomb-config-order: 1 -APPLICATION_ID: spring-boot-jaxrstest -service_description: - name: jaxrs - version: 0.0.1 -servicecomb: - service: - registry: - address: http://127.0.0.1:30100 - rest: - address: 0.0.0.0:8080 - highway: - address: 0.0.0.0:7070 - handler: - chain: - Provider: - default: bizkeeper-provider \ No newline at end of file diff --git a/demo/demo-spring-boot-provider/pom.xml b/demo/demo-spring-boot-provider/pom.xml deleted file mode 100644 index 72f816cd02e..00000000000 --- a/demo/demo-spring-boot-provider/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - 4.0.0 - - org.apache.servicecomb.demo - demo-parent - 2.6.0-SNAPSHOT - - demo-spring-boot - Java Chassis::Demo::Spring Boot - pom - - demo-spring-boot-jaxrs-server - demo-spring-boot-jaxrs-client - - - - - org.apache.servicecomb - registry-service-center - - - org.apache.servicecomb - java-chassis-spring-boot-starter-standalone - - - - diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/pom.xml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/pom.xml index 27c00a07660..372d3a8ccc3 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/pom.xml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/pom.xml @@ -25,31 +25,12 @@ org.apache.servicecomb.demo demo-spring-boot-transport - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT - org.apache.servicecomb.springboot.pojo.client.PojoClient + org.apache.servicecomb.demo.springboot.pojo.client.PojoClient - - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - @@ -58,6 +39,83 @@ demo-spring-boot-pojo-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/Test.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/Test.java deleted file mode 100644 index d853caffc13..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/Test.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.demo.server; - -public interface Test { - String testStringArray(String[] arr); - - String getTestString(String code); - - String postTestStatic(int code); - - String testException(int code); - - User wrapParam(TestRequest request); - - User splitParam(int index, User user); - - String addString(String[] strArr); -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/TestRequest.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/TestRequest.java deleted file mode 100644 index 6f622686271..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/TestRequest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.demo.server; - -import java.util.ArrayList; -import java.util.List; - -public class TestRequest { - private int index; - - private User user; - - private List users = new ArrayList<>(); - - private byte[] data; - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } - - public byte[] getData() { - return data; - } - - public void setData(byte[] data) { - this.data = data; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/TestResponse.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/TestResponse.java deleted file mode 100644 index c6baa8e0078..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/TestResponse.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.demo.server; - -public class TestResponse { - private User user; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - @Override - public String toString() { - return "TestResponse [user=" + user + "]"; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/User.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/User.java deleted file mode 100644 index e7d4e94d40d..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/server/User.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.demo.server; - -public class User { - private String name = "nameA"; - - private int age = 100; - - private int index; - - private String[] names; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String[] getNames() { - return names; - } - - public void setNames(String[] names) { - this.names = names; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - @Override - public String toString() { - return "User [name=" + name + ", age=" + age + ", index=" + index + "]"; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/DemoConst.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/DemoConst.java similarity index 82% rename from demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/DemoConst.java rename to demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/DemoConst.java index 3dd5f64cc22..eb60d1e9d83 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/DemoConst.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/DemoConst.java @@ -15,10 +15,10 @@ * limitations under the License. */ -package org.apache.servicecomb.demo; +package org.apache.servicecomb.demo.springboot.pojo.client; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; public interface DemoConst { - String[] transports = new String[] {"rest", Const.ANY_TRANSPORT}; + String[] transports = new String[] {"rest", CoreConst.ANY_TRANSPORT}; } diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/springboot/pojo/client/PojoClient.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClient.java similarity index 85% rename from demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/springboot/pojo/client/PojoClient.java rename to demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClient.java index b642d161afe..b5a590b65e7 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/springboot/pojo/client/PojoClient.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClient.java @@ -15,12 +15,12 @@ * limitations under the License. */ -package org.apache.servicecomb.springboot.pojo.client; +package org.apache.servicecomb.demo.springboot.pojo.client; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ImportResource; /** * SpringmvcClient @@ -28,12 +28,12 @@ * */ @SpringBootApplication -@EnableServiceComb +@ImportResource(value = "classpath*:META-INF/spring/*.bean.xml") public class PojoClient { public static void main(final String[] args) throws Exception { new SpringApplicationBuilder().sources(PojoClient.class).web(WebApplicationType.SERVLET).build().run(args); - org.apache.servicecomb.demo.pojo.client.PojoClientTest.runTest(); + PojoClientTest.runTest(); } } diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClientTest.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClientTest.java similarity index 80% rename from demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClientTest.java rename to demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClientTest.java index a67bfa6e4f4..4e0525a1230 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/pojo/client/PojoClientTest.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClientTest.java @@ -15,19 +15,17 @@ * limitations under the License. */ -package org.apache.servicecomb.demo.pojo.client; +package org.apache.servicecomb.demo.springboot.pojo.client; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; import org.apache.servicecomb.core.provider.consumer.InvokerUtils; -import org.apache.servicecomb.demo.DemoConst; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.server.Test; -import org.apache.servicecomb.demo.server.TestRequest; -import org.apache.servicecomb.demo.server.User; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.demo.springboot.pojo.server.schema.server.Test; +import org.apache.servicecomb.demo.springboot.pojo.server.schema.server.TestRequest; +import org.apache.servicecomb.demo.springboot.pojo.server.schema.server.User; import org.apache.servicecomb.provider.pojo.RpcReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,12 +35,12 @@ public class PojoClientTest { private static Logger LOGGER = LoggerFactory.getLogger(PojoClientTest.class); - @RpcReference(microserviceName = "pojo") + @RpcReference(microserviceName = "spring-boot-pojo-server", schemaId = "server") public static Test test; - public static Test testFromXml; + private static Test testFromXml; - public static final byte buffer[] = new byte[1024]; + public static final byte[] buffer = new byte[1024]; public static final String SPLITPARAM_RESPONSE_USER_SUFFIX = "(modified by MyHandler)"; @@ -55,10 +53,10 @@ public static void setTestFromXml(Test testFromXml) { } public static void runTest() throws Exception { - String microserviceName = "pojo"; + String microserviceName = "spring-boot-pojo-server"; for (String transport : DemoConst.transports) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); TestMgr.setMsg(microserviceName, transport); LOGGER.info("test {}, transport {}", microserviceName, transport); @@ -94,23 +92,26 @@ private static void testSplitParam(Test test) { @SuppressWarnings({"deprecation"}) private static void testCommonInvoke(String transport) { Map arguments = new HashMap<>(); + Map wrap = new HashMap<>(); arguments.put("index", 2); arguments.put("user", new User()); + wrap.put("splitParamBody", arguments); - Object result = InvokerUtils.syncInvoke("pojo", "server", "splitParam", arguments); + Object result = InvokerUtils.syncInvoke("spring-boot-pojo-server", "server", "splitParam", wrap, User.class); TestMgr.check("User [name=nameA, users count:0" + SPLITPARAM_RESPONSE_USER_SUFFIX + ", age=100, index=2]", result); arguments = new HashMap<>(); arguments.put("index", 3); arguments.put("user", new User()); + wrap = new HashMap<>(); + wrap.put("splitParamBody", arguments); result = - InvokerUtils.syncInvoke("pojo", - "0.0.1", + InvokerUtils.syncInvoke("spring-boot-pojo-server", transport, "server", "splitParam", - arguments); + wrap, User.class); TestMgr.check("User [name=nameA, users count:0" + SPLITPARAM_RESPONSE_USER_SUFFIX + ", age=100, index=3]", result); } diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/TestMgr.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/TestMgr.java similarity index 97% rename from demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/TestMgr.java rename to demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/TestMgr.java index e9444722faf..f0505643417 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/TestMgr.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/client/TestMgr.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.demo; +package org.apache.servicecomb.demo.springboot.pojo.client; import java.util.ArrayList; import java.util.List; diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/Test.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/Test.java new file mode 100644 index 00000000000..6542be49ffc --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/Test.java @@ -0,0 +1,34 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +public interface Test { + String testStringArray(String[] arr); + + String getTestString(String code); + + String postTestStatic(int code); + + String testException(int code); + + User wrapParam(TestRequest request); + + User splitParam(int index, User user); + + String addString(String[] strArr); +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestRequest.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestRequest.java new file mode 100644 index 00000000000..2b0aeeac41e --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestRequest.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.demo.springboot.pojo.server.schema.server; + +import java.util.ArrayList; +import java.util.List; + +public class TestRequest { + private int index; + + private User user; + + private List users = new ArrayList<>(); + + private byte[] data; + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestResponse.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestResponse.java new file mode 100644 index 00000000000..290ab4e9d58 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestResponse.java @@ -0,0 +1,35 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +public class TestResponse { + private User user; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + @Override + public String toString() { + return "TestResponse [user=" + user + "]"; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/User.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/User.java new file mode 100644 index 00000000000..a46291ed9ff --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/User.java @@ -0,0 +1,65 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +public class User { + private String name = "nameA"; + + private int age = 100; + + private int index; + + private String[] names; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String[] getNames() { + return names; + } + + public void setNames(String[] names) { + this.names = names; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public String toString() { + return "User [name=" + name + ", age=" + age + ", index=" + index + "]"; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml index 753ff9a29fe..a2219f31ba4 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/META-INF/spring/pojo.client.bean.xml @@ -22,10 +22,10 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.huawei.com/schema/paas/cse/rpc classpath:META-INF/spring/spring-paas-cse-rpc.xsd"> - + - + diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/application.yml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/application.yml index 91c08652b5d..1d901a66c99 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/application.yml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/main/resources/application.yml @@ -18,24 +18,21 @@ server: port: 8082 -# java-chassis configurations - -APPLICATION_ID: spring-boot-pojotest -service_description: - name: pojoClient - version: 0.0.1 servicecomb: service: - registry: + application: spring-boot-pojotest + name: spring-boot-pojo-client + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 handler: chain: Consumer: - #default: loadbalance - default: bizkeeper-consumer,loadbalance + default: loadbalance isolation: Consumer: enabled: false references: pojo: - version-rule: 0.0.1 \ No newline at end of file + version-rule: 0.0.1 diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/test/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClientIT.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/test/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClientIT.java new file mode 100644 index 00000000000..1312a72739b --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/test/java/org/apache/servicecomb/demo/springboot/pojo/client/PojoClientIT.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.demo.springboot.pojo.client; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = PojoClient.class) +public class PojoClientIT { + + @BeforeEach + public void setUp() throws Exception { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() throws Exception { + PojoClientTest.runTest(); + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/test/java/org/apache/servicecomb/springboot/pojo/client/PojoClientIT.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/test/java/org/apache/servicecomb/springboot/pojo/client/PojoClientIT.java deleted file mode 100644 index 77725ac6dc8..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-client/src/test/java/org/apache/servicecomb/springboot/pojo/client/PojoClientIT.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.springboot.pojo.client; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - -import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; -import org.springframework.boot.SpringApplication; - -public class PojoClientIT { - - @Before - public void setUp() throws Exception { - TestMgr.errors().clear(); - } - - @Test - public void clientGetsNoError() throws Exception { - SpringApplication.run(PojoClient.class); - - assertThat(TestMgr.errors().isEmpty(), is(true)); - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/pom.xml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/pom.xml index 17d56b1498f..60761704af9 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/pom.xml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/pom.xml @@ -25,42 +25,26 @@ org.apache.servicecomb.demo demo-spring-boot-transport - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT - org.apache.servicecomb.springboot.pojo.server.PojoServer + org.apache.servicecomb.demo.springboot.pojo.server.PojoServer + - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - inspector + jakarta.ws.rs + jakarta.ws.rs-api - + org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -68,15 +52,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java deleted file mode 100644 index a84ac020671..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/helloworld/greeter/Hello.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.demo.helloworld.greeter; - -public interface Hello { - public String SayHello(String name); - - public String SayHelloAgain(String name); -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/HelloImpl.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/HelloImpl.java deleted file mode 100644 index e2933daf5cf..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/HelloImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.demo.pojo.server; - -import org.apache.servicecomb.demo.helloworld.greeter.Hello; -import org.apache.servicecomb.provider.pojo.RpcSchema; - -@RpcSchema(schemaId = "helloworld.Greeter") -public class HelloImpl implements Hello { - - @Override - public String SayHello(String name) { - return "Hello Message fast"; - } - - @Override - public String SayHelloAgain(String name) { - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return "Hello Message slow"; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java deleted file mode 100644 index c842f929456..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/pojo/server/TestImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * 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.demo.pojo.server; - -import java.util.Arrays; -import java.util.List; - -import org.apache.servicecomb.demo.server.Test; -import org.apache.servicecomb.demo.server.TestRequest; -import org.apache.servicecomb.demo.server.User; -import org.apache.servicecomb.provider.pojo.RpcSchema; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -@RpcSchema(schemaId = "server") -public class TestImpl implements Test { - @Override - public String testStringArray(String[] arr) { - return String.format("arr is '%s'", Arrays.toString(arr)); - } - - @Override - public String getTestString(String code) { - return String.format("code is '%s'", String.valueOf(code)); - } - - @Override - public String postTestStatic(int code) { - return null; - } - - private User doTest(int index, User user, List users, byte[] data) { - if (user == null) { - user = new User(); - } - - user.setIndex(index); - - int userCount = (users == null) ? 0 : users.size(); - user.setName(user.getName() + ", users count:" + userCount); - return user; - } - - @Override - public String testException(int code) { - String strCode = String.valueOf(code); - switch (code) { - case 200: - return strCode; - case 456: - throw new InvocationException(code, strCode, strCode + " error"); - case 556: - throw new InvocationException(code, strCode, Arrays.asList(strCode + " error")); - case 557: - throw new InvocationException(code, strCode, Arrays.asList(Arrays.asList(strCode + " error"))); - default: - break; - } - - return "not expected"; - } - - @Override - public User splitParam(int index, User user) { - return doTest(index, user, null, null); - } - - @Override - public User wrapParam(TestRequest request) { - if (request == null) { - return null; - } - return doTest(request.getIndex(), request.getUser(), request.getUsers(), request.getData()); - } - - @Override - public String addString(String[] strArr) { - String result = Arrays.toString(strArr); - System.out.println("addString: " + result); - return result; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/Test.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/Test.java deleted file mode 100644 index d853caffc13..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/Test.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.demo.server; - -public interface Test { - String testStringArray(String[] arr); - - String getTestString(String code); - - String postTestStatic(int code); - - String testException(int code); - - User wrapParam(TestRequest request); - - User splitParam(int index, User user); - - String addString(String[] strArr); -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/TestRequest.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/TestRequest.java deleted file mode 100644 index 6f622686271..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/TestRequest.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.demo.server; - -import java.util.ArrayList; -import java.util.List; - -public class TestRequest { - private int index; - - private User user; - - private List users = new ArrayList<>(); - - private byte[] data; - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - public List getUsers() { - return users; - } - - public void setUsers(List users) { - this.users = users; - } - - public byte[] getData() { - return data; - } - - public void setData(byte[] data) { - this.data = data; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/TestResponse.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/TestResponse.java deleted file mode 100644 index c6baa8e0078..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/TestResponse.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.demo.server; - -public class TestResponse { - private User user; - - public User getUser() { - return user; - } - - public void setUser(User user) { - this.user = user; - } - - @Override - public String toString() { - return "TestResponse [user=" + user + "]"; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/User.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/User.java deleted file mode 100644 index e7d4e94d40d..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/server/User.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.demo.server; - -public class User { - private String name = "nameA"; - - private int age = 100; - - private int index; - - private String[] names; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String[] getNames() { - return names; - } - - public void setNames(String[] names) { - this.names = names; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - @Override - public String toString() { - return "User [name=" + name + ", age=" + age + ", index=" + index + "]"; - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/springboot/pojo/server/PojoServer.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/PojoServer.java similarity index 89% rename from demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/springboot/pojo/server/PojoServer.java rename to demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/PojoServer.java index 4c59a3c9a37..30af50bf5f5 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/springboot/pojo/server/PojoServer.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/PojoServer.java @@ -15,15 +15,13 @@ * limitations under the License. */ -package org.apache.servicecomb.springboot.pojo.server; +package org.apache.servicecomb.demo.springboot.pojo.server; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class PojoServer { public static void main(final String[] args) throws Exception { diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/handler/MyHandler.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/handler/MyHandler.java new file mode 100644 index 00000000000..09d2e2eb06d --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/handler/MyHandler.java @@ -0,0 +1,61 @@ +/* + * 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.demo.springboot.pojo.server.handler; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.demo.springboot.pojo.server.schema.server.User; +import org.apache.servicecomb.swagger.invocation.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +@Component +public class MyHandler extends AbstractFilter implements ProviderFilter { + + private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class); + + public static final String SPLITPARAM_RESPONSE_USER_SUFFIX = "(modified by MyHandler)"; + + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 100; + } + + @Override + public String getName() { + return "test-my-filter"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + LOGGER.info("If you see this log, that means this demo project has been converted to ServiceComb framework."); + + return nextNode.onFilter(invocation).whenComplete((response, throwable) -> { + if (invocation.getOperationMeta().getSchemaQualifiedName().equals("server.splitParam")) { + User user = response.getResult(); + user.setName(user.getName() + SPLITPARAM_RESPONSE_USER_SUFFIX); + } + }); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/greeter/Hello.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/greeter/Hello.java new file mode 100644 index 00000000000..7279c9fede1 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/greeter/Hello.java @@ -0,0 +1,24 @@ +/* + * 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.demo.springboot.pojo.server.schema.greeter; + +public interface Hello { + String SayHello(String name); + + String SayHelloAgain(String name); +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/HelloImpl.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/HelloImpl.java new file mode 100644 index 00000000000..4bf9381a738 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/HelloImpl.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.demo.springboot.pojo.server.schema.server; + +import org.apache.servicecomb.demo.springboot.pojo.server.schema.greeter.Hello; +import org.apache.servicecomb.provider.pojo.RpcSchema; + +@RpcSchema(schemaId = "helloworld.Greeter") +public class HelloImpl implements Hello { + + @Override + public String SayHello(String name) { + return "Hello Message fast"; + } + + @Override + public String SayHelloAgain(String name) { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return "Hello Message slow"; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/Test.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/Test.java new file mode 100644 index 00000000000..6542be49ffc --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/Test.java @@ -0,0 +1,34 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +public interface Test { + String testStringArray(String[] arr); + + String getTestString(String code); + + String postTestStatic(int code); + + String testException(int code); + + User wrapParam(TestRequest request); + + User splitParam(int index, User user); + + String addString(String[] strArr); +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestImpl.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestImpl.java new file mode 100644 index 00000000000..6b9622a0804 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestImpl.java @@ -0,0 +1,93 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +import java.util.Arrays; +import java.util.List; + +import org.apache.servicecomb.provider.pojo.RpcSchema; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +@RpcSchema(schemaId = "server") +public class TestImpl implements Test { + @Override + public String testStringArray(String[] arr) { + return String.format("arr is '%s'", Arrays.toString(arr)); + } + + @Override + public String getTestString(String code) { + return String.format("code is '%s'", code); + } + + @Override + public String postTestStatic(int code) { + return null; + } + + private User doTest(int index, User user, List users, byte[] data) { + if (user == null) { + user = new User(); + } + + user.setIndex(index); + + int userCount = (users == null) ? 0 : users.size(); + user.setName(user.getName() + ", users count:" + userCount); + return user; + } + + @Override + public String testException(int code) { + String strCode = String.valueOf(code); + switch (code) { + case 200: + return strCode; + case 456: + throw new InvocationException(code, strCode, strCode + " error"); + case 556: + throw new InvocationException(code, strCode, Arrays.asList(strCode + " error")); + case 557: + throw new InvocationException(code, strCode, Arrays.asList(Arrays.asList(strCode + " error"))); + default: + break; + } + + return "not expected"; + } + + @Override + public User splitParam(int index, User user) { + return doTest(index, user, null, null); + } + + @Override + public User wrapParam(TestRequest request) { + if (request == null) { + return null; + } + return doTest(request.getIndex(), request.getUser(), request.getUsers(), request.getData()); + } + + @Override + public String addString(String[] strArr) { + String result = Arrays.toString(strArr); + System.out.println("addString: " + result); + return result; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestRequest.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestRequest.java new file mode 100644 index 00000000000..2b0aeeac41e --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestRequest.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.demo.springboot.pojo.server.schema.server; + +import java.util.ArrayList; +import java.util.List; + +public class TestRequest { + private int index; + + private User user; + + private List users = new ArrayList<>(); + + private byte[] data; + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestResponse.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestResponse.java new file mode 100644 index 00000000000..290ab4e9d58 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/TestResponse.java @@ -0,0 +1,35 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +public class TestResponse { + private User user; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + @Override + public String toString() { + return "TestResponse [user=" + user + "]"; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/User.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/User.java new file mode 100644 index 00000000000..a46291ed9ff --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/demo/springboot/pojo/server/schema/server/User.java @@ -0,0 +1,65 @@ +/* + * 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.demo.springboot.pojo.server.schema.server; + +public class User { + private String name = "nameA"; + + private int age = 100; + + private int index; + + private String[] names; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String[] getNames() { + return names; + } + + public void setNames(String[] names) { + this.names = names; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @Override + public String toString() { + return "User [name=" + name + ", age=" + age + ", index=" + index + "]"; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/handler/MyHandler.java b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/handler/MyHandler.java deleted file mode 100644 index 6719d03780d..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/java/org/apache/servicecomb/handler/MyHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.handler; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.demo.server.User; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MyHandler implements Handler { - - private static final Logger LOGGER = LoggerFactory.getLogger(MyHandler.class); - - public static final String SPLITPARAM_RESPONSE_USER_SUFFIX = "(modified by MyHandler)"; - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - LOGGER.info("If you see this log, that means this demo project has been converted to ServiceComb framework."); - - invocation.next(response -> { - if (invocation.getOperationMeta().getSchemaQualifiedName().equals("server.splitParam")) { - User user = response.getResult(); - user.setName(user.getName() + SPLITPARAM_RESPONSE_USER_SUFFIX); - asyncResp.handle(response); - } else { - asyncResp.handle(response); - } - }); - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/application.yml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/application.yml index 0d121e96891..e7c0ccf1da0 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/application.yml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/application.yml @@ -18,19 +18,13 @@ server: port: 8080 -# java-chassis configurations - -APPLICATION_ID: spring-boot-pojotest -service_description: - name: pojo - version: 0.0.1 servicecomb: service: - registry: + application: spring-boot-pojotest + name: spring-boot-pojo-server + version: 0.0.1 + registry: + sc: address: http://127.0.0.1:30100 rest: address: 0.0.0.0:8080 - handler: - chain: - Provider: - default: myhandler diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/cse.handler.xml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/cse.handler.xml deleted file mode 100644 index e4838960750..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/helloworld.Greeter.yaml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/helloworld.Greeter.yaml deleted file mode 100644 index d503f154ce0..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/helloworld.Greeter.yaml +++ /dev/null @@ -1,74 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: helloworld.Greeter - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.helloworld.greeter.Hello - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest/helloworld.Greeter -produces: - - application/json - -paths: - /SayHello: - post: - operationId: SayHello - parameters: - - name: name - in: body - required: true - schema: - type: string - responses: - "200": - description: asdf - schema: - type: string - default: - description: asf - schema: - type: string - /SayHelloAgain: - post: - operationId: SayHelloAgain - parameters: - - name: name - in: body - required: true - schema: - type: string - responses: - "200": - description: asdf - schema: - type: string - default: - description: asf - schema: - type: string diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/server.yaml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/server.yaml deleted file mode 100644 index 97592353956..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/server.yaml +++ /dev/null @@ -1,197 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: cse test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.server.Test - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest -produces: - - application/json - -paths: - /testStringArray: - get: - operationId: testStringArray - parameters: - - name: arr - in: query - required: true - type: array - items: - type: string - responses: - "200": - description: asdf - schema: - type: string - /testStatic: - get: - operationId: getTestString - parameters: - - name: code - in: query - required: false - type: string - responses: - "200": - description: asdf - schema: - type: string - post: - operationId: postTestStatic - parameters: - - name: code - in: query - required: true - type: integer - format: int32 - responses: - "200": - description: asdf - schema: - type: string - /testException/{code}: - get: - operationId: testException - parameters: - - name: code - in: path - required: true - type: integer - format: int32 - responses: - "200": - description: asdf - schema: - type: string - 456: - description: asdf - schema: - type: string - 556: - description: asdf - schema: - type: array - items: - type: string - 557: - description: asdf - schema: - type: array - items: - type: array - items: - type: string - /splitParam: - post: - operationId: splitParam - parameters: - - name: index - in: query - required: true - type: number - - name: user - in: body - schema: - $ref: '#/definitions/User' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - /wrapParam: - post: - operationId: wrapParam - parameters: - - name: request - in: body - required: false - schema: - $ref: '#/definitions/TestRequest' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - /addstring: - delete: - operationId: addString - parameters: - - name: strArr - in: query - required: true - type: array - items: - type: string - responses: - "200": - description: add string - schema: - type: string - -definitions: - Error: - type: object - x-java-class: org.apache.servicecomb.core.exception.CommonExceptionData - properties: - message: - type: string - TestRequest: - type: object - properties: - index: - type: number - user: - $ref: '#/definitions/User' - users: - type: array - items: - $ref: '#/definitions/User' - data: - type: string - format: byte - User: - type: object - properties: - name: - type: string - age: - type: number - index: - type: number - x-java-class: "org.apache.servicecomb.demo.server.User" \ No newline at end of file diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/smartcare.yaml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/smartcare.yaml deleted file mode 100644 index 49a8ac93e72..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/smartcare.yaml +++ /dev/null @@ -1,135 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: smartcare test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.smartcare.SmartCare - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest/plat/meta/v1 -produces: - - application/json - -paths: - /applications: - post: - operationId: addApplication - parameters: - - name: application - in: body - required: true - schema: - $ref: '#/definitions/Application' - responses: - 201: - description: success - schema: - $ref: '#/definitions/Response' - 400: - description: error - schema: - $ref: '#/definitions/Response' - 500: - description: error - schema: - $ref: '#/definitions/Response' - - /applications/{appName}: - delete: - operationId: delApplication - parameters: - - name: appName - in: path - required: true - type: string - responses: - 201: - description: success - schema: - $ref: '#/definitions/Response' - 400: - description: error - schema: - $ref: '#/definitions/Response' - 500: - description: error - schema: - $ref: '#/definitions/Response' - - -definitions: - Application: - type: object - properties: - name: - type: string - labelEN: - type: string - labelCH: - type: string - defaultGroup: - type: string - version: - type: string - dynamicFlag: - type: boolean - groups: - type: array - items: - $ref: '#/definitions/Group' - required: - - name - - defaultGroup - - version - - dynamicFlag - - groups - - Group: - type: object - properties: - name: - type: string - labelEN: - type: string - labelCH: - type: string - required: - - name - - Response: - type: object - x-java-class: org.apache.servicecomb.demo.smartcare.Response - properties: - resultCode: - type: integer - format: int32 - resultMessage: - type: string - required: - - resultCode - diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/tcc-server.yaml b/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/tcc-server.yaml deleted file mode 100644 index 4af831b88d8..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-pojo-server/src/main/resources/microservices/pojo/tcc-server.yaml +++ /dev/null @@ -1,108 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# this is an example of the Uber API -# as a demonstration of an API spec in YAML -swagger: '2.0' -info: - title: cse test - version: 1.0.0 - x-java-interface: org.apache.servicecomb.demo.tccserver.TestTcc - -# the domain of the service -#host: api.uber.com - -# array of all schemes that your API supports -#schemes: -# - https - -# will be prefixed to all paths -basePath: /pojo/rest/tcc-server -produces: - - application/json - -paths: - /splitParam: - post: - operationId: splitParam - parameters: - - name: index - in: query - required: true - type: number - - name: user - in: body - schema: - $ref: '#/definitions/User' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - /wrapParam: - post: - operationId: wrapParam - parameters: - - name: TestRequest - in: body - required: true - schema: - $ref: '#/definitions/TestRequest' - responses: - "200": - description: asdf - schema: - $ref: '#/definitions/User' - default: - description: asf - schema: - $ref: '#/definitions/Error' - -definitions: - Error: - type: object - x-java-class: org.apache.servicecomb.core.exception.CommonExceptionData - properties: - message: - type: string - TestRequest: - type: object - properties: - index: - type: number - user: - $ref: '#/definitions/User' - users: - type: array - items: - $ref: '#/definitions/User' - data: - type: string - format: byte - User: - type: object - properties: - name: - type: string - age: - type: number - index: - type: number diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/pom.xml b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/pom.xml index 42f2fb28bde..edd73c1428b 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/pom.xml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/pom.xml @@ -26,42 +26,15 @@ org.apache.servicecomb.demo demo-spring-boot-transport - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT + org.apache.servicecomb.demo - springmvc-client - - - log4j - log4j - - - org.slf4j - slf4j-log4j12 - - + demo-schema - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - docker @@ -69,6 +42,83 @@ demo-spring-boot-springmvc-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/PlaceHolderSchemaTest.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/PlaceHolderSchemaTest.java index dc616c6cff5..f7e066497d1 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/PlaceHolderSchemaTest.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/PlaceHolderSchemaTest.java @@ -21,13 +21,13 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class PlaceHolderSchemaTest implements CategorizedTestCase { @Override - public void testAllTransport() throws Exception { - RestTemplate template = RestTemplateBuilder.create(); + public void testRestTransport() throws Exception { + RestOperations template = RestTemplateBuilder.create(); String result = template.getForObject("servicecomb://springmvc/placeholder/schema?name=test", String.class); TestMgr.check("test", result); } diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/ReactiveStreamIT.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/ReactiveStreamIT.java new file mode 100644 index 00000000000..c9c1957ddf5 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/ReactiveStreamIT.java @@ -0,0 +1,113 @@ +/* + * 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.springboot.springmvc.client; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.springboot.springmvc.client.ThirdSvcConfiguration.ReactiveStreamClient; +import org.apache.servicecomb.springboot.springmvc.client.ThirdSvcConfiguration.ReactiveStreamClient.Model; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +public class ReactiveStreamIT implements CategorizedTestCase { + @Autowired + @Qualifier("reactiveStreamProvider") + ReactiveStreamClient reactiveStreamProvider; + + @Override + public void testRestTransport() throws Exception { + testSseString(reactiveStreamProvider); + testSseModel(reactiveStreamProvider); + } + + private void testSseModel(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseModel(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(Model s) { + buffer.append(s.getName()).append(s.getAge()); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("jack0jack1jack2jack3jack4", buffer.toString()); + } + + private void testSseString(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseString(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(String s) { + buffer.append(s); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("abc", buffer.toString()); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/SpringMvcClient.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/SpringMvcClient.java new file mode 100644 index 00000000000..8ce77d9818e --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/SpringMvcClient.java @@ -0,0 +1,46 @@ +/* + * 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.springboot.springmvc.client; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +/** + * SpringMvcClient + * + * + */ +@SpringBootApplication +public class SpringMvcClient { + + public static void main(final String[] args) throws Exception { + + new SpringApplicationBuilder().sources(SpringMvcClient.class).web(WebApplicationType.SERVLET).build().run(args); + + runTest(); + } + + public static void runTest() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("springmvc"); + + TestMgr.summary(); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/SpringmvcClient.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/SpringmvcClient.java deleted file mode 100644 index 5e092d8bb1f..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/SpringmvcClient.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.springboot.springmvc.client; - -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -/** - * SpringmvcClient - * - * - */ -@SpringBootApplication -@EnableServiceComb -public class SpringmvcClient { - - public static void main(final String[] args) throws Exception { - - new SpringApplicationBuilder().sources(SpringmvcClient.class).web(WebApplicationType.SERVLET).build().run(args); - - org.apache.servicecomb.demo.springmvc.client.SpringmvcClient.run(); - - TestMgr.summary(); - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/TestAnnotationsSchema.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/TestAnnotationsSchema.java new file mode 100644 index 00000000000..7d77fa1be35 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/TestAnnotationsSchema.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.springboot.springmvc.client; + +import org.apache.http.HttpStatus; +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.controller.Person; +import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; +import org.apache.servicecomb.provider.springmvc.reference.UrlWithServiceNameClientHttpRequestFactory; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +public class TestAnnotationsSchema implements CategorizedTestCase { + private static final String microserviceName = "springmvc"; + + private static final RestTemplate templateUrlWithServiceName = new CseRestTemplate(); + + @Override + public void testRestTransport() throws Exception { + templateUrlWithServiceName.setRequestFactory(new UrlWithServiceNameClientHttpRequestFactory()); + testRequiredBody(templateUrlWithServiceName, microserviceName); + testRegExpPath(); + } + + private void testRegExpPath() { + String prefix = "cse://" + microserviceName; + String result = templateUrlWithServiceName.getForObject(prefix + "/annotations/testRegExpPath/a?name={name}", + String.class, "a"); + TestMgr.check("a", result); + result = templateUrlWithServiceName.getForObject(prefix + "/annotations/testRegExpPath/a/b?name={name}", + String.class, "ab"); + TestMgr.check("ab", result); + result = templateUrlWithServiceName.getForObject(prefix + "/annotations/testRegExpPath/a/b/c?name={name}", + String.class, "abc"); + TestMgr.check("abc", result); + } + + private static void testRequiredBody(RestTemplate template, String microserviceName) { + String prefix = "cse://" + microserviceName; + Person user = new Person(); + + TestMgr.check("No user data found", + template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", + user, + String.class, + "ha")); + + user.setName("world"); + TestMgr.check("ha world", + template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", + user, + String.class, + "ha")); + + TestMgr.check("No user data found", + template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", + null, + String.class, + "ha")); + + TestMgr.check("No user name found", + template.postForObject(prefix + "/annotations/say", + "", + String.class, + "ha")); + TestMgr.check("test", + template.postForObject(prefix + "/annotations/say", + "test", + String.class, + "ha")); + + try { + template.postForObject(prefix + "/annotations/testRequiredBody", + null, + String.class); + TestMgr.fail("should fail"); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/ThirdSvcConfiguration.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/ThirdSvcConfiguration.java new file mode 100644 index 00000000000..098a36828ed --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/ThirdSvcConfiguration.java @@ -0,0 +1,75 @@ +/* + * 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.springboot.springmvc.client; + +import org.apache.servicecomb.provider.pojo.Invoker; +import org.reactivestreams.Publisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@Configuration +public class ThirdSvcConfiguration { + @RequestMapping(path = "/") + public interface ReactiveStreamClient { + 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") + Publisher sseString(); + + @GetMapping("/sseModel") + Publisher sseModel(); + } + + @Bean("reactiveStreamProvider") + public ReactiveStreamClient reactiveStreamProvider() { + return Invoker.createProxy("springmvc", "ReactiveStreamController", ReactiveStreamClient.class); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/UploadDownloadSchemaTest.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/UploadDownloadSchemaTest.java new file mode 100644 index 00000000000..18054cf4f4a --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/java/org/apache/servicecomb/springboot/springmvc/client/UploadDownloadSchemaTest.java @@ -0,0 +1,69 @@ +/* + * 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.springboot.springmvc.client; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.io.FileUtils; +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +@Component +public class UploadDownloadSchemaTest implements CategorizedTestCase { + RestOperations restOperations = RestTemplateBuilder.create(); + + @Override + public void testRestTransport() throws Exception { + testEmptyFileUploadWork(); + testNonEmptyFileUploadWork(); + } + + private void testNonEmptyFileUploadWork() throws Exception { + String file2Content = " bonjour"; + File someFile = File.createTempFile("upload2", ".txt"); + FileUtils.writeStringToFile(someFile, file2Content, StandardCharsets.UTF_8, false); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + Map params = new HashMap<>(); + params.put("name", "test"); + params.put("file", someFile); + HttpEntity> entity = new HttpEntity<>(params, headers); + String url = "servicecomb://springmvc/up/down/upload"; + String result = restOperations.postForObject(url, entity, String.class); + TestMgr.check("test; bonjour", result); + } + + private void testEmptyFileUploadWork() { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + Map params = new HashMap<>(); + params.put("name", "test"); + HttpEntity> entity = new HttpEntity<>(params, headers); + String url = "servicecomb://springmvc/up/down/upload"; + String result = restOperations.postForObject(url, entity, String.class); + TestMgr.check("test;", result); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/application.yml b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/application.yml index a036aacdf79..68ab69a48cb 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/application.yml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/application.yml @@ -15,11 +15,16 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: springmvcboottest - server: port: 8999 servicecomb: + service: + application: springmvcboottest + name: springmvcclient + version: 0.0.3 + registry: + sc: + address: http://127.0.0.1:30100 test: vert: - transport: false \ No newline at end of file + transport: false diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/microservice.yaml b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/microservice.yaml new file mode 100644 index 00000000000..587c6bbf55a --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/main/resources/microservice.yaml @@ -0,0 +1,21 @@ +## --------------------------------------------------------------------------- +## 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-config-order: 100 + +3rd-svc: + urls: + - rest://localhost:8080?sslEnabled=false diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/test/java/org/apache/servicecomb/springboot/springmvc/client/SpringMvcClientIT.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/test/java/org/apache/servicecomb/springboot/springmvc/client/SpringMvcClientIT.java new file mode 100644 index 00000000000..ae3ef5b0044 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/test/java/org/apache/servicecomb/springboot/springmvc/client/SpringMvcClientIT.java @@ -0,0 +1,47 @@ +/* + * 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.springboot.springmvc.client; + +import org.apache.servicecomb.demo.TestMgr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = SpringMvcClient.class) +public class SpringMvcClientIT { + @BeforeEach + public void setUp() throws Exception { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() throws Exception { + try { + SpringMvcClient.runTest(); + + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } catch (Throwable e) { + e.printStackTrace(); + Assertions.fail("test case failed, message=" + e.getMessage()); + } + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/test/java/org/apache/servicecomb/springboot/springmvc/client/SpringmvcClientIT.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/test/java/org/apache/servicecomb/springboot/springmvc/client/SpringmvcClientIT.java deleted file mode 100644 index 279d6dafcb3..00000000000 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-client/src/test/java/org/apache/servicecomb/springboot/springmvc/client/SpringmvcClientIT.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.springboot.springmvc.client; - -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -import org.apache.servicecomb.demo.TestMgr; -import org.junit.Before; -import org.junit.Test; - -public class SpringmvcClientIT { - @Before - public void setUp() throws Exception { - TestMgr.errors().clear(); - } - - @Test - public void clientGetsNoError() throws Exception { - try { - SpringmvcClient.main(new String[0]); - - assertThat(TestMgr.errors().isEmpty(), is(true)); - } catch (Throwable e) { - e.printStackTrace(); - fail("test case failed, message=" + e.getMessage()); - } - } -} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/pom.xml b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/pom.xml index ba541dd630b..efa0723b59a 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/pom.xml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/pom.xml @@ -26,22 +26,12 @@ org.apache.servicecomb.demo demo-spring-boot-transport - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT org.apache.servicecomb.demo - springmvc-server - - - log4j - log4j - - - org.slf4j - slf4j-log4j12 - - + demo-schema @@ -50,19 +40,6 @@ org.springframework.boot spring-boot-maven-plugin - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - @@ -70,15 +47,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/AnnotationsSchema.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/AnnotationsSchema.java new file mode 100644 index 00000000000..b1bcaba83ed --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/AnnotationsSchema.java @@ -0,0 +1,86 @@ +/* + * 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.springboot.springmvc.server; + +import org.apache.servicecomb.demo.controller.Person; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.ws.rs.core.MediaType; + +@RestSchema(schemaId = "annotations") +@RequestMapping(path = "/springmvc/annotations", produces = MediaType.APPLICATION_JSON) +public class AnnotationsSchema { + @GetMapping(path = "/add") + public int add(@RequestParam(name = "a", defaultValue = "10") int a, + @RequestParam(name = "b", defaultValue = "10") int b) { + return a + b; + } + + @RequestMapping(path = "/sayhei", method = RequestMethod.GET) + public String sayHei(@RequestHeader(name = "name", defaultValue = "test") String name) { + return "hei " + name; + } + + @GetMapping(path = "/sayhi") + @Parameters({ + @Parameter(name = "name", in = ParameterIn.QUERY, schema = @Schema(type = "string", defaultValue = "test")), + @Parameter(name = "age", in = ParameterIn.QUERY, schema = @Schema(type = "integer", defaultValue = "20")) + }) + public String sayHi(String name, int age) { + return "hi " + name + " your age is : " + age; + } + + @RequestMapping(path = "/saysomething", method = RequestMethod.POST) + public String saySomething(String prefix, @RequestBody(required = false) Person user) { + if (user == null || user.getName() == null || user.getName().isEmpty()) { + return "No user data found"; + } + return prefix + " " + user.getName(); + } + + @RequestMapping(path = "/say", method = RequestMethod.POST) + public String say(@RequestBody(required = false) String user) { + if (user == null || user.isEmpty()) { + return "No user name found"; + } + return user; + } + + @RequestMapping(path = "/testRequiredBody", method = RequestMethod.POST) + public String testRequiredBody(@RequestBody(required = true) Person user) { + if (user == null) { + return "Should not happen"; + } + return user.getName(); + } + + @RequestMapping(path = "/testRegExpPath/{path: .+}", method = RequestMethod.GET) + public String testRegExpPath(@RequestParam("name") String name) { + return name; + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/ReactiveStreamController.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/ReactiveStreamController.java new file mode 100644 index 00000000000..e82028d1286 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/ReactiveStreamController.java @@ -0,0 +1,75 @@ +/* + * 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.springboot.springmvc.server; + + +import java.util.concurrent.TimeUnit; + +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 = "/") +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-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/SpringmvcServer.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/SpringmvcServer.java index 311bd535874..acbd39e0cc4 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/SpringmvcServer.java +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/SpringmvcServer.java @@ -18,17 +18,15 @@ package org.apache.servicecomb.springboot.springmvc.server; import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration; import org.springframework.boot.builder.SpringApplicationBuilder; -import com.netflix.config.DynamicPropertyFactory; - -@SpringBootApplication -@EnableServiceComb +@SpringBootApplication(exclude = {WebMvcAutoConfiguration.class}) public class SpringmvcServer { private static final Logger LOGGER = LoggerFactory.getLogger(SpringmvcServer.class); @@ -39,11 +37,13 @@ public static void main(final String[] args) throws Exception { } private static void assertPropertyCorrect() { - String result = DynamicPropertyFactory.getInstance() - .getStringProperty("test.unresolved.placeholder", null).get(); - if (!"jdbc:postgresql://${ip}:${port}/pt".equals(result)) { - LOGGER.error("tests for configuration error, stop"); - SCBEngine.getInstance().destroy(); + // spring environment will fail for unresolved placeholder property + try { + LegacyPropertyFactory.getStringProperty("test.unresolved.placeholder"); + } catch (IllegalArgumentException e) { + return; } + LOGGER.error("tests for configuration error, stop"); + SCBEngine.getInstance().destroy(); } } diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/UploadDownloadSchema.java b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/UploadDownloadSchema.java new file mode 100644 index 00000000000..ec80bedbec4 --- /dev/null +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/java/org/apache/servicecomb/springboot/springmvc/server/UploadDownloadSchema.java @@ -0,0 +1,47 @@ +/* + * 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.springboot.springmvc.server; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.apache.commons.io.IOUtils; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.ws.rs.core.MediaType; + +@RestSchema(schemaId = "UploadDownloadSchema") +@RequestMapping(path = "/up/down") +public class UploadDownloadSchema { + @PostMapping(path = "/upload", consumes = MediaType.MULTIPART_FORM_DATA) + public String fileUpload(@RequestPart MultipartFile file, @RequestPart(value = "name") String name) throws Exception { + StringBuilder result = new StringBuilder(); + result.append(name).append(";"); + if (file == null || file.isEmpty()) { + return result.toString(); + } + try (InputStream is = file.getInputStream()) { + result.append(IOUtils.toString(is, StandardCharsets.UTF_8)); + } + return result.toString(); + } +} diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/application.yml b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/application.yml index 41650780cba..7cd484f51bb 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/application.yml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/application.yml @@ -15,8 +15,6 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: springmvcboottest - server: port: 8080 @@ -26,6 +24,13 @@ test: schema: placeholder/schema servicecomb: + service: + application: springmvcboottest + name: springmvc + version: 0.0.3 + registry: + sc: + address: http://127.0.0.1:30100 test: vert: - transport: false \ No newline at end of file + transport: false diff --git a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/microservice.yaml b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/microservice.yaml index 141c0d4f10c..c3738a1dd60 100644 --- a/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/microservice.yaml +++ b/demo/demo-spring-boot-transport/demo-spring-boot-springmvc-server/src/main/resources/microservice.yaml @@ -17,4 +17,25 @@ servicecomb: config: - ignoreResolveFailure: true \ No newline at end of file + ignoreResolveFailure: true + + service: + registry: + registerPath: true + address: http://127.0.0.1:9980,http://127.0.0.1:30100 + client: + timeout: + idle: 60 + watch: 60 + instance: + healthCheck: + interval: 3 + pull: + interval: 10 + watch: true + autodiscovery: true + uploads: + directory: target + + rest: + address: 0.0.0.0:8080?sslEnabled=false diff --git a/demo/demo-spring-boot-transport/pom.xml b/demo/demo-spring-boot-transport/pom.xml index 001f4a9b83f..bd7650a3f26 100644 --- a/demo/demo-spring-boot-transport/pom.xml +++ b/demo/demo-spring-boot-transport/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-spring-boot-transport Java Chassis::Demo::Spring Boot::Transport @@ -35,10 +35,33 @@ + + org.apache.servicecomb + solution-basic + org.apache.servicecomb java-chassis-spring-boot-starter-servlet + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.apache.logging.log4j + log4j-slf4j-impl + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + + org.apache.servicecomb registry-service-center diff --git a/demo/demo-springmvc/pom.xml b/demo/demo-springmvc/pom.xml index e30707a44cd..c307aa7741b 100644 --- a/demo/demo-springmvc/pom.xml +++ b/demo/demo-springmvc/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb.demo demo-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT demo-springmvc Java Chassis::Demo::Spring MVC @@ -32,17 +32,33 @@ springmvc-client + + org.apache.servicecomb.demo + demo-schema + org.apache.servicecomb registry-service-center - log4j - log4j + org.apache.servicecomb + registry-local + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-core diff --git a/demo/demo-springmvc/springmvc-client/pom.xml b/demo/demo-springmvc/springmvc-client/pom.xml index a67ddf0c1cc..17b7bbcd709 100644 --- a/demo/demo-springmvc/springmvc-client/pom.xml +++ b/demo/demo-springmvc/springmvc-client/pom.xml @@ -23,72 +23,18 @@ org.apache.servicecomb.demo demo-springmvc - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT springmvc-client Java Chassis::Demo::Spring MVC::Client - - org.apache.servicecomb.demo - demo-schema - - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - provider-pojo - - - org.apache.servicecomb - config-cc - - - org.apache.servicecomb - handler-fault-injection - - - - org.apache.servicecomb.demo - demo-signature - - - org.apache.servicecomb - foundation-test-scaffolding - - org.apache.servicecomb.demo.springmvc.client.SpringmvcClient + org.apache.servicecomb.demo.springmvc.SpringmvcClient - - - - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-run-config - ${project.version} - - - - - - + docker @@ -96,6 +42,83 @@ springmvc-server + + + + io.fabric8 + docker-maven-plugin + + + + servicecomb/service-center + service-center + + + server is ready + + + 30100 + + + + + + 30100:30100 + + + + + ${demo.service.name}:${project.version} + ${demo.service.name} + + + + -Dservicecomb.registry.sc.address=http://sc.servicecomb.io:30100 + + /maven/maven/${demo.service.name}-${project.version}.jar + + + service-center:sc.servicecomb.io + + + ServiceComb is ready + + + 8080 + + + + + + 7070:7070 + 8080:8080 + + + service-center + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + io.fabric8 diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/SpringmvcClient.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/SpringmvcClient.java new file mode 100644 index 00000000000..b827884d323 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/SpringmvcClient.java @@ -0,0 +1,519 @@ +/* + * 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.demo.springmvc; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.HttpStatus; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.DemoConst; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.controller.Person; +import org.apache.servicecomb.demo.springmvc.client.CodeFirstRestTemplateSpringmvc; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; +import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.provider.springmvc.reference.UrlWithProviderPrefixClientHttpRequestFactory; +import org.apache.servicecomb.provider.springmvc.reference.UrlWithServiceNameClientHttpRequestFactory; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.ImportResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestOperations; +import org.springframework.web.client.RestTemplate; + + +@SpringBootApplication +@ImportResource(value = "classpath*:META-INF/spring/*.bean.xml") +public class SpringmvcClient { + private static final Logger LOGGER = LoggerFactory.getLogger(SpringmvcClient.class); + + private static RestTemplate templateUrlWithServiceName = new CseRestTemplate(); + + private static RestTemplate templateUrlWithProviderPrefix = new CseRestTemplate(); + + private static RestOperations restTemplate; + + public static void main(String[] args) { + new SpringApplicationBuilder(SpringmvcClient.class).web(WebApplicationType.NONE).run(args); + + run(); + } + + private static void changeTransport(String microserviceName, String transport) { + InMemoryDynamicPropertiesSource.update("servicecomb.references.transport." + microserviceName, transport); + TestMgr.setMsg(microserviceName, transport); + } + + public static void run() { + try { + runImpl(); + } catch (Throwable e) { + TestMgr.check("success", "failed"); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + LOGGER.info("-------------- last time updated checks(maybe more/less): 1344 -------------"); + } + + private static void runImpl() throws Exception { + testHttpClientsIsOk(); + + templateUrlWithServiceName.setRequestFactory(new UrlWithServiceNameClientHttpRequestFactory()); + restTemplate = RestTemplateBuilder.create(); + templateUrlWithProviderPrefix.setRequestFactory(new UrlWithProviderPrefixClientHttpRequestFactory("/pojo/rest")); + + String prefix = "cse://springmvc"; + String microserviceName = "springmvc"; + + try { + // only works in rest, highway does not have name param, because not defined. + templateUrlWithServiceName.getForObject(prefix + "/controller/sayhi?name=throwexception", String.class); + TestMgr.check("true", "false"); + } catch (Exception e) { + TestMgr.check("true", "true"); + } + try { + // only works in rest, highway does not have name param, because not defined. + templateUrlWithServiceName.getForObject(prefix + "/controller/sayhi?name=throwexception", String.class); + TestMgr.check("true", "false"); + } catch (Exception e) { + TestMgr.check("true", "true"); + } + + testHandler(microserviceName); + CodeFirstRestTemplateSpringmvc codeFirstClient = + BeanUtils.getContext().getBean(CodeFirstRestTemplateSpringmvc.class); + codeFirstClient.testCodeFirst(restTemplate, "springmvc", "/codeFirstSpringmvc/"); + codeFirstClient.testCodeFirst(templateUrlWithProviderPrefix, "springmvc", "/pojo/rest/codeFirstSpringmvc/"); + testAllTransport(microserviceName); + testRestTransport(microserviceName, prefix); + CategorizedTestCaseRunner.runCategorizedTestCase(microserviceName); + } + + private static void testHandler(String microserviceName) { + changeTransport(microserviceName, "rest"); + String prefix = "cse://springmvc"; + String result = templateUrlWithServiceName.getForObject(prefix + "/controller/sayHello1?name=tom", String.class); + TestMgr.check("Hello tom,v", result); + } + + private static void testHttpClientsIsOk() { + TestMgr.check(HttpClients.getClient("http-transport-client") != null, true); + TestMgr.check(HttpClients.getClient("http2-transport-client") != null, true); + + TestMgr.check(HttpClients.getClient("http-transport-client", false) != null, true); + TestMgr.check(HttpClients.getClient("http2-transport-client", false) != null, true); + } + + private static void testRestTransport(String microserviceName, String prefix) { + changeTransport(microserviceName, "rest"); + + testControllerRest(templateUrlWithServiceName, microserviceName); + testSpringMvcDefaultValuesRest(templateUrlWithServiceName, microserviceName); + testSpringMvcDefaultValuesJavaPrimitiveRest(templateUrlWithServiceName, microserviceName); + + HttpHeaders headers = new HttpHeaders(); + headers.set("Accept-Encoding", "gzip"); + HttpEntity entity = new HttpEntity<>(headers); + ResponseEntity entityCompress = + restTemplate.exchange(prefix + + "/codeFirstSpringmvc/sayhi/compressed/{name}/v2", HttpMethod.GET, entity, String.class, "Test"); + TestMgr.check( + "Test sayhi compressed:This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text!", + entityCompress.getBody()); + // if server response is compressed, the content-length header will be removed , so can't check this. + // the transfer-encoding header will be missing when the server is set to not compressed + if (entityCompress.getHeaders().get("transfer-encoding") != null) { + TestMgr.check("chunked", entityCompress.getHeaders().get("transfer-encoding").get(0)); + } + + //0.5.0 later version metrics integration test + @SuppressWarnings("unchecked") + Map metrics = restTemplate.getForObject(prefix + "/scb/metrics", Map.class); + + // TestMgr.check(true, metrics.get("jvm(name=heapUsed,statistic=gauge)") != 0); + TestMgr.check(true, metrics.size() > 0); + + //prometheus integration test + try { + String content = restTemplate + .getForObject("cse://springmvc/codeFirstSpringmvc/prometheusForTest", String.class); + + String application = LegacyPropertyFactory.getStringProperty("servicecomb.service.application", ""); + + TestMgr.check(true, + content.contains( + "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.addDate")); + TestMgr.check(true, + content.contains( + "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.sayHello")); + TestMgr.check(true, + content + .contains("servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.isTrue")); + TestMgr.check(true, + content.contains("servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.add")); + TestMgr.check(true, + content + .contains("servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.sayHi2")); + TestMgr.check(true, content + .contains( + "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.saySomething")); + + String[] metricLines = content.split("\n"); + if (metricLines.length > 0) { + for (String metricLine : metricLines) { + if (!metricLine.startsWith("#")) { + String[] metricKeyAndValue = metricLine.split(" "); + if (!metricKeyAndValue[0].startsWith("jvm") && !metricKeyAndValue[0].startsWith("os")) { + if (Double.parseDouble(metricKeyAndValue[1]) < 0) { + TestMgr.check("true", "false"); + break; + } + } + } + } + } else { + TestMgr.check("true", "false"); + } + } catch (Exception e) { + LOGGER.error("", e); + TestMgr.check("true", "false"); + } + } + + private static void testAllTransport(String microserviceName) { + for (String transport : DemoConst.transports) { + changeTransport(microserviceName, transport); + + TestMgr.setMsg(microserviceName, transport); + + testControllerAllTransport(templateUrlWithServiceName, microserviceName); + + testSpringMvcDefaultValuesAllTransport(templateUrlWithServiceName, microserviceName); + testSpringMvcDefaultValuesJavaPrimitiveAllTransport(templateUrlWithServiceName, microserviceName); + } + } + + private static void testControllerRest(RestTemplate template, String microserviceName) { + String prefix = "cse://" + microserviceName; + + TestMgr.check("hi world [world]", + template.getForObject(prefix + "/controller/sayhi?name=world", + String.class)); + + TestMgr.check("hi world boot [world boot]", + template.getForObject(prefix + "/controller/sayhi?name=world boot", + String.class)); + + TestMgr.check("hi world boot [world boot]", + template.getForObject(prefix + "/controller/sayhi?name=world+boot", + String.class)); + + TestMgr.check("hi world1 [world1]", + template.getForObject(prefix + "/controller/sayhi?name={name}", + String.class, + "world1")); + + TestMgr.check("hi world1+world2 [world1+world2]", + template.getForObject(prefix + "/controller/sayhi?name={name}", + String.class, + "world1+world2")); + + TestMgr.check("hi hi 中国 [hi 中国]", + template.getForObject(prefix + "/controller/sayhi?name={name}", + String.class, + "hi 中国")); + + Map params = new HashMap<>(); + params.put("name", "world2"); + TestMgr.check("hi world2 [world2]", + template.getForObject(prefix + "/controller/sayhi?name={name}", + String.class, + params)); + + try { + template.postForObject(prefix + "/controller/sayhello/{name}", + null, + String.class, + "exception"); + TestMgr.check(true, false); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 503); + } + } + + private static void testControllerAllTransport(RestTemplate template, String microserviceName) { + String prefix = "cse://" + microserviceName; + + TestMgr.check(7, + template.getForObject(prefix + "/controller/add?a=3&b=4", + Integer.class)); + + try { + template.getForObject(prefix + "/controller/add", + Integer.class); + TestMgr.check("failed", "success"); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 400); + } + + TestMgr.check("hello world", + template.postForObject(prefix + "/controller/sayhello/{name}", + null, + String.class, + "world")); + TestMgr.check("hello hello 中国", + template.postForObject(prefix + "/controller/sayhello/{name}", + null, + String.class, + "hello 中国")); + + try { + template.postForObject(prefix + "/controller/sayhello/{name}", + null, + String.class, + "exception"); + TestMgr.check(true, false); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), 503); + } + + HttpHeaders headers = new HttpHeaders(); + headers.add("name", "world"); + @SuppressWarnings("rawtypes") + HttpEntity entity = new HttpEntity<>(null, headers); + ResponseEntity response = template.exchange(prefix + "/controller/sayhei", + HttpMethod.GET, + entity, + String.class); + TestMgr.check("hei world", response.getBody()); + + Person user = new Person(); + user.setName("world"); + TestMgr.check("ha world", + template.postForObject(prefix + "/controller/saysomething?prefix={prefix}", + user, + String.class, + "ha")); + } + + private static void testSpringMvcDefaultValuesRest(RestTemplate template, String microserviceName) { + String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; + String result = template.getForObject(cseUrlPrefix + "/query?d=10", String.class); + TestMgr.check("Hello 20bobo4010", result); + boolean failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); + TestMgr.check("Hello 20bobo40302", result); + + failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + } + + private static void testSpringMvcDefaultValuesAllTransport(RestTemplate template, String microserviceName) { + String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; + //default values + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + MultiValueMap map = new LinkedMultiValueMap<>(); + HttpEntity> request = new HttpEntity<>(map, headers); + String result = template.postForObject(cseUrlPrefix + "/form", request, String.class); + TestMgr.check("Hello 20bobo", result); + + headers = new HttpHeaders(); + HttpEntity entity = new HttpEntity<>(null, headers); + result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); + TestMgr.check("Hello 20bobo30", result); + + result = template.getForObject(cseUrlPrefix + "/query?d=10", String.class); + TestMgr.check("Hello 20bobo4010", result); + boolean failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); + TestMgr.check("Hello 20bobo40302", result); + + failed = false; + result = null; + try { + result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); + } catch (InvocationException e) { + failed = true; + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + TestMgr.check(true, failed); + TestMgr.check(null, result); + + result = template.getForObject(cseUrlPrefix + "/query3?a=30&b=2", String.class); + TestMgr.check("Hello 302", result); + + result = template.getForObject(cseUrlPrefix + "/query3?a=30", String.class); + TestMgr.check("Hello 30null", result); + + //input values + headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity> requestPara = new HttpEntity<>(null, headers); + result = template.postForObject(cseUrlPrefix + "/form?a=30&b=sam", requestPara, String.class); + TestMgr.check("Hello 30sam", result); + + headers = new HttpHeaders(); + headers.add("a", "30"); + headers.add("b", "sam"); + headers.add("c", "40"); + entity = new HttpEntity<>(null, headers); + result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); + TestMgr.check("Hello 30sam40", result); + + result = template.getForObject(cseUrlPrefix + "/query?a=3&b=sam&c=5&d=30", String.class); + TestMgr.check("Hello 3sam530", result); + + result = template.getForObject(cseUrlPrefix + "/query2?a=3&b=4&c=5&d=30&e=2", String.class); + TestMgr.check("Hello 345302", result); + } + + private static void testSpringMvcDefaultValuesJavaPrimitiveAllTransport(RestTemplate template, + String microserviceName) { + String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; + //default values with primitive + String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", null, String.class); + TestMgr.check("Hello 0bobo", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", null, String.class); + TestMgr.check("Hello 0.0false", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", null, String.class); + TestMgr.check("Hello", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", null, String.class); + TestMgr.check("Hello nullnull", result); + + result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); + TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); + + result = template.postForObject(cseUrlPrefix + + "/allprimitivetypes?pBoolean=true&pChar=c&pByte=20&pShort=30&pInt=40&pLong=50&pFloat=60&pDouble=70&pDoubleWrap=80", + null, String.class); + TestMgr.check("Hello true,c,20,30,40,50,60.0,70.0,80.0", result); + } + + private static void testSpringMvcDefaultValuesJavaPrimitiveRest(RestTemplate template, String microserviceName) { + String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; + //default values with primitive + String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", null, String.class); + TestMgr.check("Hello 0bobo", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", null, String.class); + TestMgr.check("Hello 0.0false", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", null, String.class); + TestMgr.check("Hello", result); + + result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", null, String.class); + TestMgr.check("Hello nullnull", result); + + result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); + TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java index 991016a4846..d30edc6b495 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CodeFirstRestTemplateSpringmvc.java @@ -26,16 +26,15 @@ import java.util.HashMap; import java.util.Map; -import javax.servlet.http.Part; - import org.apache.commons.io.FileUtils; -import org.apache.servicecomb.bizkeeper.BizkeeperExceptionUtils; +import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.demo.CodeFirstRestTemplate; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.common.part.FilePart; import org.apache.servicecomb.provider.pojo.Invoker; import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity; -import org.apache.servicecomb.registry.RegistrationManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; @@ -46,7 +45,9 @@ import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; + +import jakarta.servlet.http.Part; @Component public class CodeFirstRestTemplateSpringmvc extends CodeFirstRestTemplate { @@ -73,10 +74,14 @@ interface UploadStreamAndResource { private TestContentType testContentType = new TestContentType(); - private TestBizkeeper testBizkeeper = new TestBizkeeper(); + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + testResponse.setEnvironment(environment); + } @Override - protected void testOnlyRest(String microservcieName, RestTemplate template, String cseUrlPrefix) { + protected void testOnlyRest(String microservcieName, RestOperations template, String cseUrlPrefix) { try { testUpload(template, cseUrlPrefix); } catch (IOException e) { @@ -84,7 +89,6 @@ protected void testOnlyRest(String microservcieName, RestTemplate template, Stri } testResponseEntity("springmvc", template, cseUrlPrefix); testCodeFirstTestFormRest(template, cseUrlPrefix); - testFallback(template, cseUrlPrefix); testResponse.runRest(); testObject.runRest(); @@ -96,7 +100,7 @@ protected void testOnlyRest(String microservcieName, RestTemplate template, Stri } @Override - protected void testOnlyHighway(RestTemplate template, String cseUrlPrefix) { + protected void testOnlyHighway(RestOperations template, String cseUrlPrefix) { testResponse.runHighway(); testObject.runHighway(); testGeneric.runHighway(); @@ -105,22 +109,18 @@ protected void testOnlyHighway(RestTemplate template, String cseUrlPrefix) { } @Override - protected void testAllTransport(String microserviceName, RestTemplate template, String cseUrlPrefix) { + protected void testAllTransport(String microserviceName, RestOperations template, String cseUrlPrefix) { testResponse.runAllTransport(); testObject.runAllTransport(); testGeneric.runAllTransport(); testRestTemplate.runAllTest(); - testBizkeeper.runAllTest(); testResponseEntity("springmvc", template, cseUrlPrefix); testCodeFirstTestForm(template, cseUrlPrefix); - testFallback(template, cseUrlPrefix); super.testAllTransport(microserviceName, template, cseUrlPrefix); } - @SuppressWarnings("deprecation") -// TODO : upgrade to spring 5 will having warning's , we'll fix it later - private void testUpload(RestTemplate template, String cseUrlPrefix) throws IOException { + private void testUpload(RestOperations template, String cseUrlPrefix) throws IOException { String file1Content = "hello world"; File file1 = File.createTempFile("测 试", ".txt"); FileUtils.writeStringToFile(file1, file1Content, StandardCharsets.UTF_8, false); @@ -166,7 +166,7 @@ private void testUpload(RestTemplate template, String cseUrlPrefix) throws IOExc TestMgr.check(expect, result); } - private String testRestTemplateUpload(RestTemplate template, String cseUrlPrefix, File file1, File someFile) { + private String testRestTemplateUpload(RestOperations template, String cseUrlPrefix, File file1, File someFile) { MultiValueMap map = new LinkedMultiValueMap<>(); map.add("file1", new FileSystemResource(file1)); map.add("someFile", new FileSystemResource(someFile)); @@ -177,41 +177,7 @@ private String testRestTemplateUpload(RestTemplate template, String cseUrlPrefix String.class); } - private void testFallback(RestTemplate template, String cseUrlPrefix) { - long start = System.currentTimeMillis(); - String result = template.getForObject(cseUrlPrefix + "/fallback/returnnull/hello", String.class); - TestMgr.check(result, "hello"); - result = template.getForObject(cseUrlPrefix + "/fallback/returnnull/throwexception", String.class); - TestMgr.check(result, null); - - result = template.getForObject(cseUrlPrefix + "/fallback/throwexception/hello", String.class); - TestMgr.check(result, "hello"); - try { - result = template.getForObject(cseUrlPrefix + "/fallback/throwexception/throwexception", String.class); - TestMgr.check(false, true); - } catch (Exception e) { - TestMgr.check(e.getCause().getMessage(), - BizkeeperExceptionUtils.createBizkeeperException(BizkeeperExceptionUtils.SERVICECOMB_BIZKEEPER_FALLBACK, - null, - "springmvc.codeFirst.fallbackThrowException").getMessage()); - } - - result = template.getForObject(cseUrlPrefix + "/fallback/fromcache/hello", String.class); - TestMgr.check(result, "hello"); - result = template.getForObject(cseUrlPrefix + "/fallback/fromcache/hello", String.class); - TestMgr.check(result, "hello"); - result = template.getForObject(cseUrlPrefix + "/fallback/fromcache/throwexception", String.class); - TestMgr.check(result, "hello"); - - result = template.getForObject(cseUrlPrefix + "/fallback/force/hello", String.class); - TestMgr.check(result, "mockedreslut"); - - // This test case is fallback testing and will return null if failed. - // In order to check if failed due to some unexpected timeout exception, check the time. - TestMgr.check(System.currentTimeMillis() - start < 10000, true); - } - - private void testResponseEntity(String microserviceName, RestTemplate template, String cseUrlPrefix) { + private void testResponseEntity(String microserviceName, RestOperations template, String cseUrlPrefix) { Map body = new HashMap<>(); Date date = new Date(); body.put("date", date); @@ -219,7 +185,7 @@ private void testResponseEntity(String microserviceName, RestTemplate template, CseHttpEntity> httpEntity = new CseHttpEntity<>(body); httpEntity.addContext("contextKey", "contextValue"); - String srcName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); + String srcName = BootStrapProperties.readServiceName(environment); ResponseEntity responseEntity = template.exchange(cseUrlPrefix + "responseEntity", HttpMethod.POST, httpEntity, Date.class); @@ -237,50 +203,52 @@ private void testResponseEntity(String microserviceName, RestTemplate template, int retryResult = template.getForObject(cseUrlPrefix + "retrySuccess?a=2&b=3", Integer.class); TestMgr.check(retryResult, 5); + retryResult = template.getForObject(cseUrlPrefix + "retrySuccess?a=2&b=3", Integer.class); + TestMgr.check(retryResult, 5); } - private void testCodeFirstTestForm(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstTestForm(RestOperations template, String cseUrlPrefix) { HttpHeaders formHeaders = new HttpHeaders(); formHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); Map map = new HashMap<>(); String code = "servicecomb%2bwelcome%40%23%24%25%5e%26*()%3d%3d"; map.put("form1", code); - HttpEntity> formEntiry = new HttpEntity<>(map, formHeaders); + HttpEntity> formEntry = new HttpEntity<>(map, formHeaders); TestMgr.check(code + "null", - template.postForEntity(cseUrlPrefix + "/testform", formEntiry, String.class).getBody()); + template.postForEntity(cseUrlPrefix + "/testform", formEntry, String.class).getBody()); map.put("form2", "hello"); TestMgr - .check(code + "hello", template.postForEntity(cseUrlPrefix + "/testform", formEntiry, String.class).getBody()); + .check(code + "hello", template.postForEntity(cseUrlPrefix + "/testform", formEntry, String.class).getBody()); } - private void testCodeFirstTestFormHighway(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstTestFormHighway(RestOperations template, String cseUrlPrefix) { HttpHeaders formHeaders = new HttpHeaders(); formHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); Map map = new HashMap<>(); String code = "servicecomb%2bwelcome%40%23%24%25%5e%26*()%3d%3d"; map.put("form1", code); map.put("form2", ""); - HttpEntity> formEntiry = new HttpEntity<>(map, formHeaders); - TestMgr.check(code + "", template.postForEntity(cseUrlPrefix + "/testform", formEntiry, String.class).getBody()); + HttpEntity> formEntry = new HttpEntity<>(map, formHeaders); + TestMgr.check(code + "", template.postForEntity(cseUrlPrefix + "/testform", formEntry, String.class).getBody()); map = new HashMap<>(); code = "servicecomb%2bwelcome%40%23%24%25%5e%26*()%3d%3d"; map.put("form1", code); map.put("form2", null); - formEntiry = new HttpEntity<>(map, formHeaders); + formEntry = new HttpEntity<>(map, formHeaders); TestMgr.check(code + "null", - template.postForEntity(cseUrlPrefix + "/testform", formEntiry, String.class).getBody()); + template.postForEntity(cseUrlPrefix + "/testform", formEntry, String.class).getBody()); } - private void testCodeFirstTestFormRest(RestTemplate template, String cseUrlPrefix) { + private void testCodeFirstTestFormRest(RestOperations template, String cseUrlPrefix) { HttpHeaders formHeaders = new HttpHeaders(); formHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED); Map map = new HashMap<>(); String code = "servicecomb%2bwelcome%40%23%24%25%5e%26*()%3d%3d"; map.put("form1", code); map.put("form2", ""); - HttpEntity> formEntiry = new HttpEntity<>(map, formHeaders); + HttpEntity> formEntry = new HttpEntity<>(map, formHeaders); // Rest will have empty string, but users will try to avoid depend on this, This is different from highway - TestMgr.check(code + "", template.postForEntity(cseUrlPrefix + "/testform", formEntiry, String.class).getBody()); + TestMgr.check(code + "", template.postForEntity(cseUrlPrefix + "/testform", formEntry, String.class).getBody()); } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ConsumerTestsAfterBootup.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ConsumerTestsAfterBootup.java deleted file mode 100644 index 1624a21458c..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ConsumerTestsAfterBootup.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.apache.servicecomb.demo.springmvc.client; -/* - * 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. - */ - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.Charset; - -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.registry.RegistrationManager; -import org.springframework.stereotype.Component; - -/** - * Testing after bootup. - */ -@Component -public class ConsumerTestsAfterBootup implements BootListener { - private void testRegisterPath() { - TestMgr.check(RegistrationManager.INSTANCE.getMicroservice().getPaths().size(), 0); - } - - private void testSchemaContent() { - String content = RegistrationManager.INSTANCE.getMicroservice().getSchemaMap().get("SpringMVCSchema"); - TestMgr.check(content.replaceAll("\\s", ""), - readFile("SpringMVCSchema.yaml").replaceAll("[\\s#]", "")); - } - - private String readFile(String restController) { - // test code, make simple - try { - InputStream inputStream = this.getClass().getResource("/" + restController).openStream(); - byte[] buffer = new byte[2048 * 10]; - inputStream.skip(1000); - int len = inputStream.read(buffer); - TestMgr.check(2048 * 10 > len, true); - inputStream.close(); - return new String(buffer, 0, len, Charset.forName("UTF-8")); - } catch (IOException e) { - TestMgr.failed(e.getMessage(), e); - return null; - } - } - - @Override - public void onBootEvent(BootEvent event) { - if (event.getEventType() == BootListener.EventType.AFTER_REGISTRY) { - testRegisterPath(); - testSchemaContent(); - if (!TestMgr.isSuccess()) { - TestMgr.summary(); - throw new IllegalStateException("some tests are failed. "); - } - } - } -} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java index aa3ee5d53cb..6bf78279d42 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/CustomEndpointDiscoveryFilter.java @@ -17,10 +17,10 @@ package org.apache.servicecomb.demo.springmvc.client; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; import org.apache.servicecomb.registry.discovery.AbstractEndpointDiscoveryFilter; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; public class CustomEndpointDiscoveryFilter extends AbstractEndpointDiscoveryFilter { @Override @@ -31,7 +31,7 @@ protected String findTransportName(DiscoveryContext context, DiscoveryTreeNode p @Override protected Object createEndpoint(DiscoveryContext context, String transportName, String endpoint, - MicroserviceInstance instance) { + StatefulDiscoveryInstance instance) { return endpoint; } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ICompatible1xTestSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ICompatible1xTestSchema.java new file mode 100644 index 00000000000..ac8c10ecbda --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ICompatible1xTestSchema.java @@ -0,0 +1,37 @@ +/* + * 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.demo.springmvc.client; + +import org.apache.servicecomb.swagger.invocation.context.InvocationContext; + +import io.swagger.v3.oas.annotations.Operation; + +public interface ICompatible1xTestSchema { + String parameterName(int c, int d); + + @Operation(operationId = "parameterName", summary = "parameterName") + String parameterNamePartMatchLeft(int a, int d); + + @Operation(operationId = "parameterName", summary = "parameterName") + String parameterNamePartMatchRight(int c, int b); + + String parameterName(InvocationContext context, int c, int d); + + String parameterNameServerContext(int c, int d); + + String beanParameter(String notName, int notAge); +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/MicroserviceArray.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/MicroserviceArray.java deleted file mode 100644 index add5e6f1163..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/MicroserviceArray.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.demo.springmvc.client; - -import java.util.List; - -import org.apache.servicecomb.registry.api.registry.Microservice; - -public class MicroserviceArray { - - private List services; - - public List getServices() { - return services; - } - - public void setServices(List services) { - this.services = services; - } -} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/MockedFallbackExample.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/MockedFallbackExample.java deleted file mode 100644 index 3533aed2063..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/MockedFallbackExample.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.demo.springmvc.client; - -import org.apache.servicecomb.bizkeeper.FallbackPolicy; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; - -@Component -public class MockedFallbackExample implements FallbackPolicy { - - @Override - public String name() { - return "mycustom"; - } - - @Override - public Response getFallbackResponse(Invocation invocation, Throwable error) { - return Response.succResp("mockedreslut"); - } -} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ResponseOKData.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ResponseOKData.java new file mode 100644 index 00000000000..df2bf9c5f42 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ResponseOKData.java @@ -0,0 +1,48 @@ +/* + * 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.demo.springmvc.client; + +public class ResponseOKData { + private String errorCode; + + private String errorMessage; + + public ResponseOKData() { + + } + + public ResponseOKData(String errorCode, String errorMessage) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java index 863f9b825b7..9bce39f0af7 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SchemeInterfaceSpringmvc.java @@ -21,4 +21,8 @@ public interface SchemeInterfaceSpringmvc { int add(int a, int b); int reduce(int a, int b); + + String tailingSlash(int a, int b); + + String nonTailingSlash(int a, int b); } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ServiceCenterExample.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ServiceCenterExample.java deleted file mode 100644 index 84d39473a36..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ServiceCenterExample.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.demo.springmvc.client; - -import java.net.URI; - -import org.springframework.http.HttpMethod; -import org.springframework.http.RequestEntity; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -public class ServiceCenterExample { - - public static void main(String[] args) throws Exception { - RestTemplate template = new RestTemplate(); - template.getMessageConverters().add(new MappingJackson2HttpMessageConverter()); - MultiValueMap headers = new LinkedMultiValueMap<>(); - headers.add("X-Tenant-Name", "default"); - - RequestEntity requestEntity = new RequestEntity(headers, HttpMethod.GET, - new URI("http://127.0.0.1:9980/registry/v3/microservices")); - ResponseEntity stringResponseEntity = template.exchange(requestEntity, String.class); - System.out.println(stringResponseEntity.getBody()); - ResponseEntity microseriveResponseEntity = template - .exchange(requestEntity, MicroserviceArray.class); - MicroserviceArray microserives = microseriveResponseEntity.getBody(); - System.out.println(microserives.getServices().get(1).getServiceId()); - - // instance - headers.add("X-ConsumerId", microserives.getServices().get(1).getServiceId()); - requestEntity = new RequestEntity(headers, HttpMethod.GET, - new URI("http://127.0.0.1:9980/registry/v3/microservices/" + microserives.getServices().get(1).getServiceId() - + "/instances")); - ResponseEntity microserviceInstanceResponseEntity = template.exchange(requestEntity, String.class); - System.out.println(microserviceInstanceResponseEntity.getBody()); - } -} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringMVCSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringMVCSchema.java index a4c85238574..42c912188af 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringMVCSchema.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringMVCSchema.java @@ -17,30 +17,45 @@ package org.apache.servicecomb.demo.springmvc.client; -import javax.servlet.http.HttpServletRequest; - import org.apache.servicecomb.provider.rest.common.RestSchema; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Example; -import io.swagger.annotations.ExampleProperty; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.servlet.http.HttpServletRequest; @RestSchema(schemaId = "SpringMVCSchema") @RequestMapping("/springMvcSchema") public class SpringMVCSchema { + // TODO: examples not serialized by yaml parser @ApiResponses({ - @ApiResponse(code = 200, response = String.class, message = "success", - examples = @Example({ - @ExampleProperty(value = "wget http://localhost/springMvcSchema/testApiExample", mediaType = "text"), - @ExampleProperty(value = "{name:hello}", mediaType = "application/json"), - @ExampleProperty(value = "{name:hello}", mediaType = "json")}) + @ApiResponse(responseCode = "200", content = @Content( + schema = @Schema(implementation = String.class, example = "wget http://localhost/springMvcSchema/testApiExample"), + examples = {@ExampleObject(value = "wget http://localhost/springMvcSchema/testApiExample", name = "text"), + @ExampleObject(value = "{name:hello}", name = "application/json"), + @ExampleObject(value = "{name:hello}", name = "json")}) + , description = "success" )}) @RequestMapping(path = "/testApiExample", method = RequestMethod.POST) public String testApiExample(@RequestBody String name, HttpServletRequest request) { return null; } + + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class), + examples = {@ExampleObject(value = "wget http://localhost/springMvcSchema/testApiExample", name = "text"), + @ExampleObject(value = "{name:hello}", name = "application/json"), + @ExampleObject(value = "{name:hello}", name = "json")}) + , description = "success" + )}) + @RequestMapping(path = "/testDefaultGetApiExample") + public String testDefaultGetApiExample(@RequestParam String name, HttpServletRequest request) { + return null; + } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java deleted file mode 100644 index 7b37debe36b..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/SpringmvcClient.java +++ /dev/null @@ -1,588 +0,0 @@ -/* - * 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.demo.springmvc.client; - -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import org.apache.http.HttpStatus; -import org.apache.servicecomb.demo.CategorizedTestCaseRunner; -import org.apache.servicecomb.demo.DemoConst; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.controller.Controller; -import org.apache.servicecomb.demo.controller.Person; -import org.apache.servicecomb.demo.springmvc.client.ThirdSvc.ThirdSvcClient; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; -import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.apache.servicecomb.provider.springmvc.reference.UrlWithProviderPrefixClientHttpRequestFactory; -import org.apache.servicecomb.provider.springmvc.reference.UrlWithServiceNameClientHttpRequestFactory; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; - -import com.netflix.config.DynamicPropertyFactory; - -public class SpringmvcClient { - private static final Logger LOGGER = LoggerFactory.getLogger(SpringmvcClient.class); - - private static RestTemplate templateUrlWithServiceName = new CseRestTemplate(); - - private static RestTemplate templateUrlWithProviderPrefix = new CseRestTemplate(); - - private static RestTemplate restTemplate; - - private static Controller controller; - - public static void main(String[] args) throws Exception { - try { - Log4jUtils.init(); - BeanUtils.init(); - - run(); - } catch (Throwable e) { - TestMgr.check("success", "failed"); - LOGGER.error("-------------- test failed -------------"); - LOGGER.error("", e); - LOGGER.error("-------------- test failed -------------"); - } - TestMgr.summary(); - } - - private static void changeTransport(String microserviceName, String transport) { - ArchaiusUtils.setProperty("servicecomb.references.transport." + microserviceName, transport); - TestMgr.setMsg(microserviceName, transport); - } - - public static void run() throws Exception { - testHttpClientsIsOk(); - testConfigurationDuplicate(); - - templateUrlWithServiceName.setRequestFactory(new UrlWithServiceNameClientHttpRequestFactory()); - restTemplate = RestTemplateBuilder.create(); - templateUrlWithProviderPrefix.setRequestFactory(new UrlWithProviderPrefixClientHttpRequestFactory("/pojo/rest")); - controller = BeanUtils.getBean("controller"); - - String prefix = "cse://springmvc"; - String microserviceName = "springmvc"; - - try { - // this test class is intended for retry hanging issue JAV-127 - templateUrlWithServiceName.getForObject(prefix + "/controller/sayhi?name=throwexception", String.class); - TestMgr.check("true", "false"); - } catch (Exception e) { - TestMgr.check("true", "true"); - } - - CodeFirstRestTemplateSpringmvc codeFirstClient = - BeanUtils.getContext().getBean(CodeFirstRestTemplateSpringmvc.class); - codeFirstClient.testCodeFirst(restTemplate, "springmvc", "/codeFirstSpringmvc/"); - codeFirstClient.testCodeFirst(templateUrlWithProviderPrefix, "springmvc", "/pojo/rest/codeFirstSpringmvc/"); - - testAllTransport(microserviceName); - testRestTransport(microserviceName, prefix); - CategorizedTestCaseRunner.runCategorizedTestCase(microserviceName); - } - - private static void testHttpClientsIsOk() { - TestMgr.check(HttpClients.getClient("registry") != null, true); - TestMgr.check(HttpClients.getClient("registry-watch") != null, true); - TestMgr.check(HttpClients.getClient("http-transport-client") != null, true); - TestMgr.check(HttpClients.getClient("http2-transport-client") != null, true); - - TestMgr.check(HttpClients.getClient("registry", false) != null, true); - TestMgr.check(HttpClients.getClient("registry-watch", false) != null, true); - TestMgr.check(HttpClients.getClient("http-transport-client", false) != null, true); - TestMgr.check(HttpClients.getClient("http2-transport-client", false) != null, true); - } - - private static void testRestTransport(String microserviceName, String prefix) { - changeTransport(microserviceName, "rest"); - - testControllerRest(templateUrlWithServiceName, microserviceName); - testSpringMvcDefaultValuesRest(templateUrlWithServiceName, microserviceName); - testSpringMvcDefaultValuesJavaPrimitiveRest(templateUrlWithServiceName, microserviceName); - - HttpHeaders headers = new HttpHeaders(); - headers.set("Accept-Encoding", "gzip"); - HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity entityCompress = - restTemplate.exchange(prefix - + "/codeFirstSpringmvc/sayhi/compressed/{name}/v2", HttpMethod.GET, entity, String.class, "Test"); - TestMgr.check( - "Test sayhi compressed:This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text,This is a big text!", - entityCompress.getBody()); - // if server response is compressed, the content-length header will be removed , so can't check this. - // the transfer-encoding header will be missing when the server is set to not compressed - if (entityCompress.getHeaders().get("transfer-encoding") != null) { - TestMgr.check("chunked", entityCompress.getHeaders().get("transfer-encoding").get(0)); - } - - //0.5.0 later version metrics integration test - @SuppressWarnings("unchecked") - Map metrics = restTemplate.getForObject(prefix + "/metrics", Map.class); - - // TestMgr.check(true, metrics.get("jvm(name=heapUsed,statistic=gauge)") != 0); - TestMgr.check(true, metrics.size() > 0); - - //prometheus integration test - try { - String content = restTemplate - .getForObject("cse://springmvc/codeFirstSpringmvc/prometheusForTest", String.class); - - String application = DynamicPropertyFactory.getInstance().getStringProperty("APPLICATION_ID", "").get(); - - TestMgr.check(true, - content.contains( - "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.addDate")); - TestMgr.check(true, - content.contains( - "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.sayHello")); - TestMgr.check(true, content.contains( - "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.fallbackFromCache")); - TestMgr.check(true, - content - .contains("servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.isTrue")); - TestMgr.check(true, - content.contains("servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.add")); - TestMgr.check(true, - content - .contains("servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.sayHi2")); - TestMgr.check(true, content - .contains( - "servicecomb_invocation{appId=\"" + application + "\",operation=\"springmvc.codeFirst.saySomething")); - - String[] metricLines = content.split("\n"); - if (metricLines.length > 0) { - for (String metricLine : metricLines) { - if (!metricLine.startsWith("#")) { - String[] metricKeyAndValue = metricLine.split(" "); - if (!metricKeyAndValue[0].startsWith("jvm") && !metricKeyAndValue[0].startsWith("os")) { - if (Double.parseDouble(metricKeyAndValue[1]) < 0) { - TestMgr.check("true", "false"); - break; - } - } - } - } - } else { - TestMgr.check("true", "false"); - } - } catch (Exception e) { - TestMgr.check("true", "false"); - } - } - - private static void testAllTransport(String microserviceName) { - for (String transport : DemoConst.transports) { - changeTransport(microserviceName, transport); - - TestMgr.setMsg(microserviceName, transport); - - testControllerAllTransport(templateUrlWithServiceName, microserviceName); - - testController(); - testRequiredBody(templateUrlWithServiceName, microserviceName); - testSpringMvcDefaultValuesAllTransport(templateUrlWithServiceName, microserviceName); - testSpringMvcDefaultValuesJavaPrimitiveAllTransport(templateUrlWithServiceName, microserviceName); - testThirdService(); - } - } - - private static void testThirdService() { - ThirdSvcClient client = BeanUtils.getContext().getBean(ThirdSvcClient.class); - - Date date = new Date(); - ResponseEntity responseEntity = client.responseEntity(date); - TestMgr.check(date, responseEntity.getBody()); - } - - private static void testControllerRest(RestTemplate template, String microserviceName) { - String prefix = "cse://" + microserviceName; - - TestMgr.check("hi world [world]", - template.getForObject(prefix + "/controller/sayhi?name=world", - String.class)); - - TestMgr.check("hi world1 [world1]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - "world1")); - - TestMgr.check("hi world1+world2 [world1+world2]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - "world1+world2")); - - TestMgr.check("hi hi 中国 [hi 中国]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - "hi 中国")); - - Map params = new HashMap<>(); - params.put("name", "world2"); - TestMgr.check("hi world2 [world2]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - params)); - - try { - template.postForObject(prefix + "/controller/sayhello/{name}", - null, - String.class, - "exception"); - TestMgr.check(true, false); - } catch (InvocationException e) { - TestMgr.check(e.getStatusCode(), 503); - } - - TestMgr.check("hi world [world]", controller.sayHi("world")); - } - - private static void testControllerAllTransport(RestTemplate template, String microserviceName) { - String prefix = "cse://" + microserviceName; - - TestMgr.check(7, - template.getForObject(prefix + "/controller/add?a=3&b=4", - Integer.class)); - - try { - template.getForObject(prefix + "/controller/add", - Integer.class); - TestMgr.check("failed", "success"); - } catch (InvocationException e) { - TestMgr.check(e.getStatusCode(), 400); - } - - TestMgr.check("hi world [world]", - template.getForObject(prefix + "/controller/sayhi?name=world", - String.class)); - - TestMgr.check("hi world1 [world1]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - "world1")); - TestMgr.check("hi hi 中国 [hi 中国]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - "hi 中国")); - - Map params = new HashMap<>(); - params.put("name", "world2"); - TestMgr.check("hi world2 [world2]", - template.getForObject(prefix + "/controller/sayhi?name={name}", - String.class, - params)); - - TestMgr.check("hello world", - template.postForObject(prefix + "/controller/sayhello/{name}", - null, - String.class, - "world")); - TestMgr.check("hello hello 中国", - template.postForObject(prefix + "/controller/sayhello/{name}", - null, - String.class, - "hello 中国")); - - try { - template.postForObject(prefix + "/controller/sayhello/{name}", - null, - String.class, - "exception"); - TestMgr.check(true, false); - } catch (InvocationException e) { - TestMgr.check(e.getStatusCode(), 503); - } - - HttpHeaders headers = new HttpHeaders(); - headers.add("name", "world"); - @SuppressWarnings("rawtypes") - HttpEntity entity = new HttpEntity<>(null, headers); - ResponseEntity response = template.exchange(prefix + "/controller/sayhei", - HttpMethod.GET, - entity, - String.class); - TestMgr.check("hei world", response.getBody()); - - Person user = new Person(); - user.setName("world"); - TestMgr.check("ha world", - template.postForObject(prefix + "/controller/saysomething?prefix={prefix}", - user, - String.class, - "ha")); - } - - private static void testController() { - TestMgr.check("hi world [world]", controller.sayHi("world")); - Person user = new Person(); - user.setName("world"); - TestMgr.check("ha world", controller.saySomething("ha", user)); - } - - private static void testConfigurationDuplicate() { - // this configuration will give warning messages: - // Key servicecomb.test.duplicate2 with an ambiguous item cse.test.duplicate2 exists, please use the same prefix or will get unexpected merged value. - // Key servicecomb.test.duplicate1 with an ambiguous item cse.test.duplicate1 exists, please use the same prefix or will get unexpected merged value. - // and the expected value is not quite determined. But will not get wrong value like 'older,newer' or 'newer,older' - TestMgr.check(DynamicPropertyFactory.getInstance().getStringProperty("cse.test.duplicate2", "wrong").get(), - "newer"); - TestMgr.check(DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.test.duplicate2", "wrong").get(), - "newer"); - TestMgr.check(DynamicPropertyFactory.getInstance().getStringProperty("cse.test.duplicate1", "wrong").get(), - "older"); - TestMgr.check(DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.test.duplicate1", "wrong").get(), - "newer"); - } - - private static void testRequiredBody(RestTemplate template, String microserviceName) { - String prefix = "cse://" + microserviceName; - Person user = new Person(); - - TestMgr.check("No user data found", - template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", - user, - String.class, - "ha")); - - user.setName("world"); - TestMgr.check("ha world", - template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", - user, - String.class, - "ha")); - - TestMgr.check("No user data found", - template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", - null, - String.class, - "ha")); - - TestMgr.check("No user name found", - template.postForObject(prefix + "/annotations/say", - "", - String.class, - "ha")); - TestMgr.check("test", - template.postForObject(prefix + "/annotations/say", - "test", - String.class, - "ha")); - } - - private static void testSpringMvcDefaultValuesRest(RestTemplate template, String microserviceName) { - String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; - String result = template.getForObject(cseUrlPrefix + "/query?d=10", String.class); - TestMgr.check("Hello 20bobo4010", result); - boolean failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); - TestMgr.check("Hello 20bobo40302", result); - - failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - } - - private static void testSpringMvcDefaultValuesAllTransport(RestTemplate template, String microserviceName) { - String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; - //default values - HttpHeaders headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - MultiValueMap map = new LinkedMultiValueMap<>(); - HttpEntity> request = new HttpEntity<>(map, headers); - String result = template.postForObject(cseUrlPrefix + "/form", request, String.class); - TestMgr.check("Hello 20bobo", result); - - headers = new HttpHeaders(); - HttpEntity entity = new HttpEntity<>(null, headers); - result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); - TestMgr.check("Hello 20bobo30", result); - - result = template.getForObject(cseUrlPrefix + "/query?d=10", String.class); - TestMgr.check("Hello 20bobo4010", result); - boolean failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query2?d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query2?a=&d=2&e=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - result = template.getForObject(cseUrlPrefix + "/query2?d=30&e=2", String.class); - TestMgr.check("Hello 20bobo40302", result); - - failed = false; - result = null; - try { - result = template.getForObject(cseUrlPrefix + "/query3?a=2&b=2", String.class); - } catch (InvocationException e) { - failed = true; - TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); - } - TestMgr.check(true, failed); - TestMgr.check(null, result); - - result = template.getForObject(cseUrlPrefix + "/query3?a=30&b=2", String.class); - TestMgr.check("Hello 302", result); - - result = template.getForObject(cseUrlPrefix + "/query3?a=30", String.class); - TestMgr.check("Hello 30null", result); - - //input values - headers = new HttpHeaders(); - headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); - HttpEntity> requestPara = new HttpEntity<>(null, headers); - result = template.postForObject(cseUrlPrefix + "/form?a=30&b=sam", requestPara, String.class); - TestMgr.check("Hello 30sam", result); - - headers = new HttpHeaders(); - headers.add("a", "30"); - headers.add("b", "sam"); - headers.add("c", "40"); - entity = new HttpEntity<>(null, headers); - result = template.postForObject(cseUrlPrefix + "/header", entity, String.class); - TestMgr.check("Hello 30sam40", result); - - result = template.getForObject(cseUrlPrefix + "/query?a=3&b=sam&c=5&d=30", String.class); - TestMgr.check("Hello 3sam530", result); - - result = template.getForObject(cseUrlPrefix + "/query2?a=3&b=4&c=5&d=30&e=2", String.class); - TestMgr.check("Hello 345302", result); - } - - private static void testSpringMvcDefaultValuesJavaPrimitiveAllTransport(RestTemplate template, - String microserviceName) { - String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; - //default values with primitive - String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", null, String.class); - TestMgr.check("Hello 0bobo", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", null, String.class); - TestMgr.check("Hello 0.0false", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", null, String.class); - TestMgr.check("Hello", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", null, String.class); - TestMgr.check("Hello nullnull", result); - - result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); - TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); - - result = template.postForObject(cseUrlPrefix - + "/allprimitivetypes?pBoolean=true&pChar=c&pByte=20&pShort=30&pInt=40&pLong=50&pFloat=60&pDouble=70&pDoubleWrap=80", - null, String.class); - TestMgr.check("Hello true,c,20,30,40,50,60.0,70.0,80.0", result); - } - - private static void testSpringMvcDefaultValuesJavaPrimitiveRest(RestTemplate template, String microserviceName) { - String cseUrlPrefix = "cse://" + microserviceName + "/SpringMvcDefaultValues/"; - //default values with primitive - String result = template.postForObject(cseUrlPrefix + "/javaprimitiveint", null, String.class); - TestMgr.check("Hello 0bobo", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivenumber", null, String.class); - TestMgr.check("Hello 0.0false", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivestr", null, String.class); - TestMgr.check("Hello", result); - - result = template.postForObject(cseUrlPrefix + "/javaprimitivecomb", null, String.class); - TestMgr.check("Hello nullnull", result); - - result = template.postForObject(cseUrlPrefix + "/allprimitivetypes", null, String.class); - TestMgr.check("Hello false,\0,0,0,0,0,0.0,0.0,null", result); - } -} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestAnnotationsSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestAnnotationsSchema.java new file mode 100644 index 00000000000..89f7862384b --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestAnnotationsSchema.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.demo.springmvc.client; + +import org.apache.http.HttpStatus; +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.controller.Person; +import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; +import org.apache.servicecomb.provider.springmvc.reference.UrlWithServiceNameClientHttpRequestFactory; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +@Component +public class TestAnnotationsSchema implements CategorizedTestCase { + private static final String microserviceName = "springmvc"; + + private static final RestTemplate templateUrlWithServiceName = new CseRestTemplate(); + + @Override + public void testAllTransport() throws Exception { + templateUrlWithServiceName.setRequestFactory(new UrlWithServiceNameClientHttpRequestFactory()); + testRequiredBody(templateUrlWithServiceName, microserviceName); + testRegExpPath(); + } + + private void testRegExpPath() { + String prefix = "cse://" + microserviceName; + String result = templateUrlWithServiceName.getForObject(prefix + "/annotations/testRegExpPath/a?name={name}", + String.class, "a"); + TestMgr.check("a", result); + result = templateUrlWithServiceName.getForObject(prefix + "/annotations/testRegExpPath/a/b?name={name}", + String.class, "ab"); + TestMgr.check("ab", result); + result = templateUrlWithServiceName.getForObject(prefix + "/annotations/testRegExpPath/a/b/c?name={name}", + String.class, "abc"); + TestMgr.check("abc", result); + } + + private static void testRequiredBody(RestTemplate template, String microserviceName) { + String prefix = "cse://" + microserviceName; + Person user = new Person(); + + TestMgr.check("No user data found", + template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", + user, + String.class, + "ha")); + + user.setName("world"); + TestMgr.check("ha world", + template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", + user, + String.class, + "ha")); + + TestMgr.check("No user data found", + template.postForObject(prefix + "/annotations/saysomething?prefix={prefix}", + null, + String.class, + "ha")); + + TestMgr.check("No user name found", + template.postForObject(prefix + "/annotations/say", + "", + String.class, + "ha")); + TestMgr.check("test", + template.postForObject(prefix + "/annotations/say", + "test", + String.class, + "ha")); + + try { + template.postForObject(prefix + "/annotations/testRequiredBody", + null, + String.class); + TestMgr.fail("should fail"); + } catch (InvocationException e) { + TestMgr.check(e.getStatusCode(), HttpStatus.SC_BAD_REQUEST); + } + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBigNumberSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBigNumberSchema.java new file mode 100644 index 00000000000..3b70709e6d2 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBigNumberSchema.java @@ -0,0 +1,59 @@ +/* + * 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.demo.springmvc.client; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class TestBigNumberSchema implements CategorizedTestCase { + interface IBigNumberSchema { + BigInteger bigInteger(BigInteger intHeader, BigInteger intQuery, BigInteger intForm); + + BigDecimal bigDecimal(BigDecimal decimalHeader, BigDecimal decimalQuery, BigDecimal decimalForm); + } + + @RpcReference(microserviceName = "springmvc", schemaId = "BigNumberSchema") + private IBigNumberSchema schema; + + @Override + public void testAllTransport() throws Exception { + testBigInteger(); + testBigDecimal(); + } + + public void testBigInteger() { + BigInteger result = schema.bigInteger(BigInteger.valueOf(100L), BigInteger.valueOf(3000000000000000000L), + BigInteger.valueOf(200L)); + TestMgr.check("3000000000000000300", result.toString()); + } + + public void testBigDecimal() { + BigDecimal a = BigDecimal.valueOf(100.1D); + BigDecimal b = BigDecimal.valueOf(300000000000000000.1D); + BigDecimal c = BigDecimal.valueOf(200.1D); + BigDecimal expected = a.add(b).add(c); + BigDecimal result = schema.bigDecimal(a, b, c); + TestMgr.check(expected, result); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java deleted file mode 100644 index 305447e1d95..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestBizkeeper.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.demo.springmvc.client; - -import java.util.concurrent.TimeoutException; - -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.springframework.web.client.RestTemplate; - -public class TestBizkeeper { - private RestTemplate restTemplate = RestTemplateBuilder.create(); - - private String prefix = "cse://springmvc/codeFirstBizkeeperTest"; - - public void runAllTest() { - testTimeout(); - } - - private void testTimeout() { - //config timeout starts with cse.xxx, from yaml - try { - restTemplate.getForObject(prefix + "/testTimeout?name={1}&delaytime={2}", String.class, "joker", 1000); - TestMgr.check("expect: throw timeout exception", "real: not throw timeout exception"); - } catch (Exception e) { - TestMgr.check(TimeoutException.class, e.getCause().getCause().getClass()); - } - //modify config timeout starts with servicecomb.xxx, can change the timeout effect - ArchaiusUtils.setProperty( - "servicecomb.isolation.Consumer.springmvc.codeFirstBizkeeperTest.testTimeout.timeout.enabled", "false"); - try { - String result = - restTemplate.getForObject(prefix + "/testTimeout?name={1}&delaytime={2}", String.class, "joker", 1000); - TestMgr.check("joker", result); - } catch (Exception e) { - TestMgr.check("expect: not throw timeout exception", "real: throw timeout exception"); - } - - try { - ArchaiusUtils.setProperty( - "servicecomb.fallback.Consumer.springmvc.codeFirstBizkeeperTest.testTimeout.enabled", "false"); - ArchaiusUtils.setProperty( - "servicecomb.isolation.Consumer.springmvc.codeFirstBizkeeperTest.testTimeout.timeout.enabled", "true"); - ArchaiusUtils.setProperty( - "servicecomb.isolation.Consumer.springmvc.codeFirstBizkeeperTest.testTimeout.timeoutInMilliseconds", 500); - restTemplate.getForObject(prefix + "/testTimeout?name={1}&delaytime={2}", String.class, "joker", 1000); - TestMgr.check("expect: throw timeout exception", "real: not throw timeout exception"); - } catch (InvocationException e) { - TestMgr.check(TimeoutException.class, e.getCause().getCause().getClass()); - } - } -} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestContentType.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestContentType.java index 65fc1461dd7..aa0d9d0f63d 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestContentType.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestContentType.java @@ -17,24 +17,27 @@ package org.apache.servicecomb.demo.springmvc.client; -import javax.ws.rs.core.MediaType; - import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.core.MediaType; public class TestContentType { - private RestTemplate restTemplate = RestTemplateBuilder.create(); + private RestOperations restTemplate = RestTemplateBuilder.create(); public void runAllTest() { testGlobalSetting(); testApiOperation(); testRequestMapping(); + testProtoBuffer(); testResponseTypeOverwrite(); } @@ -53,15 +56,15 @@ private void testGlobalSetting() { private void testApiOperation() { HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON); + requestHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN); CseHttpEntity requestEntity = new CseHttpEntity<>("from testApiOperation", requestHeaders); ResponseEntity responseEntity = restTemplate .exchange("cse://springmvc/contentTypeSpringmvc/testApiOperation", HttpMethod.POST, requestEntity, String.class); TestMgr.check( - "testApiOperation: name=[from testApiOperation], request content-type=[" + MediaType.APPLICATION_JSON + "]", + "testApiOperation: name=[from testApiOperation], request content-type=[" + MediaType.TEXT_PLAIN + "]", responseEntity.getBody()); - TestMgr.check(MediaType.APPLICATION_JSON, extractContentType(responseEntity.getHeaders().getContentType())); + TestMgr.check(MediaType.TEXT_PLAIN, extractContentType(responseEntity.getHeaders().getContentType())); } private void testRequestMapping() { @@ -77,6 +80,24 @@ private void testRequestMapping() { TestMgr.check(MediaType.APPLICATION_JSON, extractContentType(responseEntity.getHeaders().getContentType())); } + + private void testProtoBuffer() { + HttpHeaders requestHeaders = new HttpHeaders(); + requestHeaders.add(HttpHeaders.CONTENT_TYPE, SwaggerConst.PROTOBUF_TYPE); + User user = new User(); + user.setIndex(100); + user.setName("hello"); + user.setNames(new String[] {"a1", "a2"}); + CseHttpEntity requestEntity = new CseHttpEntity<>(user, requestHeaders); + ResponseEntity responseEntity = restTemplate + .exchange("cse://springmvc/contentTypeSpringmvc/testProtoBuffer", HttpMethod.POST, + requestEntity, String.class); + TestMgr.check( + "testRequestMapping: name=[hello:100:[a1, a2]], request content-type=[application/protobuf]", + responseEntity.getBody()); + TestMgr.check(SwaggerConst.PROTOBUF_TYPE, extractContentType(responseEntity.getHeaders().getContentType())); + } + private void testResponseTypeOverwrite() { ResponseEntity responseEntity = restTemplate .getForEntity("cse://springmvc/contentTypeSpringmvcOverwrite/testResponseTypeOverwrite", String.class); diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestControllerImpl.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestControllerImpl.java new file mode 100644 index 00000000000..3264caa9fa9 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestControllerImpl.java @@ -0,0 +1,93 @@ +/* + * 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.demo.springmvc.client; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.controller.Controller; +import org.apache.servicecomb.demo.controller.Person; +import org.apache.servicecomb.demo.controller.PersonAlias; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.http.client.common.HttpUtils; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +@Component +public class TestControllerImpl implements CategorizedTestCase { + private static final String SERVER = "servicecomb://springmvc"; + + @Autowired + Controller controller; + + RestOperations restTemplate = RestTemplateBuilder.create(); + + @Override + public void testRestTransport() throws Exception { + testQueryParamSpecial(); + testResponseModel(); + } + + @Override + public void testAllTransport() throws Exception { + testControllerBodyModel(); + testControllerHeaderModel(); + } + + private void testControllerHeaderModel() throws Exception { + // HTTP header只允许 ASCII 字符。 + // 在Header参数中使用特殊字符,需要在发送请求前进行编码,在收到响应后进行解码,具体编码方式可以业务自行选择。 + // 如果不进行编码,则可能会出现乱码(HTTP协议历史上只标准化了ASCII字符,其他字符集可能工作,可能不工作)。 + String encodedResult = controller.sayHei(HttpUtils.encodeURLParam("中文HTTP Header")); + TestMgr.check("hei 中文HTTP Header", HttpUtils.decodeURLParam(encodedResult)); + + // 普通ASCII字符不需要编码 + TestMgr.check("hei ~!@#$%^&*()_+-={}[]|\\:\";''<>?,./AL340", + controller.sayHei("~!@#$%^&*()_+-={}[]|\\:\";''<>?,./AL340")); + } + + private void testControllerBodyModel() { + Person user = new Person(); + user.setName("world"); + TestMgr.check("ha world", controller.saySomething("ha", user)); + } + + private void testResponseModel() { + Person person = restTemplate.getForObject(SERVER + "/springmvc/controller/testResponseModel", Person.class); + TestMgr.check("jack", person.getName()); + + PersonAlias personAlias = restTemplate.getForObject(SERVER + "/springmvc/controller/testResponseModel", + PersonAlias.class); + TestMgr.check("jack", personAlias.getName()); + } + + private void testQueryParamSpecial() { + // vert.x and servlet container have different query parameter implementations + if (LegacyPropertyFactory.getBooleanProperty("servicecomb.test.vert.transport", true)) { + + TestMgr.check(restTemplate.getForObject( + SERVER + "/springmvc/controller/sayHello1?name=you;me", String.class), "Hello you,v"); + } else { + TestMgr.check(restTemplate.getForObject( + SERVER + "/springmvc/controller/sayHello1?name=you;me", String.class), "Hello you;me,v"); + } + TestMgr.check(restTemplate.getForObject( + SERVER + "/springmvc/controller/sayHello1?name={1}", + String.class, "you;me"), "Hello you;me,v"); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDataTypesAnnotationsSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDataTypesAnnotationsSchema.java new file mode 100644 index 00000000000..6234b0a99f6 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDataTypesAnnotationsSchema.java @@ -0,0 +1,54 @@ +/* + * 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.demo.springmvc.client; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class TestDataTypesAnnotationsSchema implements CategorizedTestCase { + public interface DataTypesAnnotationsItf { + int[] testIntArrayQuery(int[] param); + + Integer[] testIntegerArrayQuery(Integer[] param); + } + + @RpcReference(schemaId = "DataTypesAnnotationsSchema", microserviceName = "springmvc") + private DataTypesAnnotationsItf client; + + @Override + public void testAllTransport() throws Exception { + testIntArrayQuery(); + testIntegerArrayQuery(); + } + + private void testIntArrayQuery() { + int[] request = new int[] {5, 11, 4}; + int[] result = client.testIntArrayQuery(request); + TestMgr.check(request.length, result.length); + TestMgr.check(request[1], result[1]); + } + + private void testIntegerArrayQuery() { + Integer[] request = new Integer[] {5, 11, 4}; + Integer[] result = client.testIntegerArrayQuery(request); + TestMgr.check(request.length, result.length); + TestMgr.check(request[1], result[1]); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java index 409e634c039..580192c71a1 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDateTimeSchema.java @@ -31,16 +31,18 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.loadbalance.LoadbalanceHandler; +import org.apache.servicecomb.loadbalance.LoadBalanceFilter; import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.provider.springmvc.reference.CseHttpEntity; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.registry.DiscoveryManager; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTree; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; interface DateTimeSchemaInf { Date getDate(Date date); @@ -74,20 +76,22 @@ public class TestDateTimeSchema implements CategorizedTestCase { @RpcReference(microserviceName = "springmvc", schemaId = "DateTimeSchema") private DateTimeSchemaWithContextInf dateTimeSchemaWithContextInf; - private DiscoveryTree discoveryTree = new DiscoveryTree(); + private DiscoveryTree discoveryTree; - public TestDateTimeSchema() { - discoveryTree.addFilter(new CustomEndpointDiscoveryFilter()); - discoveryTree.sort(); - } + private SCBEngine scbEngine; - @Override - public void testRestTransport() throws Exception { + @Autowired + public void setScbEngine(SCBEngine scbEngine) { + this.scbEngine = scbEngine; + } + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryTree = new DiscoveryTree(discoveryManager); + discoveryTree.setDiscoveryFilters(List.of(new CustomEndpointDiscoveryFilter())); } - @Override - public void testHighwayTransport() throws Exception { + public TestDateTimeSchema() { } @@ -126,17 +130,17 @@ private void testDateTimeSchema() { private void testDateTimeSchemaMulticast() throws Exception { DiscoveryContext context = new DiscoveryContext(); - VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc", "0+"); - List enpoints = serversVersionedCache.data(); + VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc"); + List endpoints = serversVersionedCache.data(); - for (String endpoint : enpoints) { + for (String endpoint : endpoints) { InvocationContext invocationContext = new InvocationContext(); - invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, endpoint); + invocationContext.addLocalContext(LoadBalanceFilter.SERVICECOMB_SERVER_ENDPOINT, endpoint); Date date = new Date(); TestMgr.check(date.getTime(), dateTimeSchemaWithContextInf.getDate(invocationContext, date).getTime()); invocationContext = new InvocationContext(); - invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, parseEndpoint(endpoint)); + invocationContext.addLocalContext(LoadBalanceFilter.SERVICECOMB_SERVER_ENDPOINT, parseEndpoint(endpoint)); date = new Date(); TestMgr.check(date.getTime(), dateTimeSchemaWithContextInf.getDate(invocationContext, date).getTime()); } @@ -144,21 +148,21 @@ private void testDateTimeSchemaMulticast() throws Exception { private Endpoint parseEndpoint(String endpointUri) throws Exception { URI formatUri = new URI(endpointUri); - Transport transport = SCBEngine.getInstance().getTransportManager().findTransport(formatUri.getScheme()); + Transport transport = scbEngine.getTransportManager().findTransport(formatUri.getScheme()); return new Endpoint(transport, endpointUri); } private void testDateTimeSchemaMulticastRestTemplate() throws Exception { DiscoveryContext context = new DiscoveryContext(); - VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc", "0+"); - List enpoints = serversVersionedCache.data(); + VersionedCache serversVersionedCache = discoveryTree.discovery(context, "springmvctest", "springmvc"); + List endpoints = serversVersionedCache.data(); - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); - for (String endpoint : enpoints) { + for (String endpoint : endpoints) { CseHttpEntity entity = new CseHttpEntity<>(null); InvocationContext invocationContext = new InvocationContext(); - invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, endpoint); + invocationContext.addLocalContext(LoadBalanceFilter.SERVICECOMB_SERVER_ENDPOINT, endpoint); entity.setContext(invocationContext); Date date = new Date(); @@ -170,7 +174,7 @@ private void testDateTimeSchemaMulticastRestTemplate() throws Exception { entity = new CseHttpEntity<>(null); invocationContext = new InvocationContext(); - invocationContext.addLocalContext(LoadbalanceHandler.SERVICECOMB_SERVER_ENDPOINT, parseEndpoint(endpoint)); + invocationContext.addLocalContext(LoadBalanceFilter.SERVICECOMB_SERVER_ENDPOINT, parseEndpoint(endpoint)); entity.setContext(invocationContext); date = new Date(); diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownloadSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownloadSchema.java index 37a24116a44..f1ba4b87095 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownloadSchema.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestDownloadSchema.java @@ -17,24 +17,77 @@ package org.apache.servicecomb.demo.springmvc.client; +import java.net.URI; +import java.util.Collections; +import java.util.List; + import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @Component public class TestDownloadSchema implements CategorizedTestCase { + @Autowired + DiscoveryManager discoveryManager; + @Override public void testRestTransport() throws Exception { testDownloadFileAndDeleted(); + testDownloadFileAndDeletedCN(); testDownloadFileNotDeleted(); testDownloadFileWithNull(); + testSetContentTypeByResponseEntity(); + testResponseOKException(); + } + + private void testResponseOKException() { + List instances = + discoveryManager.findServiceInstances("springmvctest", "springmvc"); + String endpoint = instances.get(0).getEndpoints().stream() + .filter(item -> item.startsWith("rest")).findFirst().get(); + URI endpointItem = URI.create(endpoint); + RestTemplate template = new RestTemplate(); + + // This is for compatible usage. For best practise, any status code + // should have only one type of response. + ResponseEntity resultFail = template.getForEntity( + "http://" + endpointItem.getHost() + ":" + endpointItem.getPort() + + "/api/download/testResponseOKExceptionBean?exception=true", ResponseOKData.class); + TestMgr.check(200, resultFail.getStatusCode().value()); + TestMgr.check("code-005", resultFail.getBody().getErrorCode()); + TestMgr.check("error-005", resultFail.getBody().getErrorMessage()); + ResponseEntity resultOK = template.getForEntity( + "http://" + endpointItem.getHost() + ":" + endpointItem.getPort() + + "/api/download/testResponseOKExceptionBean?exception=false", boolean.class); + TestMgr.check(true, resultOK.getBody()); + + resultFail = template.getForEntity( + "http://" + endpointItem.getHost() + ":" + endpointItem.getPort() + + "/api/download/testResponseOKExceptionDownload?exception=true&content=ddd&contentType=plain/text", + ResponseOKData.class); + TestMgr.check(200, resultFail.getStatusCode().value()); + TestMgr.check("code-005", resultFail.getBody().getErrorCode()); + TestMgr.check("error-005", resultFail.getBody().getErrorMessage()); + + ResponseEntity resultPartOK = template.getForEntity( + "http://" + endpointItem.getHost() + ":" + endpointItem.getPort() + + "/api/download/testResponseOKExceptionDownload?exception=false&content=ddd&contentType=plain/text", + String.class); + TestMgr.check(200, resultPartOK.getStatusCode().value()); + TestMgr.check("ddd", resultPartOK.getBody()); } private void testDownloadFileAndDeleted() throws Exception { - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); ReadStreamPart readStreamPart = restTemplate .getForObject("servicecomb://springmvc/download/deleteAfterFinished?content=hello", ReadStreamPart.class); String hello = readStreamPart.saveAsString().get(); @@ -45,8 +98,21 @@ private void testDownloadFileAndDeleted() throws Exception { TestMgr.check(exists, false); } + private void testDownloadFileAndDeletedCN() throws Exception { + RestOperations restTemplate = RestTemplateBuilder.create(); + ReadStreamPart readStreamPart = restTemplate + .getForObject("servicecomb://springmvc/download/deleteAfterFinished?content={1}&fileName={2}", + ReadStreamPart.class, "hello", "中文"); + String hello = readStreamPart.saveAsString().get(); + TestMgr.check(hello, "hello"); + + boolean exists = restTemplate + .getForObject("servicecomb://springmvc/download/assertLastFileDeleted", boolean.class); + TestMgr.check(exists, false); + } + private void testDownloadFileWithNull() throws Exception { - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); ReadStreamPart readStreamPart = restTemplate .getForObject("servicecomb://springmvc/download/partIsNull?content=test", ReadStreamPart.class); String result = readStreamPart.saveAsString().get(); @@ -59,7 +125,7 @@ private void testDownloadFileWithNull() throws Exception { } private void testDownloadFileNotDeleted() throws Exception { - RestTemplate restTemplate = RestTemplateBuilder.create(); + RestOperations restTemplate = RestTemplateBuilder.create(); ReadStreamPart readStreamPart = restTemplate .getForObject("servicecomb://springmvc/download/notDeleteAfterFinished?content=hello", ReadStreamPart.class); String hello = readStreamPart.saveAsString().get(); @@ -69,4 +135,15 @@ private void testDownloadFileNotDeleted() throws Exception { .getForObject("servicecomb://springmvc/download/assertLastFileDeleted", boolean.class); TestMgr.check(exists, true); } + + private void testSetContentTypeByResponseEntity() throws Exception { + RestOperations restTemplate = RestTemplateBuilder.create(); + ResponseEntity responseEntity = restTemplate + .getForEntity( + "servicecomb://springmvc/download/setContentTypeByResponseEntity?content=hello&contentType=customType", + ReadStreamPart.class); + String hello = responseEntity.getBody().saveAsString().get(); + TestMgr.check(responseEntity.getHeaders().get(HttpHeaders.CONTENT_TYPE), Collections.singletonList("customType")); + TestMgr.check(hello, "hello"); + } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestFactoryBean.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestFactoryBean.java new file mode 100644 index 00000000000..78295f47a8a --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestFactoryBean.java @@ -0,0 +1,42 @@ +/* + * 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.demo.springmvc.client; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.springmvc.client.factory.ServiceBean; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class TestFactoryBean implements CategorizedTestCase, ApplicationContextAware { + ApplicationContext applicationContext; + + @Override + public void testRestTransport() throws Exception { + ServiceBean serviceBean = (ServiceBean) this.applicationContext.getBean("ServiceFactoryBean"); + TestMgr.check("a-3", serviceBean.getName()); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestGeneric.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestGeneric.java index 0a950b56ced..ce976f10d5b 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestGeneric.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestGeneric.java @@ -23,14 +23,14 @@ import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.foundation.common.Holder; import org.apache.servicecomb.provider.pojo.Invoker; -import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.http.HttpStatus; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; public class TestGeneric { private CodeFirstSpringmvcIntf intf; - private RestTemplate restTemplate = new CseRestTemplate(); + private RestOperations restTemplate = RestTemplateBuilder.create(); private String prefix = "cse://springmvc/codeFirstSpringmvc"; diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestInvokeWhenServerNotReady.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestInvokeWhenServerNotReady.java index 5be0e2ff127..899de3dcdca 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestInvokeWhenServerNotReady.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestInvokeWhenServerNotReady.java @@ -26,7 +26,7 @@ import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class TestInvokeWhenServerNotReady { @@ -41,50 +41,44 @@ public TestInvokeWhenServerNotReady() { } private void startRestTemplateCall() { - new Thread() { - public void run() { - for (int i = 0; i < 100; i++) { - try { - RestTemplate template = RestTemplateBuilder.create(); - template.getForObject("servicecomb://springmvc/upload/isServerStartUpSuccess", Boolean.class); - } catch (Throwable e) { - // ignore - } + new Thread(() -> { + for (int i = 0; i < 100; i++) { + try { + RestOperations template = RestTemplateBuilder.create(); + template.getForObject("servicecomb://springmvc/upload/isServerStartUpSuccess", Boolean.class); + } catch (Throwable e) { + // ignore } } - }.start(); + }).start(); } private void startRpcCall() { - new Thread() { - public void run() { - for (int i = 0; i < 100; i++) { - try { - InvocationContext context = new InvocationContext(); - client.testInvocationTimeout(context, 1001, "customized"); - } catch (Throwable e) { - // ignore - } + new Thread(() -> { + for (int i = 0; i < 100; i++) { + try { + InvocationContext context = new InvocationContext(); + client.testInvocationTimeout(context, 1001, "customized"); + } catch (Throwable e) { + // ignore } } - }.start(); + }).start(); } private void startInvokerUtilsCall() { - new Thread() { - public void run() { - for (int i = 0; i < 100; i++) { - try { - Map args = new HashMap<>(); - args.put("timeout", 1); - args.put("name", "customized"); - InvokerUtils - .syncInvoke("springmvc", "SpringMVCCommonSchemaInterface", "testInvocationTimeout", args, String.class); - } catch (Throwable e) { - // ignore - } + new Thread(() -> { + for (int i = 0; i < 100; i++) { + try { + Map args = new HashMap<>(); + args.put("timeout", 1); + args.put("name", "customized"); + InvokerUtils + .syncInvoke("springmvc", "SpringMVCCommonSchemaInterface", "testInvocationTimeout", args, String.class); + } catch (Throwable e) { + // ignore } } - }.start(); + }).start(); } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestManagementEndpoint.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestManagementEndpoint.java new file mode 100644 index 00000000000..edac80715a8 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestManagementEndpoint.java @@ -0,0 +1,153 @@ +/* + * 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.demo.springmvc.client; + +import java.util.Map; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.solution.basic.integration.ManagementEndpoint; +import org.springframework.stereotype.Component; + +@Component +public class TestManagementEndpoint implements CategorizedTestCase { + private static final String CONTENT_SCHEMA = """ + openapi: 3.0.1 + info: + title: swagger definition for org.apache.servicecomb.demo.springmvc.server.SchemeInterfaceSpringmvc + version: 1.0.0 + servers: + - url: /springmvc/schemaInterface + paths: + /add: + get: + operationId: add + parameters: + - name: a + in: query + required: true + schema: + minimum: 1 + type: integer + format: int32 + - name: b + in: query + required: true + schema: + minimum: 1 + type: integer + format: int32 + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: integer + format: int32 + /nonTailingSlash: + get: + operationId: nonTailingSlash + parameters: + - name: a + in: query + required: true + schema: + minimum: 1 + type: integer + format: int32 + - name: b + in: query + required: true + schema: + minimum: 1 + type: integer + format: int32 + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /tailingSlash/: + get: + operationId: tailingSlash + parameters: + - name: a + in: query + required: true + schema: + minimum: 1 + type: integer + format: int32 + - name: b + in: query + required: true + schema: + minimum: 1 + type: integer + format: int32 + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + components: {} + """; + + @RpcReference(microserviceName = "springmvc", schemaId = "SchemeInterfaceSpringmvc") + private SchemeInterfaceSpringmvc schemeInterfaceSpringmvc; + + @RpcReference(microserviceName = "springmvc", schemaId = ManagementEndpoint.NAME) + private ManagementEndpoint managementEndpoint; + + @Override + public void testAllTransport() throws Exception { + testSchemeInterfaceSpringmvcContentCorrect(); + } + + @Override + public void testRestTransport() throws Exception { + testSchemeInterfaceSpringmvcPathSlashCorrect(); + testSchemeInterfaceSpringmvcPathNonSlashCorrect(); + } + + private void testSchemeInterfaceSpringmvcPathSlashCorrect() { + String result = schemeInterfaceSpringmvc.tailingSlash(3, 5); + TestMgr.check("/api/springmvc/schemaInterface/tailingSlash/;" + + "/api/springmvc/schemaInterface/tailingSlash/;" + + "/api/springmvc/schemaInterface/tailingSlash/;" + + "-2", result); + } + + private void testSchemeInterfaceSpringmvcPathNonSlashCorrect() { + String result = schemeInterfaceSpringmvc.nonTailingSlash(3, 5); + TestMgr.check("/api/springmvc/schemaInterface/nonTailingSlash;" + + "/api/springmvc/schemaInterface/nonTailingSlash;" + + "/api/springmvc/schemaInterface/nonTailingSlash;" + + "-2", result); + } + + private void testSchemeInterfaceSpringmvcContentCorrect() { + Map contents = managementEndpoint.schemaContents(); + TestMgr.check(CONTENT_SCHEMA, contents.get("SchemeInterfaceSpringmvc")); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestMaxHttpUrlLength.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestMaxHttpUrlLength.java index d696b40f69a..08f9cdda1ee 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestMaxHttpUrlLength.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestMaxHttpUrlLength.java @@ -15,36 +15,37 @@ */ package org.apache.servicecomb.demo.springmvc.client; -import static javax.ws.rs.core.Response.Status.REQUEST_URI_TOO_LONG; +import static jakarta.ws.rs.core.Response.Status.REQUEST_URI_TOO_LONG; import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; import com.google.common.base.Strings; -import com.netflix.config.DynamicPropertyFactory; @Component public class TestMaxHttpUrlLength implements CategorizedTestCase { @Override public void testRestTransport() throws Exception { - if (DynamicPropertyFactory.getInstance().getBooleanProperty("servicecomb.test.vert.transport", true).get()) { + if (LegacyPropertyFactory.getBooleanProperty("servicecomb.test.vert.transport", true)) { testUrlNotLongerThan4096(); } } private void testUrlNotLongerThan4096() { - RestTemplate restTemplate = RestTemplateBuilder.create(); - - String q = Strings.repeat("q", 4096 - "GET /springmvc/controller/sayhi?name=".length() - " HTTP/1.1\r".length()); + RestOperations restTemplate = RestTemplateBuilder.create(); + // \r doesn't count for url length Since netty 4.1.88.Final See https://github.com/netty/netty/pull/12321 + String q = Strings.repeat("q", + 4096 + 1 - "GET /api/springmvc/controller/sayhi?name=".length() - " HTTP/1.1\r".length()); TestMgr.check("hi " + q + " [" + q + "]", restTemplate.getForObject("cse://springmvc/springmvc/controller/sayhi?name=" + q, String.class)); - q = Strings.repeat("q", 4096 + 1 - "GET /springmvc/controller/sayhi?name=".length() - " HTTP/1.1\r".length()); + q = Strings.repeat("q", 4096 + 2 - "GET /api/springmvc/controller/sayhi?name=".length() - " HTTP/1.1\r".length()); try { restTemplate.getForObject("cse://springmvc/springmvc/controller/sayhi?name=" + q, String.class); @@ -53,14 +54,4 @@ private void testUrlNotLongerThan4096() { TestMgr.check(REQUEST_URI_TOO_LONG.getStatusCode(), e.getStatusCode()); } } - - @Override - public void testHighwayTransport() throws Exception { - - } - - @Override - public void testAllTransport() throws Exception { - - } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java index 9cd55cdcbbd..498a7d0c832 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestObject.java @@ -26,13 +26,13 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.common.Holder; import org.apache.servicecomb.provider.pojo.Invoker; -import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate; -import org.springframework.web.client.RestTemplate; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.web.client.RestOperations; public class TestObject { private CodeFirstSpringmvcIntf intf; - private RestTemplate restTemplate = new CseRestTemplate(); + private RestOperations restTemplate = RestTemplateBuilder.create(); private String prefix = "cse://springmvc/codeFirstSpringmvc"; @@ -41,20 +41,17 @@ public TestObject() { } public void runRest() { - testEmptyObject_rest(); - testMapObject_rest(); - testObject(); - testListObject(); - testHolderObject(); + } public void runHighway() { - testEmptyObject_highway(); - testMapObject_highway(); + } public void runAllTransport() { testObject(); + testMapObject(); + testEmptyObject(); testListObject(); testHolderObject(); } @@ -82,19 +79,7 @@ private void testListObject() { } @SuppressWarnings("unchecked") - private void testMapObject_rest() { - Map map = Collections.singletonMap("k", "v"); - Map result = intf.testMapObject(map); - TestMgr.check("{k=v}", result); - TestMgr.check(LinkedHashMap.class, result.getClass()); - - result = restTemplate.postForObject(prefix + "/mapObject", map, Map.class); - TestMgr.check("{k=v}", result); - TestMgr.check(LinkedHashMap.class, result.getClass()); - } - - @SuppressWarnings("unchecked") - private void testMapObject_highway() { + private void testMapObject() { Map map = Collections.singletonMap("k", "v"); Map result = intf.testMapObject(map); TestMgr.check("{k=v}", result); @@ -106,16 +91,7 @@ private void testMapObject_highway() { TestMgr.check(LinkedHashMap.class, result.getClass()); } - private void testEmptyObject_highway() { - // This is a behavior change in 2.0.0, before 2.0.0 this return null - EmptyObject result = intf.testEmpty(new EmptyObject()); - TestMgr.check(result instanceof EmptyObject, true); - - result = restTemplate.postForObject(prefix + "/emptyObject", new EmptyObject(), EmptyObject.class); - TestMgr.check(result instanceof EmptyObject, true); - } - - private void testEmptyObject_rest() { + private void testEmptyObject() { EmptyObject result = intf.testEmpty(new EmptyObject()); TestMgr.check(EmptyObject.class, result.getClass()); @@ -175,6 +151,8 @@ private void testObject() { TestMgr.check(true, List.class.isAssignableFrom(result.getClass())); // generic + // This test case for HIGHWAY is not stable. + // When proto schema contains Holder message, the result type is Map. Or the result is Holder(using json). Holder holder = new Holder<>("v"); result = intf.testObject(holder); TestMgr.check("v", ((Map) result).get("value")); diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java index cae0c130eb6..bede84dadaf 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestResponse.java @@ -18,14 +18,17 @@ import java.util.Date; import java.util.Objects; +import java.util.concurrent.atomic.AtomicInteger; +import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.demo.compute.GenericParam; import org.apache.servicecomb.demo.compute.Person; import org.apache.servicecomb.provider.pojo.Invoker; -import org.apache.servicecomb.registry.RegistrationManager; import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.core.env.Environment; import org.springframework.http.ResponseEntity; import com.fasterxml.jackson.databind.exc.InvalidFormatException; @@ -33,6 +36,12 @@ public class TestResponse { private CodeFirstSpringmvcIntf intf; + private Environment environment; + + public void setEnvironment(Environment environment) { + this.environment = environment; + } + public TestResponse() { intf = Invoker.createProxy("springmvc", "codeFirst", CodeFirstSpringmvcIntf.class); } @@ -61,7 +70,7 @@ public void runAllTransport() { } private void testCseResponse() { - String srcName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); + String srcName = BootStrapProperties.readServiceName(environment); Response cseResponse = intf.cseResponse(); TestMgr.check("User [name=nameA, age=100, index=0]", cseResponse.getResult()); TestMgr.check("h1v " + srcName, cseResponse.getHeader("h1")); @@ -70,7 +79,7 @@ private void testCseResponse() { } private void testCseResponseCorrect() { - String srcName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); + String srcName = BootStrapProperties.readServiceName(environment); Response cseResponse = intf.cseResponseCorrect(); TestMgr.check("User [name=nameA, age=100, index=0]", cseResponse.getResult()); TestMgr.check("h1v " + srcName, cseResponse.getHeader("h1")); @@ -81,14 +90,14 @@ private void testCseResponseCorrect() { private void testResponseEntity() { Date date = new Date(); - String srcName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); + String srcName = BootStrapProperties.readServiceName(environment); ResponseEntity responseEntity = intf.responseEntity(date); TestMgr.check(date, responseEntity.getBody()); TestMgr.check("h1v " + srcName, responseEntity.getHeaders().getFirst("h1")); TestMgr.check("h2v " + srcName, responseEntity.getHeaders().getFirst("h2")); - TestMgr.check(202, responseEntity.getStatusCodeValue()); + TestMgr.check(202, responseEntity.getStatusCode().value()); } private void testvoidResponse() { @@ -133,20 +142,19 @@ private void testDelay() { } private void testAbort() { - StringBuilder result = new StringBuilder(); - for (int i = 0; i < 4; ++i) { - String response; + AtomicInteger count = new AtomicInteger(0); + for (int i = 0; i < 100; ++i) { try { - response = intf.testAbort(); + String response = intf.testAbort(); + count.incrementAndGet(); + TestMgr.check("OK", response); } catch (InvocationException e) { - response = e.getMessage(); + TestMgr.check(421, e.getStatusCode()); + TestMgr.check("aborted by fault inject", ((CommonExceptionData) e.getErrorData()).getMessage()); } - result.append(response).append("|"); } - TestMgr.check( - "OK|InvocationException: code=421;msg=CommonExceptionData [message=aborted by fault inject]|" - + "OK|InvocationException: code=421;msg=CommonExceptionData [message=aborted by fault inject]|", - result.toString()); + // 50% percent fail + TestMgr.check(true, count.get() >= 30 && count.get() <= 70); } private void testDecodeResponseError() { diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRestTemplate.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRestTemplate.java index 5b7ad372f70..a9d02553bf7 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRestTemplate.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRestTemplate.java @@ -25,10 +25,10 @@ import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.util.Assert; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; public class TestRestTemplate { - private RestTemplate restTemplate = RestTemplateBuilder.create(); + private RestOperations restTemplate = RestTemplateBuilder.create(); public void runAllTest() { testvoidResponse(); @@ -46,16 +46,19 @@ public void runRest() { private void testvoidResponse() { ResponseEntity resultEntity = restTemplate .getForEntity("cse://springmvc/codeFirstSpringmvc/testvoidInRestTemplate", void.class); - Assert.isTrue(200 == resultEntity.getStatusCodeValue(), "void return type invocation failed"); + Assert.isTrue(200 == resultEntity.getStatusCode().value(), "void return type invocation failed"); } private void testVoidResponse() { ResponseEntity resultEntity = restTemplate .getForEntity("cse://springmvc/codeFirstSpringmvc/testVoidInRestTemplate", Void.class); - Assert.isTrue(200 == resultEntity.getStatusCodeValue(), "Void return type invocation failed"); + Assert.isTrue(200 == resultEntity.getStatusCode().value(), "Void return type invocation failed"); resultEntity = restTemplate .getForEntity("servicecomb://springmvc/codeFirstSpringmvc/testVoidInRestTemplate", Void.class); - Assert.isTrue(200 == resultEntity.getStatusCodeValue(), "Void return type invocation failed"); + Assert.isTrue(200 == resultEntity.getStatusCode().value(), "Void return type invocation failed"); + resultEntity = restTemplate + .getForEntity("servicecomb://springmvc/codeFirstSpringmvc/testDefaultGetApiExample", Void.class); + Assert.isTrue(200 == resultEntity.getStatusCode().value(), "Void return type invocation failed"); } private void checkAllVoidTestResult() { diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRetrySchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRetrySchema.java new file mode 100644 index 00000000000..501ff30f1fc --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestRetrySchema.java @@ -0,0 +1,61 @@ +/* + * 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.demo.springmvc.client; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestOperations; + +@Component +public class TestRetrySchema implements CategorizedTestCase { + interface RetrySchemaInf { + boolean successWhenRetry(); + + CompletableFuture successWhenRetryAsync(); + } + + @RpcReference(microserviceName = "springmvc", schemaId = "RetrySchema") + private RetrySchemaInf retrySchemaInf; + + RestOperations restTemplate = RestTemplateBuilder.create(); + + private static final String SERVER = "servicecomb://springmvc"; + + @Override + public void testAllTransport() throws Exception { + testRetryGovernanceRestTemplate(); + testRetryGovernanceRpc(); + } + + private void testRetryGovernanceRpc() throws Exception { + TestMgr.check(retrySchemaInf.successWhenRetry(), true); + TestMgr.check(retrySchemaInf.successWhenRetry(), true); + + TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true); + TestMgr.check(retrySchemaInf.successWhenRetryAsync().get(), true); + } + + private void testRetryGovernanceRestTemplate() { + TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true); + TestMgr.check(restTemplate.getForObject(SERVER + "/retry/governance/successWhenRetry", boolean.class), true); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.java index c29fda9d682..03dd6c019a4 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSchemeInterfaceSpringmvc.java @@ -20,6 +20,8 @@ import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.springframework.stereotype.Component; @Component @@ -33,12 +35,12 @@ public void testAllTransport() throws Exception { try { springmvc.reduce(1, 3); TestMgr.failed("should throw exception", new Exception()); - } catch (Exception e) { + } catch (InvocationException e) { TestMgr.check( "Consumer method org.apache.servicecomb.demo.springmvc.client.SchemeInterfaceSpringmvc:reduce not " + "exist in contract, microserviceName=springmvc, " - + "schemaId=SchemeInterfaceSpringmvc; new producer not running or not deployed.", - e.getMessage()); + + "schemaId=SchemeInterfaceSpringmvc.", + ((CommonExceptionData) e.getErrorData()).getMessage()); } } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java index 3b86349ce37..e832cbbf5b1 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java @@ -44,7 +44,10 @@ public void testAllTransport() throws Exception { private void testInvocationTimeoutInClientWait() { try { - client.testInvocationTimeoutInClientWait(500, "hello"); + long begin = System.currentTimeMillis(); + String result = client.testInvocationTimeoutInClientWait(1000, "hello"); + System.out.println("test code from testInvocationTimeoutInClientWait: " + + (System.currentTimeMillis() - begin) + ":" + result); TestMgr.fail("should timeout"); } catch (InvocationException e) { TestMgr.check(408, e.getStatusCode()); @@ -67,8 +70,12 @@ private void testInvocationAlreadyTimeoutInClient() { try { InvocationContext context = new InvocationContext(); context.addLocalContext(ProcessingTimeStrategy.CHAIN_START_TIME, System.nanoTime()); - context.addLocalContext(ProcessingTimeStrategy.CHAIN_PROCESSING, TimeUnit.SECONDS.toNanos(1)); - client.testInvocationTimeout(context, 1, "hello"); + context.addLocalContext(ProcessingTimeStrategy.CHAIN_PROCESSING, TimeUnit.SECONDS.toNanos(2)); + + long begin = System.currentTimeMillis(); + String result = client.testInvocationTimeout(context, 10, "hello"); + System.out.println("testInvocationAlreadyTimeoutInClient from invocation timeout: " + + (System.currentTimeMillis() - begin) + ":" + result); TestMgr.fail("should timeout"); } catch (InvocationException e) { TestMgr.check(408, e.getStatusCode()); diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdPartyRegistration.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdPartyRegistration.java index 0ad71996615..8dc088010fb 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdPartyRegistration.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdPartyRegistration.java @@ -17,30 +17,22 @@ package org.apache.servicecomb.demo.springmvc.client; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.provider.pojo.Invoker; -import org.apache.servicecomb.registry.RegistrationManager; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; @Component public class TestThirdPartyRegistration implements BootListener, CategorizedTestCase { + @Autowired private ThirdPartyService thirdPartyService; @Override public void onAfterRegistry(BootEvent event) { - List endpoints = new ArrayList<>(); - endpoints.add("rest://localhost:8080"); - RegistrationManager.INSTANCE.registerMicroserviceMappingByEndpoints("testServiceName", - "1.0.1", endpoints, ThirdPartyService.class); - thirdPartyService = Invoker.createProxy("testServiceName", - "testServiceName", ThirdPartyService.class); } @Override @@ -48,11 +40,11 @@ public void testRestTransport() throws Exception { Date date = new Date(); ResponseEntity responseEntity = thirdPartyService.responseEntity(date); TestMgr.check(date, responseEntity.getBody()); - // Third party invocation do not pass cse-context to the target + // Third party invocation will pass cse-context to the target too TestMgr.check("h1v null", responseEntity.getHeaders().getFirst("h1")); TestMgr.check("h2v null", responseEntity.getHeaders().getFirst("h2")); - TestMgr.check(202, responseEntity.getStatusCodeValue()); + TestMgr.check(202, responseEntity.getStatusCode().value()); } @Override diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdSvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdSvc.java new file mode 100644 index 00000000000..98592c9bce2 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestThirdSvc.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.demo.springmvc.client; + +import java.util.Date; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.demo.springmvc.client.ThirdSvc.ThirdSvcClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; + +@Component +public class TestThirdSvc implements CategorizedTestCase { + private ThirdSvcClient client; + + @Autowired + public void setThirdSvcClient(ThirdSvcClient client) { + this.client = client; + } + + @Override + public void testAllTransport() throws Exception { + testResponseEntity(); + + testDifferentParameterName(); + } + + private void testDifferentParameterName() { + String result = client.getAuthorization("test", "param", "auth"); + TestMgr.check("testparamauth", result); + } + + private void testResponseEntity() { + Date date = new Date(); + ResponseEntity responseEntity = client.responseEntity(date); + TestMgr.check(date, responseEntity.getBody()); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestTransportSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestTransportSchema.java new file mode 100644 index 00000000000..d818ed439d4 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestTransportSchema.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.demo.springmvc.client; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class TestTransportSchema implements CategorizedTestCase { + interface TransportClient { + boolean restTransport(); + + boolean highwayTransport(); + } + + @RpcReference(microserviceName = "springmvc", schemaId = "TransportSchema") + private TransportClient transportClient; + + @Override + public void testRestTransport() throws Exception { + testTransportSchema(); + } + + @Override + public void testHighwayTransport() throws Exception { + testTransportSchema(); + } + + @Override + public void testAllTransport() throws Exception { + testTransportSchema(); + } + + private void testTransportSchema() { + TestMgr.check(true, transportClient.highwayTransport()); + TestMgr.check(true, transportClient.restTransport()); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java index c43f8e273e9..0e6d810d4a5 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java @@ -19,33 +19,53 @@ import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; +import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.servicecomb.demo.CategorizedTestCase; import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class TestUploadSchema implements CategorizedTestCase { + + interface FileUploadMultiInf { + String fileUploadMultiRpc(List files); + } + + @RpcReference(microserviceName = "springmvc", schemaId = "UploadSchema") + private FileUploadMultiInf fileUploadMultiInf; + @Override public void testRestTransport() throws Exception { testServerStartupSuccess(); testUploadMultiBigFiles(); + testFileUploadMultiRpc(); + testUploadFileAndAttribute(); + testUploadFileAndAttributeCN(); + testUploadFileRequestPartAttribute(); + testUploadFileRequestPartAttributeList(); } private void testServerStartupSuccess() { - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); boolean result = template.getForObject("servicecomb://springmvc/upload/isServerStartUpSuccess", Boolean.class); TestMgr.check(result, true); } @@ -65,7 +85,7 @@ private void testUploadMultiBigFiles() throws Exception { fo.close(); } - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); MultiValueMap map = new LinkedMultiValueMap<>(); for (int i = 0; i < fileNum; i++) { @@ -79,6 +99,86 @@ private void testUploadMultiBigFiles() throws Exception { String result = template.postForObject("servicecomb://springmvc/upload/fileUpload", entity, String.class); TestMgr.check(result, "success"); - files.forEach(file -> file.delete()); + files.forEach(File::delete); + } + + private void testFileUploadMultiRpc() throws IOException { + File file1 = File.createTempFile("file1", ".txt"); + File file2 = File.createTempFile("file2", ".txt"); + List files = new ArrayList<>(); + files.add(new FileSystemResource(file1)); + files.add(new FileSystemResource(file2)); + String result = fileUploadMultiInf.fileUploadMultiRpc(files); + TestMgr.check(result, "fileUploadMulti success, and fileNum is 2"); + } + + private void testUploadFileAndAttribute() throws Exception { + RestOperations template = RestTemplateBuilder.create(); + Map map = new HashMap<>(); + String message = "hi"; + File file = File.createTempFile("file", ".txt"); + FileUtils.writeStringToFile(file, "test", StandardCharsets.UTF_8, false); + + map.put("file", new FileSystemResource(file)); + map.put("attribute", message); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA); + String result = template.postForObject("servicecomb://springmvc/upload/uploadFileAndAttribute", + new HttpEntity<>(map, headers), String.class); + TestMgr.check("hi test", result); + } + + private void testUploadFileAndAttributeCN() throws Exception { + RestOperations template = RestTemplateBuilder.create(); + Map map = new HashMap<>(); + String message = "hi"; + File file = File.createTempFile("中文名称", ".txt"); + FileUtils.writeStringToFile(file, "test", StandardCharsets.UTF_8, false); + + map.put("file", new FileSystemResource(file)); + map.put("attribute", message); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA); + String result = template.postForObject("servicecomb://springmvc/upload/uploadFileAndAttribute", + new HttpEntity<>(map, headers), String.class); + TestMgr.check("hi test", result); + } + + + private void testUploadFileRequestPartAttribute() throws Exception { + RestOperations template = RestTemplateBuilder.create(); + Map map = new HashMap<>(); + String message = "hi"; + File file = File.createTempFile("file", ".txt"); + FileUtils.writeStringToFile(file, "test", StandardCharsets.UTF_8, false); + + map.put("file", new FileSystemResource(file)); + map.put("attribute", message); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA); + String result = template.postForObject("servicecomb://springmvc/upload/uploadFileRequestPartAttribute", + new HttpEntity<>(map, headers), String.class); + TestMgr.check("hi test", result); + } + + private void testUploadFileRequestPartAttributeList() throws Exception { + RestOperations template = RestTemplateBuilder.create(); + MultiValueMap map = new LinkedMultiValueMap<>(); + String message1 = "msg1"; + String message2 = "msg2"; + File file1 = File.createTempFile("file1", ".txt"); + FileUtils.writeStringToFile(file1, "test1", StandardCharsets.UTF_8, false); + File file2 = File.createTempFile("file2", ".txt"); + FileUtils.writeStringToFile(file2, "test2", StandardCharsets.UTF_8, false); + + map.add("files", new FileSystemResource(file1)); + map.add("files", new FileSystemResource(file2)); + map.add("attributes", message1); + map.add("attributes", message2); + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(org.springframework.http.MediaType.MULTIPART_FORM_DATA); + String result = template.postForObject("servicecomb://springmvc/upload/uploadFileRequestPartAttributeList", + new HttpEntity<>(map, headers), String.class); + TestMgr.check("test1test2msg1msg2", result); } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestWeakSpringmvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestWeakSpringmvc.java index 3c465cf3c88..df9f8236215 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestWeakSpringmvc.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestWeakSpringmvc.java @@ -32,7 +32,7 @@ import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; import com.fasterxml.jackson.core.JsonProcessingException; @@ -97,7 +97,7 @@ interface SpecialNameModelInf { @Component public class TestWeakSpringmvc implements CategorizedTestCase { - @Value("${APPLICATION_ID}") + @Value("${servicecomb.service.application}") private String applicationName; @RpcReference(microserviceName = "springmvc", schemaId = "weakSpringmvc") @@ -115,20 +115,10 @@ public class TestWeakSpringmvc implements CategorizedTestCase { @RpcReference(microserviceName = "springmvc", schemaId = "weakSpringmvc") private SpecialNameModelInf specialNameModelInf; - @RpcReference(microserviceName = "${APPLICATION_ID}:springmvc", schemaId = "weakSpringmvc") + @RpcReference(microserviceName = "${servicecomb.service.application}:springmvc", schemaId = "weakSpringmvc") private SpecialNameModelInf specialNameModelInfWithAppId; - private RestTemplate restTemplate = RestTemplateBuilder.create(); - - @Override - public void testRestTransport() throws Exception { - - } - - @Override - public void testHighwayTransport() throws Exception { - - } + private RestOperations restTemplate = RestTemplateBuilder.create(); @Override public void testAllTransport() throws Exception { @@ -138,10 +128,10 @@ public void testAllTransport() throws Exception { testGenericsModel(); - testSpecailNameModel(); + testSpecialNameModel(); } - private void testSpecailNameModel() { + private void testSpecialNameModel() { SpecialNameModel model = new SpecialNameModel(); model.setaIntName(30); SpecialNameModel result = specialNameModelInf.specialNameModel(0, model); @@ -180,7 +170,6 @@ private void testGenerics() { TestMgr.check("hello", nameListResult.get(0).get(0)); } - @SuppressWarnings({"deprecation"}) private void testDiffName() { TestMgr.check(7, diffNames.differentName(2, 3)); TestMgr.check(8, diffNames2.differentName(2, 3)); @@ -192,8 +181,8 @@ private void testDiffName() { args.put("x", 2); args.put("y", 3); TestMgr.check(7, InvokerUtils.syncInvoke("springmvc", - "weakSpringmvc", "differentName", args)); + "weakSpringmvc", "differentName", args, Integer.class)); TestMgr.check(7, InvokerUtils.syncInvoke(applicationName + ":springmvc", - "weakSpringmvc", "differentName", args)); + "weakSpringmvc", "differentName", args, Integer.class)); } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdPartyService.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdPartyService.java index e8a1c93d144..e31e1183333 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdPartyService.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdPartyService.java @@ -19,19 +19,23 @@ import java.util.Date; -import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; -import io.swagger.annotations.ResponseHeader; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; @RequestMapping(path = "/codeFirstSpringmvc", produces = MediaType.APPLICATION_JSON_VALUE) public interface ThirdPartyService { - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Date.class)) + , description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @RequestMapping(path = "/responseEntity", method = RequestMethod.POST) ResponseEntity responseEntity(@RequestAttribute("date") Date date); } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java index ae855e2d537..3cbd8dd97dd 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/ThirdSvc.java @@ -16,31 +16,91 @@ */ package org.apache.servicecomb.demo.springmvc.client; +import java.util.ArrayList; import java.util.Date; +import java.util.List; -import org.apache.servicecomb.provider.pojo.registry.ThirdServiceWithInvokerRegister; -import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders; +import org.apache.servicecomb.localregistry.RegistryBean; +import org.apache.servicecomb.localregistry.RegistryBean.Instance; +import org.apache.servicecomb.localregistry.RegistryBean.Instances; +import org.apache.servicecomb.provider.pojo.Invoker; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; -import io.swagger.annotations.ResponseHeader; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; @Configuration -public class ThirdSvc extends ThirdServiceWithInvokerRegister { +public class ThirdSvc { + @Autowired + Environment environment; + @RequestMapping(path = "/codeFirstSpringmvc") public interface ThirdSvcClient { - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Date.class)) + , description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @RequestMapping(path = "/responseEntity", method = RequestMethod.POST) ResponseEntity responseEntity(@RequestAttribute("date") Date date); + + @GetMapping(value = "/getAuthorization", produces = {"application/json"}) + String getAuthorization( + @RequestHeader(value = "test") String test, + @RequestParam(value = "param") String param, + @RequestHeader("Authorization") String authorization); + } + + @Bean + public RegistryBean thirdRegistryBean() { + String endpoint; + if (environment.getProperty("servicecomb.test.vert.transport", boolean.class, true)) { + endpoint = "rest://localhost:8080?sslEnabled=false&urlPrefix=%2Fapi"; + } else { + endpoint = "rest://localhost:8080?sslEnabled=false"; + } + + return new RegistryBean().addSchemaInterface("schema-1", ThirdSvcClient.class) + .setAppId("springmvctest") + .setServiceName("3rd-svc") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of(new Instance().setEndpoints(List.of(endpoint))))); } - public ThirdSvc() { - super("3rd-svc"); + @Bean + public ThirdSvcClient thirdSvcClient() { + return Invoker.createProxy("3rd-svc", "schema-1", ThirdSvcClient.class); + } + + @Bean + public RegistryBean thirdPartyServiceRegistryBean() { + List endpoints = new ArrayList<>(); + if (environment.getProperty("servicecomb.test.vert.transport", boolean.class, true)) { + endpoints.add("rest://localhost:8080?sslEnabled=false&urlPrefix=%2Fapi"); + } else { + endpoints.add("rest://localhost:8080?sslEnabled=false"); + } + + return new RegistryBean().addSchemaInterface("testServiceName", ThirdPartyService.class) + .setAppId("springmvctest") + .setServiceName("testServiceName") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of(new Instance().setEndpoints(endpoints)))); + } - addSchema("schema-1", ThirdSvcClient.class); + @Bean + public ThirdPartyService thirdPartyService() { + return Invoker.createProxy("testServiceName", "testServiceName", ThirdPartyService.class); } } diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceBean.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceBean.java new file mode 100644 index 00000000000..1a25838d083 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceBean.java @@ -0,0 +1,30 @@ +/* + * 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.demo.springmvc.client.factory; + +public class ServiceBean { + private final String name; + + public ServiceBean(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceFactoryBean.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceFactoryBean.java new file mode 100644 index 00000000000..9bee6805c48 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceFactoryBean.java @@ -0,0 +1,48 @@ +/* + * 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.demo.springmvc.client.factory; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component("ServiceFactoryBean") +public class ServiceFactoryBean implements FactoryBean { + + ServiceWithReference serviceWithReference; + + @Autowired + public ServiceFactoryBean(ServiceWithReference serviceWithReference) { + this.serviceWithReference = serviceWithReference; + } + + @Override + public ServiceBean getObject() throws Exception { + return new ServiceBean(serviceWithReference.test("a")); + } + + @Override + public Class getObjectType() { + return ServiceBean.class; + } + + @Override + public boolean isSingleton() { + return true; + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceWithReference.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceWithReference.java new file mode 100644 index 00000000000..f371bf35148 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceWithReference.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.demo.springmvc.client.factory; + +public interface ServiceWithReference { + String test(String name); +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceWithReferenceImpl.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceWithReferenceImpl.java new file mode 100644 index 00000000000..a5f8d7c6bb1 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/factory/ServiceWithReferenceImpl.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.demo.springmvc.client.factory; + +import org.apache.servicecomb.demo.springmvc.client.SchemeInterfaceSpringmvc; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component +public class ServiceWithReferenceImpl implements ServiceWithReference { + @RpcReference(schemaId = "SchemeInterfaceSpringmvc", microserviceName = "springmvc") + private SchemeInterfaceSpringmvc springmvc; + + @Override + public String test(String name) { + return name + "-" + springmvc.add(1, 2); + } +} diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/SpringMVCSchema.yaml b/demo/demo-springmvc/springmvc-client/src/main/resources/SpringMVCSchema.yaml index 6d805364e8f..db67a5779a9 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/resources/SpringMVCSchema.yaml +++ b/demo/demo-springmvc/springmvc-client/src/main/resources/SpringMVCSchema.yaml @@ -19,36 +19,53 @@ ################################################################################ ################################################################################ ################################################################################ - ---- -swagger: "2.0" +openapi: 3.0.1 info: - version: "1.0.0" - title: "swagger definition for org.apache.servicecomb.demo.springmvc.client.SpringMVCSchema" - x-java-interface: "gen.swagger.SpringMVCSchemaIntf" -basePath: "/springMvcSchema" -schemes: - - "http" -consumes: - - "application/json" -produces: - - "application/json" + title: swagger definition for org.apache.servicecomb.demo.springmvc.client.SpringMVCSchema + version: 1.0.0 +servers: +- url: /springMvcSchema paths: /testApiExample: post: - operationId: "testApiExample" + operationId: testApiExample + requestBody: + content: + application/json: + schema: + type: string + required: true + x-name: name + responses: + "200": + description: success + headers: {} + content: + application/json: + schema: + type: string + description: "" + nullable: false + example: wget http://localhost/springMvcSchema/testApiExample + /testDefaultGetApiExample: + get: + operationId: testDefaultGetApiExample parameters: - - in: "body" - name: "name" - required: true - schema: - type: "string" + - name: name + in: query + required: true + schema: + type: string responses: "200": - description: "success" - examples: - text: "wget http://localhost/springMvcSchema/testApiExample" - application/json: "{name:hello}" - json: "{name:hello}" - schema: - type: "string" + description: success + headers: {} + content: + application/json: + schema: + type: string + description: "" + nullable: false + example: "" +components: + schemas: {} diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties b/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties deleted file mode 100644 index ff989feda5d..00000000000 --- a/demo/demo-springmvc/springmvc-client/src/main/resources/config/log4j.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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. -# -log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF -log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/log4j2.xml b/demo/demo-springmvc/springmvc-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-springmvc/springmvc-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml index bc5e1c05f94..2fe0f881f55 100644 --- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml +++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml @@ -15,42 +15,29 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: springmvctest -service_description: - name: springmvcClient - version: 0.0.1 servicecomb: service: - registry: - address: http://127.0.0.1:9980,http://127.0.0.1:30100 + application: springmvctest + name: springmvcClient + version: 0.0.1 + registry: + sc: + address: http://127.0.0.1:30100 autodiscovery: true - client: - timeout: - idle: 60 - watch: 60 - instance: - healthCheck: - interval: 3 - pull: - interval: 90 - watch: true - # can download config center from https://cse-bucket.obs.myhwclouds.com/LocalCSE/Local-CSE-1.0.0.zip to test dynamic config - config: - client: - serverUri: http://127.0.0.1:30113 - refreshMode: 1 - refresh_interval: 5000 - refreshPort: 30114 + healthCheckIntervalInSeconds: 3 + pollIntervalInMillis: 90000 + watch: true + rest: client: connection: compression: true references: version-rule: 0+ - handler: - chain: - Consumer: - default: loadbalance,fault-injection-consumer,bizkeeper-consumer + request: + clientRequestHeaderFilterEnabled: + # Do not copy cse-context to target for microservice(testServiceName) + testServiceName: true invocation: timeout: check: @@ -67,9 +54,6 @@ servicecomb: userDefinedEndpoint.enabled: true strategy: name: WeightedResponse - retryEnabled: true - retryOnSame: 1 - retryOnNext: 1 filter.status.enabled: false fallbackpolicy: Consumer: @@ -93,6 +77,10 @@ servicecomb: name: myDC region: my-Region availableZone: my-Zone + + faultInjection: + enabled: true + governance: Consumer: springmvc: @@ -115,32 +103,29 @@ servicecomb: abort: httpStatus: 421 percent: 50 - test: - duplicate1: newer - -cse: - fallback: - Consumer: - springmvc: - codeFirstBizkeeperTest: - testTimeout: - enabled: false - isolation: - Consumer: - springmvc: - codeFirstBizkeeperTest: - testTimeout: - timeout: - enabled: true - timeoutInMilliseconds: 1000 - test: - duplicate2: newer -3rd-svc: - urls: - - http://localhost:8080 + # test governance retry + matchGroup: + retry-governance: | + matches: + - apiPath: + prefix: "/retry/governance/" + retry-success: | + matches: + - apiPath: + prefix: "/codeFirstSpringmvc/retrySuccess" + retry: + retry-governance: | + maxAttempts: 2 + retryOnResponseStatus: [500] + retry-success: | + maxAttempts: 2 + retryOnResponseStatus: [503] #########SSL options +# open jdk 8 now TLSv1.3 not available +# ssl.protocols: TLSv1.3 +# ssl.ciphers: TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384 ssl.protocols: TLSv1.2 ssl.authPeer: true ssl.checkCN.host: false diff --git a/demo/demo-springmvc/springmvc-client/src/test/java/org/apache/servicecomb/demo/springmvc/SpringMvcIT.java b/demo/demo-springmvc/springmvc-client/src/test/java/org/apache/servicecomb/demo/springmvc/SpringMvcIT.java index 5d610dee91f..c445ce1a647 100644 --- a/demo/demo-springmvc/springmvc-client/src/test/java/org/apache/servicecomb/demo/springmvc/SpringMvcIT.java +++ b/demo/demo-springmvc/springmvc-client/src/test/java/org/apache/servicecomb/demo/springmvc/SpringMvcIT.java @@ -17,25 +17,25 @@ package org.apache.servicecomb.demo.springmvc; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.springmvc.client.SpringmvcClient; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = SpringmvcClient.class) public class SpringMvcIT { - - @Before + @BeforeEach public void setUp() { TestMgr.errors().clear(); } @Test - public void clientGetsNoError() throws Exception { - SpringmvcClient.main(new String[0]); - - assertThat(TestMgr.errors().isEmpty(), is(true)); + public void clientGetsNoError() { + SpringmvcClient.run(); + Assertions.assertTrue(TestMgr.isSuccess()); } } diff --git a/demo/demo-springmvc/springmvc-server/pom.xml b/demo/demo-springmvc/springmvc-server/pom.xml index 8c4e0e9a96b..f88876261d6 100644 --- a/demo/demo-springmvc/springmvc-server/pom.xml +++ b/demo/demo-springmvc/springmvc-server/pom.xml @@ -23,61 +23,26 @@ org.apache.servicecomb.demo demo-springmvc - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT springmvc-server Java Chassis::Demo::Spring MVC::Server - - org.apache.servicecomb.demo - demo-schema - - - org.apache.servicecomb - provider-springmvc - - - org.apache.servicecomb - swagger-invocation-validator - org.apache.servicecomb metrics-prometheus - - - org.apache.servicecomb - config-cc - - - - org.apache.servicecomb.demo - demo-signature - - org.apache.servicecomb.demo.springmvc.server.SpringmvcServer + org.apache.servicecomb.demo.springmvc.SpringmvcServer - org.apache.maven.plugins - maven-dependency-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - + org.springframework.boot + spring-boot-maven-plugin @@ -86,15 +51,50 @@ 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 - - org.commonjava.maven.plugins - directory-maven-plugin - diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/SpringmvcServer.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/SpringmvcServer.java new file mode 100644 index 00000000000..52ede2792d8 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/SpringmvcServer.java @@ -0,0 +1,46 @@ +/* + * 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.demo.springmvc; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class SpringmvcServer { + public static void main(String[] args) throws Exception { + new SpringApplicationBuilder(SpringmvcServer.class).web(WebApplicationType.NONE).run(args); + + runTests(); + + TestMgr.summary(); + if (!TestMgr.isSuccess()) { + System.exit(1); + } + } + + private static void runTests() { + try { + CategorizedTestCaseRunner.runCategorizedTestCase("springmvc"); + } catch (Exception e) { + TestMgr.failed("runCategorizedTestCase failed", e); + } + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/filter/ProviderTestFilter.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/filter/ProviderTestFilter.java new file mode 100644 index 00000000000..310f68e0ca0 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/filter/ProviderTestFilter.java @@ -0,0 +1,47 @@ +/* + * 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.demo.springmvc.filter; + + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.swagger.invocation.Response; +import org.springframework.stereotype.Component; + +@Component +public class ProviderTestFilter extends AbstractFilter implements ProviderFilter { + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 1800; + } + + @Override + public String getName() { + return "test-provider"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + invocation.addContext("k", "v"); + return nextNode.onFilter(invocation); + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/AnnotationsSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/AnnotationsSchema.java new file mode 100644 index 00000000000..45f2c01e4b3 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/AnnotationsSchema.java @@ -0,0 +1,86 @@ +/* + * 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.demo.springmvc.server; + +import org.apache.servicecomb.demo.controller.Person; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.ws.rs.core.MediaType; + +@RestSchema(schemaId = "annotations") +@RequestMapping(path = "/springmvc/annotations", produces = MediaType.APPLICATION_JSON) +public class AnnotationsSchema { + @GetMapping(path = "/add") + public int add(@RequestParam(name = "a", defaultValue = "10") int a, + @RequestParam(name = "b", defaultValue = "10") int b) { + return a + b; + } + + @RequestMapping(path = "/sayhei", method = RequestMethod.GET) + public String sayHei(@RequestHeader(name = "name", defaultValue = "test") String name) { + return "hei " + name; + } + + @GetMapping(path = "/sayhi") + @Parameters({ + @Parameter(name = "name", in = ParameterIn.QUERY, schema = @Schema(type = "string", defaultValue = "test")), + @Parameter(name = "age", in = ParameterIn.QUERY, schema = @Schema(type = "integer", defaultValue = "20")) + }) + public String sayHi(String name, int age) { + return "hi " + name + " your age is : " + age; + } + + @RequestMapping(path = "/saysomething", method = RequestMethod.POST) + public String saySomething(String prefix, @RequestBody(required = false) Person user) { + if (user == null || user.getName() == null || user.getName().isEmpty()) { + return "No user data found"; + } + return prefix + " " + user.getName(); + } + + @RequestMapping(path = "/say", method = RequestMethod.POST) + public String say(@RequestBody(required = false) String user) { + if (user == null || user.isEmpty()) { + return "No user name found"; + } + return user; + } + + @RequestMapping(path = "/testRequiredBody", method = RequestMethod.POST) + public String testRequiredBody(@RequestBody(required = true) Person user) { + if (user == null) { + return "Should not happen"; + } + return user.getName(); + } + + @RequestMapping(path = "/testRegExpPath/{path: .+}", method = RequestMethod.GET) + public String testRegExpPath(@RequestParam("name") String name) { + return name; + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/AnnotationsTest.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/AnnotationsTest.java deleted file mode 100644 index 3af7e0ed3ab..00000000000 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/AnnotationsTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.demo.springmvc.server; - -import javax.ws.rs.core.MediaType; - -import org.apache.servicecomb.demo.controller.Person; -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestHeader; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; - -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiParam; - -@RestSchema(schemaId = "annotations") -@RequestMapping(path = "/springmvc/annotations", produces = MediaType.APPLICATION_JSON) -public class AnnotationsTest { - @GetMapping(path = "/add") - public int add(@RequestParam(name = "a", defaultValue = "10") int a, - @RequestParam(name = "b", defaultValue = "10") int b) { - return a + b; - } - - @RequestMapping(path = "/sayhei", method = RequestMethod.GET) - public String sayHei(@RequestHeader(name = "name", defaultValue = "test") String name) { - return "hei " + name; - } - - @GetMapping(path = "/sayhi") - @ApiImplicitParams({ - @ApiImplicitParam(name = "name", paramType = "query", dataType = "string", defaultValue = "test"), - @ApiImplicitParam(name = "age", paramType = "query", dataType = "integer", defaultValue = "20") - }) - public String sayHi(String name, int age) { - return "hi " + name + " your age is : " + age; - } - - @RequestMapping(path = "/saysomething", method = RequestMethod.POST) - public String saySomething(String prefix, @RequestBody(required = false) @ApiParam(required = false) Person user) { - if (user == null || user.getName() == null || user.getName().isEmpty()) { - return "No user data found"; - } - return prefix + " " + user.getName(); - } - - @RequestMapping(path = "/say", method = RequestMethod.POST) - public String say(@RequestBody(required = false) String user) { - if (user == null || user.isEmpty()) { - return "No user name found"; - } - return user; - } -} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/BigNumberSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/BigNumberSchema.java new file mode 100644 index 00000000000..1190fde43f8 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/BigNumberSchema.java @@ -0,0 +1,45 @@ +/* + * 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.demo.springmvc.server; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestAttribute; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@RestSchema(schemaId = "BigNumberSchema") +@RequestMapping("/bigNumber") +public class BigNumberSchema { + @PostMapping(path = "/integer", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public BigInteger bigInteger(@RequestHeader("intHeader") BigInteger intHeader, + @RequestParam("intQuery") BigInteger intQuery, @RequestAttribute("intForm") BigInteger intForm) { + return intHeader.add(intQuery).add(intForm); + } + + @PostMapping(path = "/decimal", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + public BigDecimal bigDecimal(@RequestHeader("decimalHeader") BigDecimal decimalHeader, + @RequestParam("decimalQuery") BigDecimal decimalQuery, @RequestAttribute("decimalForm") BigDecimal decimalForm) { + return decimalHeader.add(decimalQuery).add(decimalForm); + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java index bbd1b17c29b..36f8518afe4 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/CodeFirstSpringmvc.java @@ -25,15 +25,9 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.Part; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response.Status; - import org.apache.commons.io.IOUtils; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.core.Const; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.demo.EmptyObject; import org.apache.servicecomb.demo.Generic; import org.apache.servicecomb.demo.compute.GenericParam; @@ -42,15 +36,13 @@ import org.apache.servicecomb.demo.compute.Person; import org.apache.servicecomb.demo.ignore.InputModelForTestIgnore; import org.apache.servicecomb.demo.ignore.OutputModelForTestIgnore; -import org.apache.servicecomb.demo.jaxbbean.JAXBPerson; import org.apache.servicecomb.demo.server.User; import org.apache.servicecomb.demo.springmvc.decoderesponse.DecodeTestResponse; import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.metrics.core.MetricsBootListener; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody; -import org.apache.servicecomb.swagger.extend.annotations.ResponseHeaders; +import org.apache.servicecomb.swagger.generator.SwaggerConst; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.swagger.invocation.context.ContextUtils; import org.apache.servicecomb.swagger.invocation.context.InvocationContext; @@ -58,6 +50,7 @@ import org.apache.servicecomb.swagger.invocation.exception.InvocationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -80,20 +73,27 @@ import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.ResponseHeader; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.headers.Header; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.vertx.core.json.JsonObject; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.QueryParam; +import jakarta.ws.rs.core.Response.Status; @RestSchema(schemaId = "codeFirst") @RequestMapping(path = "/codeFirstSpringmvc", produces = MediaType.APPLICATION_JSON_VALUE) public class CodeFirstSpringmvc { private static final Logger LOGGER = LoggerFactory.getLogger(CodeFirstSpringmvc.class); - private AtomicInteger firstInovcation = new AtomicInteger(2); + private AtomicInteger invocationCounter = new AtomicInteger(0); private String _fileUpload(MultipartFile file1, Part file2) { try (InputStream is1 = file1.getInputStream(); InputStream is2 = file2.getInputStream()) { @@ -114,7 +114,7 @@ private String _fileUpload(MultipartFile file1, Part file2) { @GetMapping(path = "/retrySuccess") public int retrySuccess(@RequestParam("a") int a, @RequestParam("b") int b) { - if (firstInovcation.getAndDecrement() > 0) { + if (invocationCounter.getAndIncrement() % 3 != 0) { throw new InvocationException(Status.SERVICE_UNAVAILABLE, "try again later."); } return a + b; @@ -133,21 +133,34 @@ public String fileUpload(@RequestPart(name = "file1") MultipartFile file1, return _fileUpload(file1, file2); } - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Date.class)) + , description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @RequestMapping(path = "/responseEntity", method = RequestMethod.POST) public ResponseEntity responseEntity(InvocationContext c1, @RequestAttribute("date") Date date) { HttpHeaders headers = new HttpHeaders(); - headers.add("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE)); + headers.add("h1", "h1v " + c1.getContext().get(CoreConst.SRC_MICROSERVICE)); InvocationContext c2 = ContextUtils.getInvocationContext(); - headers.add("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE)); + headers.add("h2", "h2v " + c2.getContext().get(CoreConst.SRC_MICROSERVICE)); return new ResponseEntity<>(date, headers, HttpStatus.ACCEPTED); } - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @GetMapping(value = "/getAuthorization", produces = {"application/json"}) + public String getAuthorization( + @RequestHeader(value = "test") String test, + @RequestParam(value = "param") String param, + @Parameter(description = "Authorization header", required = true, in = ParameterIn.HEADER, + name = "Authorization") @RequestHeader("Authorization") String authorization) { + return test + param + authorization; + } + + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = Date.class)) + , description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @RequestMapping(path = "/responseEntity", method = RequestMethod.PATCH) public ResponseEntity responseEntityPATCH(InvocationContext c1, @RequestAttribute("date") Date date) { return responseEntity(c1, date); @@ -155,32 +168,34 @@ public ResponseEntity responseEntityPATCH(InvocationContext c1, @RequestAt // This definition is not correct, response type is not // same as the actual one. May be not support in future. - @ApiResponse(code = 200, response = User.class, message = "") - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = User.class)) + , description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @RequestMapping(path = "/cseResponse", method = RequestMethod.GET) public Response cseResponse(InvocationContext c1) { Response response = Response.createSuccess(Status.ACCEPTED, new User()); - response.addHeader("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE)); + response.addHeader("h1", "h1v " + c1.getContext().get(CoreConst.SRC_MICROSERVICE)); InvocationContext c2 = ContextUtils.getInvocationContext(); - response.addHeader("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE)); + response.addHeader("h2", "h2v " + c2.getContext().get(CoreConst.SRC_MICROSERVICE)); return response; } // This definition is correct, but not supported by highway. // highway do not support define code other than 200 - @ApiResponse(code = 202, response = User.class, message = "") - @ResponseHeaders({@ResponseHeader(name = "h1", response = String.class), - @ResponseHeader(name = "h2", response = String.class)}) + @ApiResponse(responseCode = "202", content = @Content(schema = @Schema(implementation = User.class)) + , description = "", + headers = {@Header(name = "h1", schema = @Schema(implementation = String.class)), + @Header(name = "h2", schema = @Schema(implementation = String.class))}) @RequestMapping(path = "/cseResponseCorrect", method = RequestMethod.GET) public Response cseResponseCorrect(InvocationContext c1) { Response response = Response.createSuccess(Status.ACCEPTED, new User()); - response.addHeader("h1", "h1v " + c1.getContext().get(Const.SRC_MICROSERVICE)); + response.addHeader("h1", "h1v " + c1.getContext().get(CoreConst.SRC_MICROSERVICE)); InvocationContext c2 = ContextUtils.getInvocationContext(); - response.addHeader("h2", "h2v " + c2.getContext().get(Const.SRC_MICROSERVICE)); + response.addHeader("h2", "h2v " + c2.getContext().get(CoreConst.SRC_MICROSERVICE)); return response; } @@ -195,11 +210,6 @@ public String textPlain(@RequestBody String body) { return body; } - @RequestMapping(path = "/appXml", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_XML_VALUE) - public JAXBPerson appXml(@RequestBody JAXBPerson person) { - return person; - } - @RequestMapping(path = "/bytes", method = RequestMethod.POST) public byte[] bytes(@RequestBody byte[] input) { input[0] = (byte) (input[0] + 1); @@ -212,7 +222,7 @@ public Date addDate(@RequestAttribute("date") Date date, @QueryParam("seconds") } // this should be ignored as it's hidden - @ApiOperation(value = "", hidden = true, httpMethod = "POST") + @Operation(summary = "", hidden = true, method = "POST") public int add(@RequestParam("a") int a) { return a; } @@ -223,7 +233,7 @@ public int add(@RequestAttribute("a") int a, @RequestAttribute("b") int b) { } @GetMapping(path = "/reduce") - @ApiImplicitParams({@ApiImplicitParam(name = "a", dataType = "integer", format = "int32", paramType = "query")}) + @Parameters({@Parameter(name = "a", schema = @Schema(implementation = int.class), in = ParameterIn.QUERY)}) public int reduce(HttpServletRequest request, @CookieValue(name = "b") int b) { int a = Integer.parseInt(request.getParameter("a")); return a - b; @@ -240,7 +250,8 @@ public Person sayHello(@RequestBody Person user) { public String testRawJsonString(String jsonInput) { Map person; try { - person = RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), Map.class); + person = RestObjectMapperFactory.getRestObjectMapper() + .readValue(jsonInput.getBytes(StandardCharsets.UTF_8), Map.class); } catch (Exception e) { e.printStackTrace(); return null; @@ -283,18 +294,19 @@ public boolean isTrue() { @DeleteMapping(path = "/addstring", produces = MediaType.TEXT_PLAIN_VALUE) public String addString(@RequestParam(name = "s") List s) { - String result = ""; + StringBuilder result = new StringBuilder(); for (String x : s) { - result += x; + result.append(x); } - return result; + return result.toString(); } // Using 490, 590 error code, the response type should be CommonExceptionData. Or we need - // complex ExceptionConverters to deal with exceptions thrown by Hanlders, etc. + // complex ExceptionConverters to deal with exceptions thrown by Handlers, etc. @RequestMapping(path = "/fallback/returnnull/{name}", method = RequestMethod.GET) - @ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"), - @ApiResponse(code = 490, response = CommonExceptionData.class, message = "xxx")}) + @ApiResponses(value = {@ApiResponse(responseCode = "200", + content = @Content(schema = @Schema(implementation = String.class)), description = "xxx"), + @ApiResponse(responseCode = "490", content = @Content(schema = @Schema(implementation = CommonExceptionData.class)), description = "xxx")}) public String fallbackReturnNull(@PathVariable(name = "name") String name) { if ("throwexception".equals(name)) { throw new InvocationException(490, "490", new CommonExceptionData("xxx")); @@ -303,8 +315,11 @@ public String fallbackReturnNull(@PathVariable(name = "name") String name) { } @RequestMapping(path = "/fallback/throwexception/{name}", method = RequestMethod.GET) - @ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"), - @ApiResponse(code = 490, response = CommonExceptionData.class, message = "xxx")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)) + , description = "xxx"), + @ApiResponse(responseCode = "490", content = @Content(schema = @Schema(implementation = CommonExceptionData.class)) + , description = "xxx")}) public String fallbackThrowException(@PathVariable(name = "name") String name) { if ("throwexception".equals(name)) { throw new InvocationException(490, "490", new CommonExceptionData("xxx")); @@ -313,8 +328,11 @@ public String fallbackThrowException(@PathVariable(name = "name") String name) { } @RequestMapping(path = "/fallback/fromcache/{name}", method = RequestMethod.GET) - @ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"), - @ApiResponse(code = 490, response = CommonExceptionData.class, message = "xxx")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)) + , description = "xxx"), + @ApiResponse(responseCode = "490", content = @Content(schema = @Schema(implementation = CommonExceptionData.class)) + , description = "xxx")}) public String fallbackFromCache(@PathVariable(name = "name") String name) { if ("throwexception".equals(name)) { throw new InvocationException(490, "490", new CommonExceptionData("xxx")); @@ -323,8 +341,11 @@ public String fallbackFromCache(@PathVariable(name = "name") String name) { } @RequestMapping(path = "/fallback/force/{name}", method = RequestMethod.GET) - @ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "xxx"), - @ApiResponse(code = 490, response = CommonExceptionData.class, message = "xxx")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)) + , description = "xxx"), + @ApiResponse(responseCode = "490", content = @Content(schema = @Schema(implementation = CommonExceptionData.class)) + , description = "xxx")}) public String fallbackForce(@PathVariable(name = "name") String name) { if ("throwexception".equals(name)) { throw new InvocationException(490, "490", new CommonExceptionData("xxx")); @@ -338,8 +359,11 @@ public enum NameType { } @RequestMapping(path = "/testenum/{name}", method = RequestMethod.GET) - @ApiResponses(value = {@ApiResponse(code = 200, response = String.class, message = "200 normal"), - @ApiResponse(code = 490, response = CommonExceptionData.class, message = "490 exception")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)) + , description = "xxx"), + @ApiResponse(responseCode = "490", content = @Content(schema = @Schema(implementation = CommonExceptionData.class)) + , description = "xxx")}) public String testEnum(@RequestParam(name = "username") String username, @PathVariable(value = "name") NameType nameType) { return nameType.toString(); @@ -360,7 +384,8 @@ public OutputModelForTestIgnore testModelWithIgnoreField(@RequestBody InputModel public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) { Map person; try { - person = RestObjectMapperFactory.getRestObjectMapper().readValue(jsonInput.getBytes(), Map.class); + person = RestObjectMapperFactory.getRestObjectMapper() + .readValue(jsonInput.getBytes(StandardCharsets.UTF_8), Map.class); } catch (Exception e) { e.printStackTrace(); return null; @@ -369,11 +394,13 @@ public String testRawJsonAnnotation(@RawJsonRequestBody String jsonInput) { } @PostMapping(path = "/testform") - @ApiImplicitParams({ - @ApiImplicitParam(name = "form1", dataType = "string", paramType = "form", value = "a required form param", - required = true), - @ApiImplicitParam(name = "form2", dataType = "string", paramType = "form", value = "an optional form param", - required = false)}) + @io.swagger.v3.oas.annotations.parameters.RequestBody( + content = {@Content(mediaType = SwaggerConst.FORM_MEDIA_TYPE, + schema = @Schema(name = "form1", implementation = String.class, + nullable = false, description = "a required form param")), + @Content(mediaType = SwaggerConst.FORM_MEDIA_TYPE, + schema = @Schema(name = "form2", implementation = String.class, + nullable = true, description = "an optional form param"))}) public String testform(HttpServletRequest request) { String form1 = request.getParameter("form1"); String form2 = request.getParameter("form2"); @@ -381,8 +408,8 @@ public String testform(HttpServletRequest request) { return form1 + form2; } - MetricsBootListener metricsBootListener = SPIServiceUtils - .getTargetService(BootListener.class, MetricsBootListener.class); + @Autowired + MetricsBootListener metricsBootListener; //Only for Prometheus integration test @RequestMapping(path = "/prometheusForTest", method = RequestMethod.GET) @@ -396,7 +423,7 @@ public String prometheusForTest() { @GetMapping(path = "/traceId") public String getTraceId() { - return ContextUtils.getInvocationContext().getContext(Const.TRACE_ID_NAME); + return ContextUtils.getInvocationContext().getContext(CoreConst.TRACE_ID_NAME); } @PostMapping(path = "/emptyObject") @@ -468,7 +495,7 @@ public Generic> testGenericGenericUser(@RequestBody Generic deleteAfterFinished(@RequestParam("content") String content) throws IOException { - File file = createTempFile(content); + public ResponseEntity deleteAfterFinished(@RequestParam("content") String content, + @RequestParam(value = "fileName", required = false) String fileName) throws IOException { + File file; + + if (StringUtils.isNotEmpty(fileName)) { + file = createTempFile(fileName, content); + } else { + file = createTempFile(content); + } return ResponseEntity .ok() @@ -92,8 +99,46 @@ public ResponseEntity notDeleteAfterFinished(@RequestParam("content") Stri .body(new FilePart(null, file)); } + @GetMapping(path = "/setContentTypeByResponseEntity") + public ResponseEntity setContentTypeByResponseEntity(@RequestParam("content") String content, + @RequestParam("contentType") String contentType) throws IOException { + File file = createTempFile(content); + + return ResponseEntity + .ok() + .header(HttpHeaders.CONTENT_TYPE, contentType) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=tempFileEntity.txt") + .body(new FilePart(null, file)); + } + @GetMapping(path = "/assertLastFileDeleted") public boolean assertLastFileDeleted() { return lastFile.exists(); } + + @GetMapping(path = "/testResponseOKExceptionDownload") + public ResponseEntity testResponseOKExceptionDownload( + @RequestParam("exception") boolean exception, + @RequestParam("content") String content, + @RequestParam("contentType") String contentType) throws IOException { + if (exception) { + throw new ResponseOKException(); + } + + File file = createTempFile(content); + + return ResponseEntity + .ok() + .header(HttpHeaders.CONTENT_TYPE, contentType) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=tempFileEntity.txt") + .body(new FilePart(null, file)); + } + + @GetMapping(path = "/testResponseOKExceptionBean") + public boolean testResponseOKExceptionBean(@RequestParam("exception") boolean exception) { + if (exception) { + throw new ResponseOKException(); + } + return true; + } } diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java index e36dcd784c8..ddf56fb5a3f 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java @@ -21,17 +21,16 @@ import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.definition.SchemaMeta; import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.registry.RegistrationManager; +import org.apache.servicecomb.swagger.generator.core.unittest.UnitTestSwaggerUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; -import com.netflix.config.DynamicPropertyFactory; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectWriter; -import io.swagger.models.Swagger; -import io.swagger.util.Yaml; +import io.swagger.v3.core.util.Yaml; +import io.swagger.v3.oas.models.OpenAPI; /** * Testing after bootup. @@ -42,62 +41,22 @@ public class ProducerTestsAfterBootup implements BootListener { private ObjectWriter writer = Yaml.pretty(); - private static final String EXPECTED_DATA = "---\n" - + "swagger: \"2.0\"\n" - + "info:\n" - + " version: \"1.0.0\"\n" - + " title: \"swagger definition for org.apache.servicecomb.demo.springmvc.server.CodeFirstSpringmvcForSchema\"\n" - + " x-java-interface: \"gen.swagger.CodeFirstSpringmvcForSchemaIntf\"\n" - + "basePath: \"/forScheam\"\n" - + "consumes:\n" - + "- \"application/json\"\n" - + "produces:\n" - + "- \"application/json\"\n" - + "paths:\n" - + " /uploadFile:\n" - + " post:\n" - + " operationId: \"uploadAwardFile\"\n" - + " consumes:\n" - + " - \"multipart/form-data\"\n" - + " produces:\n" - + " - \"application/json\"\n" - + " parameters:\n" - + " - name: \"fileType\"\n" - + " in: \"query\"\n" - + " required: true\n" - + " type: \"string\"\n" - + " - name: \"zoneId\"\n" - + " in: \"query\"\n" - + " required: true\n" - + " type: \"string\"\n" - + " - name: \"file\"\n" - + " in: \"formData\"\n" - + " required: true\n" - + " type: \"file\"\n" - + " responses:\n" - + " \"200\":\n" - + " description: \"response of 200\"\n" - + " schema:\n" - + " type: \"boolean\"\n"; - public void testSchemaNotChange(SCBEngine scbEngine) { LOGGER.info("ProducerTestsAfterBootup testing start"); - //we can not set microserviceName any more - SchemaMeta meta = scbEngine.getProducerProviderManager().registerSchema("test1", new CodeFirstSpringmvcForSchema()); + SchemaMeta meta = scbEngine.getProducerMicroserviceMeta().findSchemaMeta("CodeFirstSpringmvcForSchema"); String codeFirst = getSwaggerContent(meta.getSwagger()); - TestMgr.check(EXPECTED_DATA, - codeFirst); - } - public void testRegisteredBasePath() { - if (DynamicPropertyFactory.getInstance().getBooleanProperty("servicecomb.test.vert.transport", true).get()) { - TestMgr.check(19, RegistrationManager.INSTANCE.getMicroservice().getPaths().size()); - } else { - TestMgr.check(20, RegistrationManager.INSTANCE.getMicroservice().getPaths().size()); - } + String expectSchema = UnitTestSwaggerUtils.loadExpect("schemas/CodeFirstSpringmvcForSchema.yaml") + .replace("\r\n", "\n").trim(); + int offset = expectSchema.indexOf("---\nopenapi: 3.0.1"); + if (offset > 0) { + expectSchema = expectSchema.substring(offset + 4); + } + + TestMgr.check(expectSchema.trim(), codeFirst.trim()); } - private String getSwaggerContent(Swagger swagger) { + private String getSwaggerContent(OpenAPI swagger) { try { return writer.writeValueAsString(swagger); } catch (JsonProcessingException e) { @@ -109,7 +68,6 @@ private String getSwaggerContent(Swagger swagger) { public void onBootEvent(BootEvent event) { if (event.getEventType() == BootListener.EventType.AFTER_REGISTRY) { testSchemaNotChange(event.getScbEngine()); - testRegisteredBasePath(); if (!TestMgr.isSuccess()) { TestMgr.summary(); throw new IllegalStateException("some tests are failed. "); @@ -117,4 +75,3 @@ public void onBootEvent(BootEvent event) { } } } - diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKData.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKData.java new file mode 100644 index 00000000000..aeadbbeda90 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKData.java @@ -0,0 +1,44 @@ +/* + * 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.demo.springmvc.server; + +public class ResponseOKData { + private String errorCode; + + private String errorMessage; + + public ResponseOKData(String errorCode, String errorMessage) { + this.errorCode = errorCode; + this.errorMessage = errorMessage; + } + + public String getErrorCode() { + return errorCode; + } + + public void setErrorCode(String errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKException.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKException.java new file mode 100644 index 00000000000..6dcafb2db99 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKException.java @@ -0,0 +1,20 @@ +/* + * 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.demo.springmvc.server; + +public class ResponseOKException extends RuntimeException { +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKExceptionConverter.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKExceptionConverter.java new file mode 100644 index 00000000000..7358b72171c --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ResponseOKExceptionConverter.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.demo.springmvc.server; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.exception.ExceptionConverter; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; + +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.StatusType; + +public class ResponseOKExceptionConverter implements + ExceptionConverter { + + @Override + public boolean canConvert(Throwable throwable) { + return throwable instanceof ResponseOKException; + } + + @Override + public InvocationException convert(Invocation invocation, ResponseOKException throwable, StatusType genericStatus) { + // This is for compatible usage. For best practise, any status code + // should have only one type of response. + return new InvocationException(Status.OK, new ResponseOKData("code-005", "error-005")); + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RestProducersCustomized.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RestProducersCustomized.java new file mode 100644 index 00000000000..a3858541825 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RestProducersCustomized.java @@ -0,0 +1,28 @@ +/* + * 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.demo.springmvc.server; + +import org.apache.servicecomb.provider.rest.common.RestProducers; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +@Component +@Primary +// This example shows user's how to customize RestProducers by @Primary annotation +public class RestProducersCustomized extends RestProducers { +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RestProducersCutomized.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RestProducersCutomized.java deleted file mode 100644 index 445c6a35b07..00000000000 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RestProducersCutomized.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.demo.springmvc.server; - -import org.apache.servicecomb.provider.rest.common.RestProducers; -import org.springframework.context.annotation.Primary; -import org.springframework.stereotype.Component; - -@Component -@Primary -// This example shows user's how to customize RestProducers by @Primary annotation -public class RestProducersCutomized extends RestProducers { -} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RetrySchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RetrySchema.java new file mode 100644 index 00000000000..b3a32b34020 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/RetrySchema.java @@ -0,0 +1,54 @@ +/* + * 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.demo.springmvc.server; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicLong; + +import jakarta.ws.rs.core.Response.Status; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +// test cases for retry +@RestSchema(schemaId = "RetrySchema") +@RequestMapping(path = "/retry", produces = MediaType.APPLICATION_JSON_VALUE) +public class RetrySchema { + private AtomicLong counter = new AtomicLong(0); + + @GetMapping(path = "/governance/successWhenRetry") + public boolean successWhenRetry() { + if (counter.getAndIncrement() % 3 != 0) { + throw new InvocationException(Status.INTERNAL_SERVER_ERROR, "try again later."); + } + return true; + } + + @GetMapping(path = "/governance/successWhenRetryAsync") + public CompletableFuture successWhenRetryAsync() { + CompletableFuture result = new CompletableFuture<>(); + if (counter.getAndIncrement() % 2 == 0) { + result.completeExceptionally(new InvocationException(Status.INTERNAL_SERVER_ERROR, "try again later.")); + } else { + result.complete(true); + } + return result; + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java index 68aba03c6f7..8d4b02e85b5 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvc.java @@ -17,15 +17,22 @@ package org.apache.servicecomb.demo.springmvc.server; -import javax.validation.constraints.Min; -import javax.ws.rs.core.MediaType; - import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.core.MediaType; + @RequestMapping(path = "/springmvc/schemaInterface", produces = MediaType.APPLICATION_JSON) public interface SchemeInterfaceSpringmvc { @GetMapping(path = "/add") - public int add(@Min(1) @RequestParam("a") int a, @Min(1) @RequestParam("b") int b); + int add(@Min(1) @RequestParam("a") int a, @Min(1) @RequestParam("b") int b); + + @GetMapping(path = "/tailingSlash/") + String tailingSlash(HttpServletRequest request, @Min(1) @RequestParam("a") int a, @Min(1) @RequestParam("b") int b); + + @GetMapping(path = "/nonTailingSlash") + String nonTailingSlash(HttpServletRequest request, @Min(1) @RequestParam("a") int a, @Min(1) @RequestParam("b") int b); } diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java index 548e59197c1..828a9fc160d 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SchemeInterfaceSpringmvcImpl.java @@ -17,10 +17,11 @@ package org.apache.servicecomb.demo.springmvc.server; -import javax.validation.constraints.Min; - import org.apache.servicecomb.provider.rest.common.RestSchema; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.constraints.Min; + @RestSchema(schemaId = "SchemeInterfaceSpringmvc", schemaInterface = SchemeInterfaceSpringmvc.class) public class SchemeInterfaceSpringmvcImpl implements SchemeInterfaceSpringmvc { @Override @@ -28,6 +29,26 @@ public int add(@Min(1) int a, @Min(1) int b) { return a + b; } + @Override + public String tailingSlash(HttpServletRequest request, int a, int b) { + StringBuilder sb = new StringBuilder(); + sb.append(request.getRequestURI()).append(";") + .append(request.getRequestURL()).append(";") + .append(request.getPathInfo()).append(";") + .append(a - b); + return sb.toString(); + } + + @Override + public String nonTailingSlash(HttpServletRequest request, int a, int b) { + StringBuilder sb = new StringBuilder(); + sb.append(request.getRequestURI()).append(";") + .append(request.getRequestURL()).append(";") + .append(request.getPathInfo()).append(";") + .append(a - b); + return sb.toString(); + } + public int reduce(int a, int b) { return a - b; } diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java index edd200bd9ce..1bd1abba2e3 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.demo.springmvc.server; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.demo.CommonSchemaInterface; diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMvcDefaultValues.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMvcDefaultValues.java index 3e915096205..a30b9ad84d3 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMvcDefaultValues.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMvcDefaultValues.java @@ -16,9 +16,9 @@ */ package org.apache.servicecomb.demo.springmvc.server; -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; -import javax.ws.rs.core.MediaType; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.ws.rs.core.MediaType; import org.apache.servicecomb.provider.rest.common.RestSchema; import org.springframework.web.bind.annotation.GetMapping; diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringmvcServer.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringmvcServer.java deleted file mode 100644 index 12af40c09c0..00000000000 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringmvcServer.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.demo.springmvc.server; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.Log4jUtils; - -public class SpringmvcServer { - public static void main(String[] args) throws Exception { - Log4jUtils.init(); - BeanUtils.init(); - } -} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/TransportSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/TransportSchema.java new file mode 100644 index 00000000000..158cd806188 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/TransportSchema.java @@ -0,0 +1,42 @@ +/* + * 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.demo.springmvc.server; + +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.annotation.Transport; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.context.InvocationContext; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RestSchema(schemaId = "TransportSchema") +@RequestMapping(path = "/transport") +public class TransportSchema { + @GetMapping(path = "/restTransport") + @Transport(name = CoreConst.RESTFUL) + public boolean restTransport(InvocationContext invocation) { + return CoreConst.RESTFUL.equals(((Invocation) invocation).getTransportName()); + } + + @GetMapping(path = "/highwayTransport") + @Transport(name = CoreConst.HIGHWAY) + public boolean highwayTransport(InvocationContext invocation) { + return CoreConst.HIGHWAY.equals(((Invocation) invocation).getTransportName()); + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java index 110ccd83163..1a3a737d592 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java @@ -19,15 +19,19 @@ import java.io.File; import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.apache.commons.io.IOUtils; import org.apache.servicecomb.demo.TestMgr; 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.RequestAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.multipart.MultipartFile; @@ -48,7 +52,7 @@ public String fileUpload(@RequestPart(name = "files") List files) file.transferTo(tempFile); index++; } - savedFiles.forEach(file -> file.delete()); + savedFiles.forEach(File::delete); return "success"; } catch (IOException e) { return "failed"; @@ -59,4 +63,41 @@ public String fileUpload(@RequestPart(name = "files") List files) public boolean isServerStartUpSuccess() { return TestMgr.isSuccess(); } + + @PostMapping(path = "/fileUploadMultiRpc", produces = MediaType.TEXT_PLAIN_VALUE, + consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public String fileUploadMultiRpc(@RequestPart(name = "files") MultipartFile[] files) { + return "fileUploadMulti success, and fileNum is " + files.length; + } + + @PostMapping(path = "/uploadFileRequestPartAttribute", produces = MediaType.TEXT_PLAIN_VALUE) + public String uploadFileRequestPartAttribute(@RequestPart(name = "file") MultipartFile file, + @RequestPart(name = "attribute") String attribute) throws IOException { + try (InputStream is = file.getInputStream()) { + return attribute + " " + IOUtils.toString(is, StandardCharsets.UTF_8); + } + } + + @PostMapping(path = "/uploadFileRequestPartAttributeList", produces = MediaType.TEXT_PLAIN_VALUE) + public String uploadFileRequestPartAttributeList(@RequestPart(name = "files") List files, + @RequestPart(name = "attributes") List attributes) throws IOException { + StringBuilder result = new StringBuilder(); + for (MultipartFile file : files) { + try (InputStream is = file.getInputStream()) { + result.append(IOUtils.toString(is, StandardCharsets.UTF_8)); + } + } + for (String attribute : attributes) { + result.append(attribute); + } + return result.toString(); + } + + @PostMapping(path = "/uploadFileAndAttribute", produces = MediaType.TEXT_PLAIN_VALUE) + public String uploadFileAndAttribute(@RequestPart(name = "file") MultipartFile file, + @RequestAttribute(name = "attribute") String attribute) throws IOException { + try (InputStream is = file.getInputStream()) { + return attribute + " " + IOUtils.toString(is, StandardCharsets.UTF_8); + } + } } diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/WeakSpringmvc.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/WeakSpringmvc.java index bb75d6a4706..b9d6a119817 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/WeakSpringmvc.java +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/WeakSpringmvc.java @@ -28,31 +28,31 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; @RestSchema(schemaId = "weakSpringmvc") @RequestMapping(path = "/weakSpringmvc", produces = MediaType.APPLICATION_JSON_VALUE) public class WeakSpringmvc { @GetMapping(path = "/diffNames") - @ApiOperation(value = "differentName", nickname = "differentName") + @Operation(summary = "differentName", operationId = "differentName") public int diffNames(@RequestParam("x") int a, @RequestParam("y") int b) { return a * 2 + b; } @GetMapping(path = "/genericParams") - @ApiOperation(value = "genericParams", nickname = "genericParams") + @Operation(summary = "genericParams", operationId = "genericParams") public List> genericParams(@RequestParam("code") int code, @RequestBody List> names) { return names; } @GetMapping(path = "/genericParamsModel") - @ApiOperation(value = "genericParamsModel", nickname = "genericParamsModel") + @Operation(summary = "genericParamsModel", operationId = "genericParamsModel") public GenericsModel genericParamsModel(@RequestParam("code") int code, @RequestBody GenericsModel model) { return model; } @GetMapping(path = "/specialNameModel") - @ApiOperation(value = "specialNameModel", nickname = "specialNameModel") + @Operation(summary = "specialNameModel", operationId = "specialNameModel") public SpecialNameModel specialNameModel(@RequestParam("code") int code, @RequestBody SpecialNameModel model) { return model; } diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/EarlyConsumer.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/EarlyConsumer.java new file mode 100644 index 00000000000..79b89668560 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/EarlyConsumer.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.springmvc.third; + +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * see: https://github.com/apache/servicecomb-java-chassis/issues/2534 + */ +@Component +public class EarlyConsumer implements BootListener { + private static final Logger LOGGER = LoggerFactory.getLogger(EarlyConsumer.class); + + @RpcReference(microserviceName = "third", schemaId = "heartbeat") + private HealthSchema healthSchema; + + private volatile boolean stopped = false; + + public EarlyConsumer() { + new Thread(() -> { + while (!stopped) { + LOGGER.info("calling service"); + try { + healthSchema.heartbeat(); + } catch (Throwable e) { + // ignore error + } + try { + Thread.sleep(500); + } catch (Throwable e) { + // ignore error + } + } + }).start(); + } + + @Override + public void onAfterRegistry(BootEvent event) { + stopped = true; + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/HealthSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/HealthSchema.java new file mode 100644 index 00000000000..eab4a09e89b --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/HealthSchema.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.springmvc.third; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +@RequestMapping("/v1") +public interface HealthSchema { + @GetMapping(value = "/heartbeat") + void heartbeat(); +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/HeartBeatService.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/HeartBeatService.java new file mode 100644 index 00000000000..d01b2103343 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/HeartBeatService.java @@ -0,0 +1,28 @@ +/* + * 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.demo.springmvc.third; + +import org.apache.servicecomb.provider.rest.common.RestSchema; + +@RestSchema(schemaId = "health", schemaInterface = HealthSchema.class) +public class HeartBeatService implements HealthSchema { + @Override + public void heartbeat() { + + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/NormalConsumer.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/NormalConsumer.java new file mode 100644 index 00000000000..b9bd2daa7c6 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/NormalConsumer.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.demo.springmvc.third; + +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * see: https://github.com/apache/servicecomb-java-chassis/issues/2534 + */ +@Component +public class NormalConsumer implements BootListener { + private static final Logger LOGGER = LoggerFactory.getLogger(NormalConsumer.class); + + @RpcReference(microserviceName = "third", schemaId = "heartbeat") + private HealthSchema healthSchema; + + @Override + public void onAfterRegistry(BootListener.BootEvent event) { + try { + LOGGER.info("calling service after register"); + + healthSchema.heartbeat(); + LOGGER.info("heartbeat succ"); + } catch (Throwable e) { + TestMgr.failed("3rd invoke failed", e); + throw e; + } + } + + + @Override + public int getOrder() { + // 比ThirdServiceRegister晚 + return 0; + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/Register.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/Register.java new file mode 100644 index 00000000000..cc9144fe617 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/third/Register.java @@ -0,0 +1,53 @@ +/* + * 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.demo.springmvc.third; + +import java.util.List; + +import org.apache.servicecomb.localregistry.RegistryBean; +import org.apache.servicecomb.localregistry.RegistryBean.Instance; +import org.apache.servicecomb.localregistry.RegistryBean.Instances; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +/** + * see: https://github.com/apache/servicecomb-java-chassis/issues/2534 + */ +@Configuration +public class Register { + @Autowired + Environment environment; + + @Bean + public RegistryBean thirdRegistryBean() { + String endpoint; + if (environment.getProperty("servicecomb.test.vert.transport", boolean.class, true)) { + endpoint = "rest://localhost:8080?sslEnabled=false&urlPrefix=%2Fapi"; + } else { + endpoint = "rest://localhost:8080?sslEnabled=false"; + } + + return new RegistryBean().addSchemaInterface("heartbeat", HealthSchema.class) + .setAppId("springmvctest") + .setServiceName("third") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of(new Instance().setEndpoints(List.of(endpoint))))); + } +} diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter b/demo/demo-springmvc/springmvc-server/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter new file mode 100644 index 00000000000..f25ea28e1c1 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/resources/META-INF/services/org.apache.servicecomb.core.exception.ExceptionConverter @@ -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.servicecomb.demo.springmvc.server.ResponseOKExceptionConverter diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties b/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties deleted file mode 100644 index ff989feda5d..00000000000 --- a/demo/demo-springmvc/springmvc-server/src/main/resources/config/log4j.properties +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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. -# -log4j.logger.org.apache.servicecomb.core.definition.schema.ProducerSchemaFactory=OFF -log4j.logger.org.apache.servicecomb.core.definition.schema.StaticSchemaFactory=OFF diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/log4j2.xml b/demo/demo-springmvc/springmvc-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml index 8696bffba04..c5c10c5b41b 100644 --- a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml +++ b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml @@ -15,45 +15,31 @@ ## limitations under the License. ## --------------------------------------------------------------------------- -APPLICATION_ID: springmvctest +# test not supported configuration +# service_description.initialStatus service_description: - name: springmvc - version: 0.0.3 - paths: - - path: /test1/testpath - property: - checksession: false - - path: /test2/testpath - property: - checksession: true -instance_description: initialStatus: TESTING + servicecomb: service: - registry: - registerPath: true - address: http://127.0.0.1:30100 - client: - timeout: - idle: 60 - watch: 60 - instance: - healthCheck: - interval: 3 - pull: - interval: 10 - watch: true + application: springmvctest + name: springmvc + version: 0.0.3 + + registry: + sc: + address: http://127.0.0.1:9980,http://127.0.0.1:30100 autodiscovery: true - # can download config center from https://cse-bucket.obs.myhwclouds.com/LocalCSE/Local-CSE-1.0.0.zip to test dynamic config - config: - client: - # serverUri: http://127.0.0.1:30113 - refreshMode: 0 - refresh_interval: 5000 - refreshPort: 30114 - fileSource: file1, file2 + healthCheckIntervalInSeconds: 3 + pollIntervalInMillis: 10000 + watch: true + uploads: directory: target + http: + dispatcher: + rest: + pattern: "/api/(.*)" rest: address: 0.0.0.0:8080?sslEnabled=false server: @@ -70,10 +56,7 @@ servicecomb: timeout: 1000 testInvocationTimeoutWithInvocation: timeout: 1000 - handler: - chain: - Provider: - default: bizkeeper-provider, qps-flowcontrol-provider + flowcontrol: strategy: MyStrategy Provider: @@ -90,7 +73,15 @@ servicecomb: region: my-Region availableZone: my-Zone codec.printErrorMessage: true + + # For old testing + loadbalance: + isolation: + errorThresholdPercentage: 20 #########SSL options +# open jdk 8 now TLSv1.3 not available +# ssl.protocols: TLSv1.3 +# ssl.ciphers: TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384 ssl.protocols: TLSv1.2 ssl.authPeer: true ssl.checkCN.host: true @@ -106,4 +97,3 @@ ssl.crl: revoke.crl ssl.sslCustomClass: org.apache.servicecomb.demo.DemoSSLCustom vertx.disableFileCPResolving: false # false: create the .vertx directory, true: do not create - diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/schemas/CodeFirstSpringmvcForSchema.yaml b/demo/demo-springmvc/springmvc-server/src/main/resources/schemas/CodeFirstSpringmvcForSchema.yaml new file mode 100644 index 00000000000..2263730b56a --- /dev/null +++ b/demo/demo-springmvc/springmvc-server/src/main/resources/schemas/CodeFirstSpringmvcForSchema.yaml @@ -0,0 +1,56 @@ +## --------------------------------------------------------------------------- +## Licensed to the Apache Software Foundation (ASF) under one or more +## contributor license agreements. See the NOTICE file distributed with +## this work for additional information regarding copyright ownership. +## The ASF licenses this file to You under the Apache License, Version 2.0 +## (the "License"); you may not use this file except in compliance with +## the License. You may obtain a copy of the License at +## +## http://www.apache.org/licenses/LICENSE-2.0 +## +## Unless required by applicable law or agreed to in writing, software +## distributed under the License is distributed on an "AS IS" BASIS, +## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +## See the License for the specific language governing permissions and +## limitations under the License. +## --------------------------------------------------------------------------- + +--- +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.springmvc.server.CodeFirstSpringmvcForSchema + version: 1.0.0 +servers: +- url: /forSchema +paths: + /uploadFile: + post: + operationId: uploadAwardFile + parameters: + - name: fileType + in: query + required: true + schema: + type: string + - name: zoneId + in: query + required: true + schema: + type: string + requestBody: + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: boolean +components: {} diff --git a/demo/demo-zeroconfig-registry/README.md b/demo/demo-zeroconfig-registry/README.md new file mode 100644 index 00000000000..c2b53cf780c --- /dev/null +++ b/demo/demo-zeroconfig-registry/README.md @@ -0,0 +1,21 @@ +# Introduction + +This demo tests zeroconfig. + +* server + + run in docker + +* client + + run in docker, and find server instances through zeroconfig, find schemas through + schema discovery + +* edge + run in docker, and find server instances through zeroconfig, find schemas through + schema discovery + +* tests + + integration tests run in host machine, find client/edge instances through local, + and schemas from schema discovery. diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/pom.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/pom.xml new file mode 100644 index 00000000000..385bb4950a5 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/pom.xml @@ -0,0 +1,113 @@ + + + + + 4.0.0 + demo-zeroconfig-registry-client + Java Chassis::Demo::ZeroConfig Registry Client + + org.apache.servicecomb.demo + demo-zeroconfig-registry + 3.4.0-SNAPSHOT + + + + org.apache.servicecomb.demo.zeroconfig.client.ClientApplication + + + + jakarta.ws.rs + jakarta.ws.rs-api + + + org.apache.servicecomb + java-chassis-spring-boot-starter-servlet + + + org.apache.servicecomb + registry-zero-config + + + org.apache.servicecomb.demo + demo-schema + + + + + + 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-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientApplication.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientApplication.java similarity index 93% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientApplication.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientApplication.java index 3206cb96d9a..eaea52f6aa8 100644 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientApplication.java +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientApplication.java @@ -17,13 +17,11 @@ package org.apache.servicecomb.demo.zeroconfig.client; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class ClientApplication { public static void main(final String[] args) throws Exception { diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientModel.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientModel.java new file mode 100644 index 00000000000..ed8458a575c --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientModel.java @@ -0,0 +1,31 @@ +/* + * 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.demo.zeroconfig.client; + +import java.util.Date; + +public class ClientModel { + private Date updateDate; + + public Date getUpdateDate() { + return updateDate; + } + + public void setUpdateDate(Date updateDate) { + this.updateDate = updateDate; + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientServerEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientServerEndpoint.java new file mode 100644 index 00000000000..a2eb8f0ecb7 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientServerEndpoint.java @@ -0,0 +1,124 @@ +/* + * 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.demo.zeroconfig.client; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody; +import org.apache.servicecomb.swagger.invocation.context.ContextUtils; +import org.apache.servicecomb.swagger.invocation.context.InvocationContext; +import org.springframework.beans.factory.annotation.Autowired; +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.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import io.vertx.core.json.JsonObject; +import jakarta.ws.rs.core.MediaType; + +@RestSchema(schemaId = "ClientServerEndpoint") +@RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) +public class ClientServerEndpoint { + @RpcReference(microserviceName = "demo-zeroconfig-registry-server", schemaId = "ServerEndpoint") + private IServerEndpoint serverEndpoint; + + @RpcReference(microserviceName = "demo-zeroconfig-registry-server", schemaId = "RpcEndpoint") + private IRpcEndpoint rpcEndpoint; + + private DiscoveryManager discoveryManager; + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } + + @GetMapping(path = "/getName") + public String getName(@RequestParam(name = "name") String name) { + return serverEndpoint.getName(name); + } + + @GetMapping(path = "/getRegisteredMicroservice") + public Set getRegisteredMicroservice() { + boolean result = true; + List microserviceList = discoveryManager + .findServiceInstances("demo-zeroconfig-registry", + "demo-zeroconfig-registry-client"); + if (microserviceList.size() != 2) { // local and zero config both have one instance + result = false; + } + microserviceList = discoveryManager + .findServiceInstances("demo-zeroconfig-registry", + "demo-zeroconfig-registry-server"); + if (microserviceList.size() != 1) { + result = false; + } + + if (result) { + Set names = new HashSet<>(); + names.add("demo-zeroconfig-registry-client"); + names.add("demo-zeroconfig-registry-server"); + return names; + } + + return Collections.emptySet(); + } + + @PostMapping(path = "/jsonObject") + public JsonObject jsonObject(@RequestBody JsonObject jsonObject) { + JsonObject param = new JsonObject(); + param.put("map", jsonObject); + JsonObject message = rpcEndpoint.getJsonObject(param); + JsonObject inner = new JsonObject(); + inner.put("map", message); + return inner; + } + + @PostMapping(path = "/getString") + public String getString(@RawJsonRequestBody String jsonString) { + return jsonString; + } + + @PostMapping(path = "/postModel") + public ClientModel postModel(@RequestBody ClientModel clientModel) { + return clientModel; + } + + @GetMapping(path = "/contextMapper") + public String contextMapper(@RequestHeader("gatewayHeader") String gatewayHeader, + @RequestHeader("clientHeader") String clientHeader, + @RequestParam("gatewayQuery") String gatewayQuery, + @RequestParam("clientQuery") String clientQuery) { + InvocationContext context = ContextUtils.getInvocationContext(); + if (gatewayHeader.equals(context.getContext("context-gateway-header")) && + clientHeader.equals(context.getContext("context-client-header")) && + gatewayQuery.equals(context.getContext("context-gateway-query")) && + clientQuery.equals(context.getContext("context-client-query"))) { + return "success"; + } + return "fail"; + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/GovernanceEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/GovernanceEndpoint.java new file mode 100644 index 00000000000..574e0a4f605 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/GovernanceEndpoint.java @@ -0,0 +1,83 @@ +/* + * 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.demo.zeroconfig.client; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.client.RestOperations; + +import jakarta.ws.rs.core.Response.Status; + +@RestSchema(schemaId = "GovernanceEndpoint") +@RequestMapping("/governance") +public class GovernanceEndpoint { + private static final String SERVER = "servicecomb://demo-zeroconfig-registry-server"; + + private RestOperations restTemplate = RestTemplateBuilder.create(); + + private int count = 0; + + @GetMapping("/hello") + public String hello() { + return restTemplate.getForObject(SERVER + "/governance/hello", String.class); + } + + @GetMapping("/helloRpc") + public String helloRpc() { + return restTemplate.getForObject(SERVER + "/governance/hello", String.class); + } + + @GetMapping("/noPrefixRetry") + public String noPrefixRetry(@RequestParam(name = "invocationID") String invocationID) { + return restTemplate + .getForObject(SERVER + "/noPrefixRetry?invocationID={1}", String.class, + invocationID); + } + + @GetMapping("/retry") + public String retry(@RequestParam(name = "invocationID") String invocationID) { + return restTemplate + .getForObject(SERVER + "/governance/retry?invocationID={1}", String.class, + invocationID); + } + + @GetMapping("/retryRpc") + public String retryRpc(@RequestParam(name = "invocationID") String invocationID) { + return restTemplate + .getForObject(SERVER + "/governance/retryRpc?invocationID={1}", String.class, + invocationID); + } + + @GetMapping("/circuitBreaker") + public String circuitBreaker() throws Exception { + count++; + if (count % 3 == 0) { + return "ok"; + } + throw new InvocationException(Status.SERVICE_UNAVAILABLE, "test error"); + } + + @GetMapping("/bulkhead") + public String bulkhead() { + return restTemplate.getForObject(SERVER + "/governance/hello", String.class); + } +} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IRpcEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IRpcEndpoint.java similarity index 100% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IRpcEndpoint.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IRpcEndpoint.java diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IServerEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IServerEndpoint.java similarity index 100% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IServerEndpoint.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/IServerEndpoint.java diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/resources/application.yml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/resources/application.yml new file mode 100644 index 00000000000..af6c2946515 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/resources/application.yml @@ -0,0 +1,109 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +server: + port: 8082 + +servicecomb: + service: + application: demo-zeroconfig-registry + name: demo-zeroconfig-registry-client + version: 0.0.2 + rest: + address: 0.0.0.0:8082 + highway: + address: 0.0.0.0:8084 + config: + client: + # for testing dynamic configuration + # serverUri: http://127.0.0.1:30113 + refreshMode: 0 + # refresh_interval: 5000 + # refreshPort: 30114 + governance: + GovernanceEndpoint.helloRpc: + matchType: rpc + demo-zeroconfig-registry-server.GovernanceEndpoint.retryRpc: + matchType: rpc + matchGroup: + demo-rateLimiting: | + matches: + - apiPath: + exact: "/governance/hello" + demo-rateLimiting-rpc: | + matches: + - apiPath: + exact: "GovernanceEndpoint.helloRpc" + demo-retry: | + matches: + - apiPath: + exact: "/governance/retry" + demo-retry-no-prefix: | + matches: + - apiPath: + exact: "/noPrefixRetry" + demo-retry-rpc: | + matches: + - apiPath: + exact: "demo-zeroconfig-registry-server.GovernanceEndpoint.retryRpc" + demo-circuitBreaker: | + matches: + - apiPath: + exact: "/governance/circuitBreaker" + demo-bulkhead: | + matches: + - apiPath: + exact: "/governance/bulkhead" + rateLimiting: + demo-rateLimiting: | + rate: 10 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + demo-rateLimiting-rpc: | + rate: 10 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + retry: + demo-retry: | + maxAttempts: 3 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + demo-retry-no-prefix: | + maxAttempts: 3 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + demo-retry-rpc: | + maxAttempts: 3 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + circuitBreaker: + demo-circuitBreaker: | + minimumNumberOfCalls: 10 + slidingWindowSize: 10 + failureRateThreshold: 20 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + bulkhead: + demo-bulkhead: | + maxConcurrentCalls: 5 + ## services is optional in configuration file + services: demo-zeroconfig-registry-client + context: + headerContextMapper: | + clientHeader: context-client-header + queryContextMapper: | + clientQuery: context-client-query diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/resources/log4j2.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-client/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/pom.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/pom.xml new file mode 100644 index 00000000000..c8dcb06893a --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/pom.xml @@ -0,0 +1,118 @@ + + + + + 4.0.0 + demo-zeroconfig-registry-edge + Java Chassis::Demo::ZeroConfig Registry Edge + + org.apache.servicecomb.demo + demo-zeroconfig-registry + 3.4.0-SNAPSHOT + + + + org.apache.servicecomb.demo.zeroconfig.edge.EdgeApplication + + + + jakarta.ws.rs + jakarta.ws.rs-api + + + org.apache.servicecomb + edge-core + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + registry-zero-config + + + org.apache.servicecomb.demo + demo-schema + + + + + + + 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-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/EdgeApplication.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/EdgeApplication.java similarity index 95% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/EdgeApplication.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/EdgeApplication.java index 91685d0cddf..6ba5795c2a8 100644 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/EdgeApplication.java +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/EdgeApplication.java @@ -21,13 +21,11 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication -@EnableServiceComb public class EdgeApplication { public static void main(final String[] args) throws Exception { new SpringApplicationBuilder().sources(EdgeApplication.class).web(WebApplicationType.NONE).build().run(args); diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/SelfServiceInvoker.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/SelfServiceInvoker.java new file mode 100644 index 00000000000..e04576d2965 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/SelfServiceInvoker.java @@ -0,0 +1,42 @@ +/* + * 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.demo.zeroconfig.edge; + +import java.util.concurrent.CountDownLatch; +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component("SelfServiceInvoker") +public class SelfServiceInvoker implements BootListener { + interface IServerEndpoint { + String getName(String name); + } + + @RpcReference(microserviceName = "demo-zeroconfig-registry-edge", schemaId = "ServerEndpoint") + IServerEndpoint endpoint; + + public CountDownLatch latch = new CountDownLatch(1); + + public String result = ""; + + public void onAfterRegistry(BootEvent event) { + result = endpoint.getName("hello"); + latch.countDown(); + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/ServerEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/ServerEndpoint.java new file mode 100644 index 00000000000..71f259366ae --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/ServerEndpoint.java @@ -0,0 +1,37 @@ +/* + * 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.demo.zeroconfig.edge; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.context.ContextUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import jakarta.ws.rs.core.MediaType; + +@RestSchema(schemaId = "ServerEndpoint") +@RequestMapping(path = "/edge/prefix", produces = MediaType.APPLICATION_JSON) +public class ServerEndpoint { + @GetMapping(path = "/getName") + public String getName(@RequestParam(name = "name") String name) { + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); + return name; + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/resources/application.yml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/resources/application.yml new file mode 100644 index 00000000000..14cda29c28d --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/resources/application.yml @@ -0,0 +1,53 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +server: + port: 8888 + +servicecomb: + service: + application: demo-zeroconfig-registry + name: demo-zeroconfig-registry-edge + version: 0.0.2 + rest: + address: 0.0.0.0:8888 + filter-chains: + enabled: true + + http: + dispatcher: + edge: + default: + enabled: false + url: + enabled: true + pattern: /(.*) + mappings: + client: + prefixSegmentCount: 0 + path: "/register/url/prefix/.*" + microserviceName: demo-zeroconfig-registry-client + versionRule: 0+ + references: + transport: + demo-zeroconfig-registry-client.ClientServerEndpoint.contextMapper: rest + + context: + headerContextMapper: | + gatewayHeader: context-gateway-header + queryContextMapper: | + gatewayQuery: context-gateway-query diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/resources/log4j2.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-edge/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/pom.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/pom.xml new file mode 100644 index 00000000000..f69f1118a0a --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/pom.xml @@ -0,0 +1,118 @@ + + + + + 4.0.0 + demo-zeroconfig-registry-server + Java Chassis::Demo::ZeroConfig Registry Server + + org.apache.servicecomb.demo + demo-zeroconfig-registry + 3.4.0-SNAPSHOT + + + + org.apache.servicecomb.demo.zeroconfig.server.ServerApplication + + + + jakarta.ws.rs + jakarta.ws.rs-api + + + org.apache.servicecomb + java-chassis-spring-boot-starter-servlet + + + org.apache.servicecomb + registry-zero-config + + + org.apache.servicecomb.demo + demo-schema + + + + + + + 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 + + + org.commonjava.maven.plugins + directory-maven-plugin + + + + + + diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceEndpoint.java new file mode 100644 index 00000000000..454e3cbba36 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceEndpoint.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.demo.zeroconfig.server; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.ws.rs.core.Response.Status; + +@RestSchema(schemaId = "GovernanceEndpoint") +@RequestMapping("/governance") +public class GovernanceEndpoint { + private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceEndpoint.class); + + private Map retryTimes = new HashMap<>(); + + @GetMapping("/hello") + public String sayHello() { + return "Hello world!"; + } + + @GetMapping("/retry") + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)), description = ""), + @ApiResponse(responseCode = "502", content = @Content(schema = @Schema(implementation = String.class)), description = "")}) + public String retry(@RequestParam(name = "invocationID") String invocationID) { + LOGGER.info("invoke service: {}", invocationID); + retryTimes.putIfAbsent(invocationID, 0); + retryTimes.put(invocationID, retryTimes.get(invocationID) + 1); + + int retry = retryTimes.get(invocationID); + + if (retry == 3) { + return "try times: " + retry; + } + throw new InvocationException(502, "retry", "retry"); + } + + @GetMapping("/retryRpc") + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)), description = ""), + @ApiResponse(responseCode = "502", content = @Content(schema = @Schema(implementation = String.class)), description = "")}) + public String retryRpc(@RequestParam(name = "invocationID") String invocationID) { + return retry(invocationID); + } + + @GetMapping("/circuitBreaker") + public String circuitBreaker() { + throw new InvocationException(Status.SERVICE_UNAVAILABLE, ""); + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceNoPrefixEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceNoPrefixEndpoint.java new file mode 100644 index 00000000000..0c5121cac33 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceNoPrefixEndpoint.java @@ -0,0 +1,59 @@ +/* + * 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.demo.zeroconfig.server; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; + +@RestSchema(schemaId = "GovernanceNoPrefixEndpoint") +@RequestMapping("/") +public class GovernanceNoPrefixEndpoint { + private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceNoPrefixEndpoint.class); + + private Map retryTimes = new HashMap<>(); + + @GetMapping("/noPrefixRetry") + @ApiResponses({ + @ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = String.class)), description = ""), + @ApiResponse(responseCode = "502", content = @Content(schema = @Schema(implementation = String.class)), description = "")}) + public String noPrefixRetry(@RequestParam(name = "invocationID") String invocationID) { + LOGGER.info("invoke service: {}", invocationID); + retryTimes.putIfAbsent(invocationID, 0); + retryTimes.put(invocationID, retryTimes.get(invocationID) + 1); + + int retry = retryTimes.get(invocationID); + + if (retry == 3) { + return "try times: " + retry; + } + throw new InvocationException(502, "retry", "retry"); + } +} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/RpcEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/RpcEndpoint.java similarity index 100% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/RpcEndpoint.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/RpcEndpoint.java diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/SelfServiceInvoker.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/SelfServiceInvoker.java new file mode 100644 index 00000000000..1f8c6c800c8 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/SelfServiceInvoker.java @@ -0,0 +1,42 @@ +/* + * 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.demo.zeroconfig.server; + +import java.util.concurrent.CountDownLatch; +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.provider.pojo.RpcReference; +import org.springframework.stereotype.Component; + +@Component("SelfServiceInvoker") +public class SelfServiceInvoker implements BootListener { + interface IServerEndpoint { + String getName(String name); + } + + @RpcReference(microserviceName = "demo-zeroconfig-registry-server", schemaId = "ServerEndpoint") + IServerEndpoint endpoint; + + public CountDownLatch latch = new CountDownLatch(1); + + public String result = ""; + + public void onAfterRegistry(BootEvent event) { + result = endpoint.getName("hello"); + latch.countDown(); + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerApplication.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerApplication.java new file mode 100644 index 00000000000..a04249fd63a --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerApplication.java @@ -0,0 +1,42 @@ +/* + * 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.demo.zeroconfig.server; + +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class ServerApplication { + public static void main(final String[] args) throws Exception { + new SpringApplicationBuilder().sources(ServerApplication.class).web(WebApplicationType.SERVLET).build().run(args); + + SelfServiceInvoker invoker = BeanUtils.getBean("SelfServiceInvoker"); + invoker.latch.await(10, TimeUnit.SECONDS); + TestMgr.check(invoker.result, "hello"); + + TestMgr.summary(); + if (!TestMgr.errors().isEmpty()) { + System.exit(1); + } + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerEndpoint.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerEndpoint.java new file mode 100644 index 00000000000..b0dd4ef5d97 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerEndpoint.java @@ -0,0 +1,37 @@ +/* + * 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.demo.zeroconfig.server; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.provider.rest.common.RestSchema; +import org.apache.servicecomb.swagger.invocation.context.ContextUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +import jakarta.ws.rs.core.MediaType; + +@RestSchema(schemaId = "ServerEndpoint") +@RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) +public class ServerEndpoint { + @GetMapping(path = "/getName") + public String getName(@RequestParam(name = "name") String name) { + ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info("get name invoked."); + return name; + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/resources/application.yml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/resources/application.yml new file mode 100644 index 00000000000..52863ee0bd7 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/resources/application.yml @@ -0,0 +1,30 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +server: + port: 8080 + +servicecomb: + service: + application: demo-zeroconfig-registry + name: demo-zeroconfig-registry-server + version: 0.0.2 + + rest: + address: 0.0.0.0:8080 + filter-chains: + enabled: true diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/resources/log4j2.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..ea906df4019 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-server/src/main/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/pom.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/pom.xml new file mode 100644 index 00000000000..8c57041ea1d --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/pom.xml @@ -0,0 +1,158 @@ + + + + + 4.0.0 + demo-zeroconfig-registry-tests + Java Chassis::Demo::ZeroConfig Registry Tests + + org.apache.servicecomb.demo + demo-zeroconfig-registry + 3.4.0-SNAPSHOT + + + + org.apache.servicecomb.demo.zeroconfig.tests.Application + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-servlet + + + org.apache.servicecomb + registry-local + + + org.apache.servicecomb.demo + demo-schema + + + + + + docker + + + + + io.fabric8 + docker-maven-plugin + + + + demo-zeroconfig-registry-server:${project.version} + demo-zeroconfig-registry-server + + + /maven/maven/demo-zeroconfig-registry-server-${project.version}.jar + + + + Service information is shown below + + + 8080 + + + + + + 8080:8080 + + + + + + demo-zeroconfig-registry-client:${project.version} + demo-zeroconfig-registry-client + + + /maven/maven/demo-zeroconfig-registry-client-${project.version}.jar + + + + Service information is shown below + + + 8082 + + + + + + 8082:8082 + + + + + + demo-zeroconfig-registry-edge:${project.version} + demo-zeroconfig-registry-edge + + + /maven/maven/demo-zeroconfig-registry-edge-${project.version}.jar + + + + Service information is shown below + + + 8888 + + + + + + 8888:8888 + + + + + + + + start + pre-integration-test + + start + + + + stop + post-integration-test + + stop + + + + + + + + + io.fabric8 + docker-maven-plugin + + + + + + diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/Application.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/Application.java new file mode 100644 index 00000000000..3b98119d918 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/Application.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.demo.zeroconfig.tests; + +import org.apache.servicecomb.demo.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class Application { + private static final Logger LOGGER = LoggerFactory.getLogger(Application.class); + + public static void main(final String[] args) throws Exception { + new SpringApplicationBuilder().sources(Application.class).web(WebApplicationType.NONE) + .build().run(args); + + runTest(); + + TestMgr.summary(); + + LOGGER.info("-------------- last time updated checks(maybe more/less): 662 -------------"); + + if (!TestMgr.errors().isEmpty()) { + throw new IllegalStateException("tests failed"); + } + } + + private static void runTest() throws Exception { + CategorizedTestCaseRunner + .runCategorizedTestCase("demo-zeroconfig-registry-server"); + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ClientModel.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ClientModel.java new file mode 100644 index 00000000000..b664eef319d --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ClientModel.java @@ -0,0 +1,31 @@ +/* + * 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.demo.zeroconfig.tests; + +import java.util.Date; + +public class ClientModel { + private Date updateDate; + + public Date getUpdateDate() { + return updateDate; + } + + public void setUpdateDate(Date updateDate) { + this.updateDate = updateDate; + } +} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/GovernanceTest.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/GovernanceTest.java similarity index 91% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/GovernanceTest.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/GovernanceTest.java index dfb4bbaa720..24899c822c6 100644 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/GovernanceTest.java +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/GovernanceTest.java @@ -26,13 +26,13 @@ import org.apache.servicecomb.demo.TestMgr; import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; +import org.springframework.web.client.RestOperations; @Component public class GovernanceTest implements CategorizedTestCase { - String url = "servicecomb://demo-zeroconfig-schemadiscovery-registry-client/governance"; + String url = "servicecomb://demo-zeroconfig-registry-client/governance"; - RestTemplate template = RestTemplateBuilder.create(); + RestOperations template = RestTemplateBuilder.create(); @Override public void testRestTransport() throws Exception { @@ -41,9 +41,14 @@ public void testRestTransport() throws Exception { testRateLimitingRest(); testRateLimitingRpc(); testRetryRest(); + testRetryRestNoPrefix(); testRetryRpc(); } + private void testRetryRestNoPrefix() { + testRetry("/noPrefixRetry"); + } + private void testRetryRest() { testRetry("/retry"); } @@ -74,15 +79,14 @@ public void run() { notExpectedFailed.set(true); } } catch (Exception e) { - if (!"InvocationException: code=429;msg=CommonExceptionData [message=circuitBreaker is open.]" - .equals(e.getMessage()) - && !e.getMessage().equals( - "InvocationException: code=500;msg={message=Unexpected exception when processing the request.}")) { - notExpectedFailed.set(true); - } if ("InvocationException: code=429;msg=CommonExceptionData [message=circuitBreaker is open.]" .equals(e.getMessage())) { expectedFailed.set(true); + } else if ("InvocationException: code=503;msg=CommonExceptionData [message=test error]" + .equals(e.getMessage())) { + // by pass + } else { + notExpectedFailed.set(true); } } latch.countDown(); diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ServerTest.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ServerTest.java new file mode 100644 index 00000000000..767f43ff74b --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ServerTest.java @@ -0,0 +1,164 @@ +/* + * 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.demo.zeroconfig.tests; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Date; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CountDownLatch; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestOperations; + +import io.vertx.core.json.JsonObject; + +@Component +public class ServerTest implements CategorizedTestCase { + + RestOperations template = RestTemplateBuilder.create(); + + @Override + public void testRestTransport() throws Exception { + testServerGetName(); + testGetAllMicroservice(); + testJsonObject(); + testString(); + testDateForEdge(); + testContextMapper(); + } + + private void testContextMapper() throws URISyntaxException { + MultiValueMap headers = new HttpHeaders(); + headers.add("clientHeader", "v1"); + headers.add("gatewayHeader", "v2"); + RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, + new URI("cse://demo-zeroconfig-registry-edge/register/url/prefix/contextMapper?clientQuery=v3&" + + "gatewayQuery=v4")); + // test two times to check different transport(only use rest) + ResponseEntity response = template.exchange(requestEntity, String.class); + TestMgr.check(response.getBody(), "success"); + response = template.exchange(requestEntity, String.class); + TestMgr.check(response.getBody(), "success"); + } + + @SuppressWarnings("unchecked") + private void testDateForEdge() { + for (int i = 0; i < 3; i++) { + ClientModel clientModelReq = new ClientModel(); + Date date = new Date(1663590135202L); + clientModelReq.setUpdateDate(date); + Map response = template + .postForObject( + "cse://demo-zeroconfig-registry-edge" + + "/register/url/prefix/postModel", clientModelReq, + Map.class); + Object result = response.get("updateDate"); + // TODO: highway and rest Date field will give different result + // we can not change this now, because it is incompatible + if (result instanceof Long) { + TestMgr.check(response.get("updateDate"), 1663590135202L); + } else { + TestMgr.check(response.get("updateDate"), "2022-09-19T12:22:15.202+00:00"); + } + } + } + + private void testServerGetName() throws Exception { + // invoke demo-zeroconfig-registry-client + TestMgr.check("world", template + .getForObject( + "cse://demo-zeroconfig-registry-client/register/url/prefix/getName?name=world", + String.class)); + // invoke demo-zeroconfig-registry-edge + // create many threads to test event-loop not blocking + int thread = 32; + CountDownLatch latch = new CountDownLatch(thread); + for (int i = 0; i < thread; i++) { + new Thread(() -> { + for (int j = 0; j < 20; j++) { + try { + TestMgr.check("world", template + .getForObject( + "cse://demo-zeroconfig-registry-edge/register/url/prefix/getName?name=world", + String.class)); + } catch (Exception e) { + TestMgr.failed("test failed", e); + } + } + latch.countDown(); + }).start(); + } + + latch.await(); + } + + @SuppressWarnings("rawTypes") + private void testGetAllMicroservice() { + // invoke demo-zeroconfig-registry-client + TestMgr.check("2", template + .exchange( + "cse://demo-zeroconfig-registry-client" + + "/register/url/prefix/getRegisteredMicroservice", HttpMethod.GET, null, + new ParameterizedTypeReference>() { + + }).getBody().size()); + // invoke demo-zeroconfig-registry-edge + TestMgr.check("2", template + .exchange( + "cse://demo-zeroconfig-registry-edge" + + "/register/url/prefix/getRegisteredMicroservice", HttpMethod.GET, null, + new ParameterizedTypeReference>() { + + }).getBody().size()); + } + + private void testJsonObject() { + JsonObject in = new JsonObject(); + JsonObject inner = new JsonObject(); + //调用者需要按照swagger传参 + inner.put("hello", "world"); + in.put("map", inner); + + JsonObject result = template + .postForObject( + "cse://demo-zeroconfig-registry-client" + + "/register/url/prefix/jsonObject", in, JsonObject.class); + TestMgr.check(inner.toString(), result.toString()); + TestMgr.check(result.getString("hello"), "world"); + } + + private void testString() { + String in = "{\"hello\":\"world\"}"; + String result = template + .postForObject( + "cse://demo-zeroconfig-registry-client" + + "/register/url/prefix/getString", in, String.class); + TestMgr.check(in, result); + } +} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/application.yml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/application.yml new file mode 100644 index 00000000000..f9f987e88ef --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/application.yml @@ -0,0 +1,30 @@ +## --------------------------------------------------------------------------- +## 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-zeroconfig-registry + name: demo-zeroconfig-registry-tests + version: 0.0.2 + handler: + chain: + Consumer: + default: loadbalance + loadbalance: + filter: + isolation: + enabled: false diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/logback.xml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/logback.xml new file mode 100644 index 00000000000..cc214e46e64 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/logback.xml @@ -0,0 +1,29 @@ + + + + + + + %d [%level] [%thread] - %msg (%F:%L\)%n + + + + + + + diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/ClientServerEndpoint.yaml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/ClientServerEndpoint.yaml new file mode 100644 index 00000000000..d8e19afb43c --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/ClientServerEndpoint.yaml @@ -0,0 +1,155 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.zeroconfig.client.ClientServerEndpoint + version: 1.0.0 +servers: +- url: /register/url/prefix +paths: + /contextMapper: + get: + operationId: contextMapper + parameters: + - name: gatewayHeader + in: header + required: true + schema: + type: string + - name: clientHeader + in: header + required: true + schema: + type: string + - name: gatewayQuery + in: query + required: true + schema: + type: string + - name: clientQuery + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /getName: + get: + operationId: getName + parameters: + - name: name + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /getRegisteredMicroservice: + get: + operationId: getRegisteredMicroservice + responses: + "200": + description: response of 200 + content: + application/json: + schema: + uniqueItems: true + type: array + items: + type: string + /getString: + post: + operationId: getString + requestBody: + content: + application/json: + schema: + type: string + required: true + x-raw-json: true + x-name: jsonString + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /jsonObject: + post: + operationId: jsonObject + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/JsonObject' + required: true + x-name: jsonObject + responses: + "200": + description: response of 200 + content: + application/json: + schema: + $ref: '#/components/schemas/JsonObject' + /postModel: + post: + operationId: postModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientModel' + required: true + x-name: clientModel + responses: + "200": + description: response of 200 + content: + application/json: + schema: + $ref: '#/components/schemas/ClientModel' +components: + schemas: + JsonObject: + type: object + properties: + map: + type: object + additionalProperties: + type: object + empty: + type: boolean + x-java-class: io.vertx.core.json.JsonObject + ClientModel: + type: object + properties: + updateDate: + type: string + format: date-time + x-java-class: org.apache.servicecomb.demo.zeroconfig.client.ClientModel diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/GovernanceEndpoint.yaml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/GovernanceEndpoint.yaml new file mode 100644 index 00000000000..6dfbd0d36c8 --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/GovernanceEndpoint.yaml @@ -0,0 +1,114 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.zeroconfig.client.GovernanceEndpoint + version: 1.0.0 +servers: +- url: /governance +paths: + /bulkhead: + get: + operationId: bulkhead + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /circuitBreaker: + get: + operationId: circuitBreaker + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /hello: + get: + operationId: hello + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /helloRpc: + get: + operationId: helloRpc + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /noPrefixRetry: + get: + operationId: noPrefixRetry + parameters: + - name: invocationID + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /retry: + get: + operationId: retry + parameters: + - name: invocationID + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /retryRpc: + get: + operationId: retryRpc + parameters: + - name: invocationID + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string +components: + schemas: {} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/SchemaDiscoveryEndpoint.yaml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/SchemaDiscoveryEndpoint.yaml new file mode 100644 index 00000000000..8a34262bfbe --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-client/SchemaDiscoveryEndpoint.yaml @@ -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. +## --------------------------------------------------------------------------- + +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.schemadiscovery.SchemaDiscoveryEndpoint + version: 1.0.0 +servers: +- url: /v1/schema/discovery +paths: + /getSchema: + get: + operationId: getSchema + parameters: + - name: schemaId + in: query + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string +components: + schemas: {} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-edge/ClientServerEndpoint.yaml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-edge/ClientServerEndpoint.yaml new file mode 100644 index 00000000000..d8e19afb43c --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-edge/ClientServerEndpoint.yaml @@ -0,0 +1,155 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.demo.zeroconfig.client.ClientServerEndpoint + version: 1.0.0 +servers: +- url: /register/url/prefix +paths: + /contextMapper: + get: + operationId: contextMapper + parameters: + - name: gatewayHeader + in: header + required: true + schema: + type: string + - name: clientHeader + in: header + required: true + schema: + type: string + - name: gatewayQuery + in: query + required: true + schema: + type: string + - name: clientQuery + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /getName: + get: + operationId: getName + parameters: + - name: name + in: query + required: true + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /getRegisteredMicroservice: + get: + operationId: getRegisteredMicroservice + responses: + "200": + description: response of 200 + content: + application/json: + schema: + uniqueItems: true + type: array + items: + type: string + /getString: + post: + operationId: getString + requestBody: + content: + application/json: + schema: + type: string + required: true + x-raw-json: true + x-name: jsonString + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string + /jsonObject: + post: + operationId: jsonObject + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/JsonObject' + required: true + x-name: jsonObject + responses: + "200": + description: response of 200 + content: + application/json: + schema: + $ref: '#/components/schemas/JsonObject' + /postModel: + post: + operationId: postModel + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/ClientModel' + required: true + x-name: clientModel + responses: + "200": + description: response of 200 + content: + application/json: + schema: + $ref: '#/components/schemas/ClientModel' +components: + schemas: + JsonObject: + type: object + properties: + map: + type: object + additionalProperties: + type: object + empty: + type: boolean + x-java-class: io.vertx.core.json.JsonObject + ClientModel: + type: object + properties: + updateDate: + type: string + format: date-time + x-java-class: org.apache.servicecomb.demo.zeroconfig.client.ClientModel diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-edge/SchemaDiscoveryEndpoint.yaml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-edge/SchemaDiscoveryEndpoint.yaml new file mode 100644 index 00000000000..8a34262bfbe --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/microservices/demo-zeroconfig-registry-edge/SchemaDiscoveryEndpoint.yaml @@ -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. +## --------------------------------------------------------------------------- + +openapi: 3.0.1 +info: + title: swagger definition for org.apache.servicecomb.schemadiscovery.SchemaDiscoveryEndpoint + version: 1.0.0 +servers: +- url: /v1/schema/discovery +paths: + /getSchema: + get: + operationId: getSchema + parameters: + - name: schemaId + in: query + schema: + type: string + responses: + "200": + description: response of 200 + content: + application/json: + schema: + type: string +components: + schemas: {} diff --git a/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/registry.yaml b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/registry.yaml new file mode 100644 index 00000000000..07360eabfde --- /dev/null +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/main/resources/registry.yaml @@ -0,0 +1,38 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- + +demo-zeroconfig-registry-client: + - id: "001" + version: "0.0.2" + appid: demo-zeroconfig-registry + schemaIds: + - ClientServerEndpoint + - SchemaDiscoveryEndpoint + - GovernanceEndpoint + instances: + - endpoints: + - rest://localhost:8082 +demo-zeroconfig-registry-edge: + - id: "002" + version: "0.0.2" + appid: demo-zeroconfig-registry + schemaIds: + - ClientServerEndpoint + - SchemaDiscoveryEndpoint + instances: + - endpoints: + - rest://localhost:8888 diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/test/java/org/apache/servicecomb/demo/zeroconfig/tests/ZeroConfigRegistryIT.java b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/test/java/org/apache/servicecomb/demo/zeroconfig/tests/ZeroConfigRegistryIT.java similarity index 81% rename from demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/test/java/org/apache/servicecomb/demo/zeroconfig/tests/ZeroConfigRegistryIT.java rename to demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/test/java/org/apache/servicecomb/demo/zeroconfig/tests/ZeroConfigRegistryIT.java index 7c569caa35c..cd531243e6e 100644 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/test/java/org/apache/servicecomb/demo/zeroconfig/tests/ZeroConfigRegistryIT.java +++ b/demo/demo-zeroconfig-registry/demo-zeroconfig-registry-tests/src/test/java/org/apache/servicecomb/demo/zeroconfig/tests/ZeroConfigRegistryIT.java @@ -18,16 +18,13 @@ package org.apache.servicecomb.demo.zeroconfig.tests; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; - import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.demo.zeroconfig.tests.Application; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class ZeroConfigRegistryIT { - @Before + @BeforeEach public void setUp() throws Exception { TestMgr.errors().clear(); } @@ -36,6 +33,6 @@ public void setUp() throws Exception { public void clientGetsNoError() throws Exception { Application.main(new String[0]); - assertThat(TestMgr.errors().isEmpty(), is(true)); + Assertions.assertTrue(TestMgr.errors().isEmpty()); } } diff --git a/demo/demo-zeroconfig-registry/pom.xml b/demo/demo-zeroconfig-registry/pom.xml new file mode 100644 index 00000000000..bc02525e483 --- /dev/null +++ b/demo/demo-zeroconfig-registry/pom.xml @@ -0,0 +1,60 @@ + + + + + 4.0.0 + + org.apache.servicecomb.demo + demo-parent + 3.4.0-SNAPSHOT + + demo-zeroconfig-registry + Java Chassis::Demo::ZeroConfig Registry + pom + + demo-zeroconfig-registry-server + demo-zeroconfig-registry-edge + demo-zeroconfig-registry-client + demo-zeroconfig-registry-tests + + + + + org.apache.servicecomb + solution-basic + + + org.apache.servicecomb + foundation-test-scaffolding + compile + + + org.apache.logging.log4j + log4j-slf4j-impl + + + org.apache.logging.log4j + log4j-api + + + org.apache.logging.log4j + log4j-core + + + diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/README.md b/demo/demo-zeroconfig-schemadiscovery-registry/README.md deleted file mode 100644 index 44cd5539ce9..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Introduction - -This demo tests zeroconfig. - -* server - - run in docker - -* client - - run in docker, and find server instances through zeroconfig, find schemas through - schema discovery - -* edge - run in docker, and find server instances through zeroconfig, find schemas through - schema discovery - -* tests - - integration tests run in host machine, find client/edge instances through local, - and schemas from schema discovery. \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/pom.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/pom.xml deleted file mode 100644 index ab7aec3a81e..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/pom.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - 4.0.0 - demo-zeroconfig-schemadiscovery-registry-client - Java Chassis::Demo::ZeroConfig-SchemaDiscovery Registry Client - - org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry - 2.6.0-SNAPSHOT - - - - org.apache.servicecomb.demo.zeroconfig.client.ClientApplication - - - - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - - - org.apache.servicecomb - handler-governance - - - org.apache.servicecomb - registry-schema-discovery - - - org.apache.servicecomb - registry-zero-config - - - org.apache.servicecomb.demo - demo-schema - - - org.apache.servicecomb - config-cc - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - - - - - - - docker - - - - io.fabric8 - docker-maven-plugin - - - org.commonjava.maven.plugins - directory-maven-plugin - - - - - - diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientServerEndpoint.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientServerEndpoint.java deleted file mode 100644 index f2fb7328545..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/ClientServerEndpoint.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.demo.zeroconfig.client; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import javax.ws.rs.core.MediaType; - -import org.apache.servicecomb.provider.pojo.RpcReference; -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.swagger.extend.annotations.RawJsonRequestBody; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -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 io.vertx.core.json.JsonObject; - -@RestSchema(schemaId = "ClientServerEndpoint") -@RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) -public class ClientServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ClientServerEndpoint.class); - - @RpcReference(microserviceName = "demo-zeroconfig-schemadiscovery-registry-server", schemaId = "ServerEndpoint") - private IServerEndpoint serverEndpoint; - - @RpcReference(microserviceName = "demo-zeroconfig-schemadiscovery-registry-server", schemaId = "RpcEndpoint") - private IRpcEndpoint rpcEndpoint; - - @GetMapping(path = "/getName") - public String getName(@RequestParam(name = "name") String name) { - return serverEndpoint.getName(name); - } - - @GetMapping(path = "/getRegisteredMicroservice") - public Set getRegisteredMicroservice() { - List microserviceList = DiscoveryManager.INSTANCE.getAllMicroservices(); - Set names = new HashSet<>(); - - for (Microservice m : microserviceList) { - if (m.getServiceName().equals("demo-zeroconfig-schemadiscovery-registry-client") - || m.getServiceName().equals("demo-zeroconfig-schemadiscovery-registry-server")) { - names.add(m.getServiceName()); - } - } - return names; - } - - @PostMapping(path = "/jsonObject") - public JsonObject jsonObject(@RequestBody JsonObject jsonObject) { - JsonObject param = new JsonObject(); - param.put("map", jsonObject); - JsonObject message = rpcEndpoint.getJsonObject(param); - JsonObject inner = new JsonObject(); - inner.put("map", message); - return inner; - } - - @PostMapping(path = "/getString") - public String getString(@RawJsonRequestBody String jsonString) { - return jsonString; - } -} \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/GovernanceEndpoint.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/GovernanceEndpoint.java deleted file mode 100644 index 8c77c7c3068..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/java/org/apache/servicecomb/demo/zeroconfig/client/GovernanceEndpoint.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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.demo.zeroconfig.client; - -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.client.RestTemplate; - -@RestSchema(schemaId = "GovernanceEndpoint") -@RequestMapping("/governance") -public class GovernanceEndpoint { - private static final String SERVER = "servicecomb://demo-zeroconfig-schemadiscovery-registry-server"; - - private RestTemplate restTemplate = RestTemplateBuilder.create(); - - private int count = 0; - - @GetMapping("/hello") - public String hello() { - return restTemplate.getForObject(SERVER + "/governance/hello", String.class); - } - - @GetMapping("/helloRpc") - public String helloRpc() { - return restTemplate.getForObject(SERVER + "/governance/hello", String.class); - } - - @GetMapping("/retry") - public String retry(@RequestParam(name = "invocationID") String invocationID) { - return restTemplate - .getForObject(SERVER + "/governance/retry?invocationID={1}", String.class, - invocationID); - } - - @GetMapping("/retryRpc") - public String retryRpc(@RequestParam(name = "invocationID") String invocationID) { - return restTemplate - .getForObject(SERVER + "/governance/retryRpc?invocationID={1}", String.class, - invocationID); - } - - @GetMapping("/circuitBreaker") - public String circuitBreaker() throws Exception { - count++; - if (count % 3 == 0) { - return "ok"; - } - throw new RuntimeException("test error"); - } - - @GetMapping("/bulkhead") - public String bulkhead() { - return restTemplate.getForObject(SERVER + "/governance/hello", String.class); - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/resources/application.yml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/resources/application.yml deleted file mode 100644 index 1eb345f4322..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/resources/application.yml +++ /dev/null @@ -1,103 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -server: - port: 8082 - -# java-chassis configurations - -APPLICATION_ID: demo-zeroconfig-schemadiscovery-registry -service_description: - name: demo-zeroconfig-schemadiscovery-registry-client - version: 0.0.2 -servicecomb: - rest: - address: 0.0.0.0:8082 - config: - client: - # for testing dynamic configuration - # serverUri: http://127.0.0.1:30113 - refreshMode: 0 - # refresh_interval: 5000 - # refreshPort: 30114 - handler: - chain: - Consumer: - default: governance-consumer,loadbalance - Provider: - default: governance-provider - - governance: - GovernanceEndpoint.helloRpc: - matchType: rpc - demo-zeroconfig-schemadiscovery-registry-server.GovernanceEndpoint.retryRpc: - matchType: rpc - matchGroup: - demo-rateLimiting: | - matches: - - apiPath: - exact: "/governance/hello" - demo-rateLimiting-rpc: | - matches: - - apiPath: - exact: "GovernanceEndpoint.helloRpc" - demo-retry: | - matches: - - apiPath: - exact: "/governance/retry" - demo-retry-rpc: | - matches: - - apiPath: - exact: "demo-zeroconfig-schemadiscovery-registry-server.GovernanceEndpoint.retryRpc" - demo-circuitBreaker: | - matches: - - apiPath: - exact: "/governance/circuitBreaker" - demo-bulkhead: | - matches: - - apiPath: - exact: "/governance/bulkhead" - rateLimiting: - demo-rateLimiting: | - rate: 10 - ## services is optional in configuration file - services: demo-zeroconfig-schemadiscovery-registry-client - demo-rateLimiting-rpc: | - rate: 10 - ## services is optional in configuration file - services: demo-zeroconfig-schemadiscovery-registry-client - retry: - demo-retry: | - maxAttempts: 3 - ## services is optional in configuration file - services: demo-zeroconfig-schemadiscovery-registry-client - demo-retry-rpc: | - maxAttempts: 3 - ## services is optional in configuration file - services: demo-zeroconfig-schemadiscovery-registry-client - circuitBreaker: - demo-circuitBreaker: | - minimumNumberOfCalls: 10 - slidingWindowSize: 10 - failureRateThreshold: 20 - ## services is optional in configuration file - services: demo-zeroconfig-schemadiscovery-registry-client - bulkhead: - demo-bulkhead: | - maxConcurrentCalls: 5 - ## services is optional in configuration file - services: demo-zeroconfig-schemadiscovery-registry-client \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/resources/logback.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-client/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/pom.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/pom.xml deleted file mode 100644 index e9b1b518601..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - 4.0.0 - demo-zeroconfig-schemadiscovery-registry-edge - Java Chassis::Demo::ZeroConfig-SchemaDiscovery Registry Edge - - org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry - 2.6.0-SNAPSHOT - - - - org.apache.servicecomb.demo.zeroconfig.edge.EdgeApplication - - - - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - edge-core - - - org.apache.servicecomb - java-chassis-spring-boot-starter-standalone - - - org.apache.servicecomb - registry-schema-discovery - - - org.apache.servicecomb - registry-zero-config - - - org.apache.servicecomb.demo - demo-schema - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - - - - - - - docker - - - - io.fabric8 - docker-maven-plugin - - - org.commonjava.maven.plugins - directory-maven-plugin - - - - - - \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/SelfServiceInvoker.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/SelfServiceInvoker.java deleted file mode 100644 index e6535240ac3..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/SelfServiceInvoker.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.demo.zeroconfig.edge; - -import java.util.concurrent.CountDownLatch; -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.provider.pojo.RpcReference; -import org.springframework.stereotype.Component; - -@Component("SelfServiceInvoker") -public class SelfServiceInvoker implements BootListener { - interface IServerEndpoint { - String getName(String name); - } - - @RpcReference(microserviceName = "demo-zeroconfig-schemadiscovery-registry-edge", schemaId = "ServerEndpoint") - IServerEndpoint endpoint; - - public CountDownLatch latch = new CountDownLatch(1); - - public String result = ""; - - public void onAfterRegistry(BootEvent event) { - result = endpoint.getName("hello"); - latch.countDown(); - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/ServerEndpoint.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/ServerEndpoint.java deleted file mode 100644 index 24e25ed3ae3..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/java/org/apache/servicecomb/demo/zeroconfig/edge/ServerEndpoint.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.demo.zeroconfig.edge; - -import javax.ws.rs.core.MediaType; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; - -@RestSchema(schemaId = "ServerEndpoint") -@RequestMapping(path = "/edge/prefix", produces = MediaType.APPLICATION_JSON) -public class ServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ServerEndpoint.class); - - @GetMapping(path = "/getName") - public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); - return name; - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/resources/application.yml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/resources/application.yml deleted file mode 100644 index 50627018927..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/resources/application.yml +++ /dev/null @@ -1,47 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -server: - port: 8888 - -# java-chassis configurations - -APPLICATION_ID: demo-zeroconfig-schemadiscovery-registry -service_description: - name: demo-zeroconfig-schemadiscovery-registry-edge - version: 0.0.2 -servicecomb: - rest: - address: 0.0.0.0:8888 - handler: - chain: - Consumer: - default: loadbalance - http: - dispatcher: - edge: - default: - enabled: false - url: - enabled: true - pattern: /(.*) - mappings: - client: - prefixSegmentCount: 0 - path: "/register/url/prefix/.*" - microserviceName: demo-zeroconfig-schemadiscovery-registry-client - versionRule: 0+ diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/resources/logback.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-edge/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/pom.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/pom.xml deleted file mode 100644 index 878494abe5b..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - 4.0.0 - demo-zeroconfig-schemadiscovery-registry-server - Java Chassis::Demo::ZeroConfig-SchemaDiscovery Registry Server - - org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry - 2.6.0-SNAPSHOT - - - - org.apache.servicecomb.demo.zeroconfig.server.ServerApplication - - - - javax.ws.rs - javax.ws.rs-api - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - - - org.apache.servicecomb - handler-governance - - - org.apache.servicecomb - registry-schema-discovery - - - org.apache.servicecomb - registry-zero-config - - - org.apache.servicecomb.demo - demo-schema - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - com.github.odavid.maven.plugins - mixin-maven-plugin - - - - org.apache.servicecomb.demo - docker-build-config - ${project.version} - - - - - - - - - - docker - - - - io.fabric8 - docker-maven-plugin - - - org.commonjava.maven.plugins - directory-maven-plugin - - - - - - \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceEndpoint.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceEndpoint.java deleted file mode 100644 index 4e7e15fba4e..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/GovernanceEndpoint.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.demo.zeroconfig.server; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; - -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; - -@RestSchema(schemaId = "GovernanceEndpoint") -@RequestMapping("/governance") -public class GovernanceEndpoint { - private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceEndpoint.class); - - private Map retryTimes = new HashMap<>(); - - @GetMapping("/hello") - public String sayHello() { - return "Hello world!"; - } - - @GetMapping("/retry") - @ApiResponses({ - @ApiResponse(code = 200, response = String.class, message = ""), - @ApiResponse(code = 502, response = String.class, message = "")}) - public String retry(@RequestParam(name = "invocationID") String invocationID) { - LOGGER.info("invoke service: {}", invocationID); - retryTimes.putIfAbsent(invocationID, 0); - retryTimes.put(invocationID, retryTimes.get(invocationID) + 1); - - int retry = retryTimes.get(invocationID); - - if (retry == 3) { - return "try times: " + retry; - } - throw new InvocationException(502, "retry", "retry"); - } - - @GetMapping("/retryRpc") - @ApiResponses({ - @ApiResponse(code = 200, response = String.class, message = ""), - @ApiResponse(code = 502, response = String.class, message = "")}) - public String retryRpc(@RequestParam(name = "invocationID") String invocationID) { - return retry(invocationID); - } - - @GetMapping("/circuitBreaker") - public String circuitBreaker() { - throw new RuntimeException("circuitBreaker by provider."); - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/SelfServiceInvoker.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/SelfServiceInvoker.java deleted file mode 100644 index 0a52776fc8e..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/SelfServiceInvoker.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.demo.zeroconfig.server; - -import java.util.concurrent.CountDownLatch; -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.provider.pojo.RpcReference; -import org.springframework.stereotype.Component; - -@Component("SelfServiceInvoker") -public class SelfServiceInvoker implements BootListener { - interface IServerEndpoint { - String getName(String name); - } - - @RpcReference(microserviceName = "demo-zeroconfig-schemadiscovery-registry-server", schemaId = "ServerEndpoint") - IServerEndpoint endpoint; - - public CountDownLatch latch = new CountDownLatch(1); - - public String result = ""; - - public void onAfterRegistry(BootEvent event) { - result = endpoint.getName("hello"); - latch.countDown(); - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerApplication.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerApplication.java deleted file mode 100644 index 27e708b63e5..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerApplication.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.demo.zeroconfig.server; - -import java.util.concurrent.TimeUnit; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class ServerApplication { - public static void main(final String[] args) throws Exception { - new SpringApplicationBuilder().sources(ServerApplication.class).web(WebApplicationType.SERVLET).build().run(args); - - SelfServiceInvoker invoker = BeanUtils.getBean("SelfServiceInvoker"); - invoker.latch.await(10, TimeUnit.SECONDS); - TestMgr.check(invoker.result, "hello"); - - TestMgr.summary(); - if (!TestMgr.errors().isEmpty()) { - System.exit(1); - } - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerEndpoint.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerEndpoint.java deleted file mode 100644 index d010caa1e28..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/java/org/apache/servicecomb/demo/zeroconfig/server/ServerEndpoint.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.demo.zeroconfig.server; - -import javax.ws.rs.core.MediaType; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.provider.rest.common.RestSchema; -import org.apache.servicecomb.swagger.invocation.context.ContextUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; - -@RestSchema(schemaId = "ServerEndpoint") -@RequestMapping(path = "/register/url/prefix", produces = MediaType.APPLICATION_JSON) -public class ServerEndpoint { - private static final Logger LOGGER - = LoggerFactory.getLogger(ServerEndpoint.class); - - @GetMapping(path = "/getName") - public String getName(@RequestParam(name = "name") String name) { - ((Invocation) ContextUtils.getInvocationContext()).getTraceIdLogger().info(LOGGER, "get name invoked."); - return name; - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/resources/application.yml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/resources/application.yml deleted file mode 100644 index 7d4118f2997..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/resources/application.yml +++ /dev/null @@ -1,38 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -server: - port: 8080 - -# java-chassis configurations - -APPLICATION_ID: demo-zeroconfig-schemadiscovery-registry -service_description: - name: demo-zeroconfig-schemadiscovery-registry-server - version: 0.0.2 -servicecomb: - service: - zero-config: - mode: multicast - rest: - address: 0.0.0.0:8080 - handler: - chain: - Consumer: - default: governance-consumer,loadbalance - Provider: - default: governance-provider \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/resources/logback.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-server/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/pom.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/pom.xml deleted file mode 100644 index 6f231e8d5c4..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/pom.xml +++ /dev/null @@ -1,195 +0,0 @@ - - - - - 4.0.0 - demo-zeroconfig-schemadiscovery-registry-tests - Java Chassis::Demo::ZeroConfig-SchemaDiscovery Registry Tests - - org.apache.servicecomb.demo - demo-zeroconfig-schemadiscovery-registry - 2.6.0-SNAPSHOT - - - - org.apache.servicecomb.demo.zeroconfig.tests.Application - - - - org.apache.servicecomb - java-chassis-spring-boot-starter-servlet - - - org.apache.servicecomb - registry-schema-discovery - - - org.apache.servicecomb.demo - demo-schema - - - - - - docker - - - - - io.fabric8 - docker-maven-plugin - - - - demo-zeroconfig-schemadiscovery-registry-server:${project.version} - demo-zeroconfig-schemadiscovery-registry-server - - - /maven/maven/demo-zeroconfig-schemadiscovery-registry-server-${project.version}.jar - - - - Service information is shown below - - - 8080 - - - - - - 8080:8080 - - - - - - demo-zeroconfig-schemadiscovery-registry-client:${project.version} - demo-zeroconfig-schemadiscovery-registry-client - - - /maven/maven/demo-zeroconfig-schemadiscovery-registry-client-${project.version}.jar - - - - Service information is shown below - - - 8082 - - - - - - 8082:8082 - - - - - - demo-zeroconfig-schemadiscovery-registry-edge:${project.version} - demo-zeroconfig-schemadiscovery-registry-edge - - - /maven/maven/demo-zeroconfig-schemadiscovery-registry-edge-${project.version}.jar - - - - Service information is shown below - - - 8888 - - - - - - 8888:8888 - - - - - - - - start - pre-integration-test - - start - - - - stop - post-integration-test - - stop - - - - - - - - - io.fabric8 - docker-maven-plugin - - - org.codehaus.gmaven - gmaven-plugin - - - add-default-properties - initialize - - execute - - - - project.properties.setProperty('docker.hostname', 'localhost') - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.19.1 - - ${jacoco.failsafe.argLine} - - - - - integration-test - verify - - - - - - - - - - - diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/Application.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/Application.java deleted file mode 100644 index 1341ab2e266..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/Application.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.demo.zeroconfig.tests; - -import org.apache.servicecomb.demo.CategorizedTestCaseRunner; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.springboot2.starter.EnableServiceComb; -import org.springframework.boot.WebApplicationType; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; - -@SpringBootApplication -@EnableServiceComb -public class Application { - - public static void main(final String[] args) throws Exception { - new SpringApplicationBuilder().sources(Application.class).web(WebApplicationType.NONE) - .build().run(args); - - runTest(); - - TestMgr.summary(); - if (!TestMgr.errors().isEmpty()) { - throw new IllegalStateException("tests failed"); - } - } - - private static void runTest() throws Exception { - CategorizedTestCaseRunner - .runCategorizedTestCase("demo-zeroconfig-schemadiscovery-registry-server"); - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ServerTest.java b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ServerTest.java deleted file mode 100644 index 21585d8f28f..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/java/org/apache/servicecomb/demo/zeroconfig/tests/ServerTest.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.demo.zeroconfig.tests; - -import java.util.List; -import java.util.concurrent.CountDownLatch; - -import org.apache.servicecomb.demo.CategorizedTestCase; -import org.apache.servicecomb.demo.TestMgr; -import org.apache.servicecomb.provider.springmvc.reference.RestTemplateBuilder; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -import io.vertx.core.json.JsonObject; - -@Component -public class ServerTest implements CategorizedTestCase { - - RestTemplate template = RestTemplateBuilder.create(); - - @Override - public void testRestTransport() throws Exception { - testServerGetName(); - testGetAllMicroservice(); - testJsonObject(); - testString(); - } - - private void testServerGetName() throws Exception { - // invoke demo-zeroconfig-schemadiscovery-registry-client - TestMgr.check("world", template - .getForObject( - "cse://demo-zeroconfig-schemadiscovery-registry-client/register/url/prefix/getName?name=world", - String.class)); - // invoke demo-zeroconfig-schemadiscovery-registry-edge - // create many threads to test event-loop not blocking - int thread = 32; - CountDownLatch latch = new CountDownLatch(thread); - for (int i = 0; i < thread; i++) { - new Thread(() -> { - for (int j = 0; j < 20; j++) { - try { - TestMgr.check("world", template - .getForObject( - "cse://demo-zeroconfig-schemadiscovery-registry-edge/register/url/prefix/getName?name=world", - String.class)); - } catch (Exception e) { - TestMgr.failed("test failed", e); - } - } - latch.countDown(); - }).start(); - } - - latch.await(); - } - - @SuppressWarnings("rawTypes") - private void testGetAllMicroservice() { - // invoke demo-zeroconfig-schemadiscovery-registry-client - TestMgr.check("2", template - .getForObject( - "cse://demo-zeroconfig-schemadiscovery-registry-client" - + "/register/url/prefix/getRegisteredMicroservice", - List.class).size()); - // invoke demo-zeroconfig-schemadiscovery-registry-edge - TestMgr.check("2", template - .getForObject( - "cse://demo-zeroconfig-schemadiscovery-registry-edge" - + "/register/url/prefix/getRegisteredMicroservice", - List.class).size()); - } - - private void testJsonObject() { - JsonObject in = new JsonObject(); - JsonObject inner = new JsonObject(); - //调用者需要按照swagger传参 - inner.put("hello", "world"); - in.put("map", inner); - - JsonObject result = template - .postForObject( - "cse://demo-zeroconfig-schemadiscovery-registry-client" - + "/register/url/prefix/jsonObject", in, JsonObject.class); - TestMgr.check(inner.toString(), result.toString()); - TestMgr.check(result.getString("hello"), "world"); - } - - private void testString() { - String in = "{\"hello\":\"world\"}"; - String result = template - .postForObject( - "cse://demo-zeroconfig-schemadiscovery-registry-client" - + "/register/url/prefix/getString", in, String.class); - TestMgr.check(in, result); - } -} diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/application.yml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/application.yml deleted file mode 100644 index e139ef0e9c8..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/application.yml +++ /dev/null @@ -1,31 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -# java-chassis configurations - -APPLICATION_ID: demo-zeroconfig-schemadiscovery-registry -service_description: - name: demo-zeroconfig-schemadiscovery-registry-tests - version: 0.0.2 -servicecomb: - handler: - chain: - Consumer: - default: loadbalance - loadbalance: - isolation: - enabled: false \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/logback.xml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/logback.xml deleted file mode 100644 index 0d627f2a24d..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/logback.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - SERVICECOMB_MARKER - DENY - ACCEPT - - - - %d [%level] [%thread][%X{SERVICECOMB_TRACE_ID}] - %msg (%F:%L\)%n - - - - - - - SERVICECOMB_MARKER - ACCEPT - DENY - - - - %d [%level] [%thread] - %msg (%F:%L\)%n - - - - - - - - \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/microservices/demo-zeroconfig-schemadiscovery-registry-edge/ClientServerEndpoint.yaml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/microservices/demo-zeroconfig-schemadiscovery-registry-edge/ClientServerEndpoint.yaml deleted file mode 100644 index 3243bbd8dba..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/microservices/demo-zeroconfig-schemadiscovery-registry-edge/ClientServerEndpoint.yaml +++ /dev/null @@ -1,55 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -swagger: "2.0" -info: - version: "1.0.0" - title: "swagger definition for org.apache.servicecomb.demo.zeroconfig.client.ClientServerEndpoint" - x-java-interface: "gen.swagger.ClientServerEndpointIntf" -basePath: "/register/url/prefix" -schemes: - - "http" -consumes: - - "application/json" -produces: - - "application/json" -paths: - /getName: - get: - operationId: "getName" - parameters: - - name: "name" - in: "query" - required: true - type: "string" - responses: - "200": - description: "response of 200" - schema: - type: "string" - /getRegisteredMicroservice: - get: - operationId: "getRegisteredMicroservice" - parameters: [] - responses: - "200": - description: "response of 200" - schema: - type: "array" - items: - type: "string" - uniqueItems: true \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/registry.yaml b/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/registry.yaml deleted file mode 100644 index cdd8fc782fa..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/demo-zeroconfig-schemadiscovery-registry-tests/src/main/resources/registry.yaml +++ /dev/null @@ -1,38 +0,0 @@ -## --------------------------------------------------------------------------- -## 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. -## --------------------------------------------------------------------------- - -demo-zeroconfig-schemadiscovery-registry-client: - - id: "001" - version: "0.0.2" - appid: demo-zeroconfig-schemadiscovery-registry - schemaIds: - - ClientServerEndpoint - - SchemaDiscoveryEndpoint - - GovernanceEndpoint - instances: - - endpoints: - - rest://localhost:8082 -demo-zeroconfig-schemadiscovery-registry-edge: - - id: "002" - version: "0.0.2" - appid: demo-zeroconfig-schemadiscovery-registry - schemaIds: - - ClientServerEndpoint - - SchemaDiscoveryEndpoint - instances: - - endpoints: - - rest://localhost:8888 \ No newline at end of file diff --git a/demo/demo-zeroconfig-schemadiscovery-registry/pom.xml b/demo/demo-zeroconfig-schemadiscovery-registry/pom.xml deleted file mode 100644 index 07135e788a3..00000000000 --- a/demo/demo-zeroconfig-schemadiscovery-registry/pom.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - 4.0.0 - - org.apache.servicecomb.demo - demo-parent - 2.6.0-SNAPSHOT - - demo-zeroconfig-schemadiscovery-registry - Java Chassis::Demo::ZeroConfig-SchemaDiscovery Registry - pom - - demo-zeroconfig-schemadiscovery-registry-server - demo-zeroconfig-schemadiscovery-registry-edge - demo-zeroconfig-schemadiscovery-registry-client - demo-zeroconfig-schemadiscovery-registry-tests - - - - - org.apache.servicecomb - foundation-test-scaffolding - compile - - - \ No newline at end of file diff --git a/demo/demo-zookeeper/README.md b/demo/demo-zookeeper/README.md new file mode 100644 index 00000000000..48a74913f83 --- /dev/null +++ b/demo/demo-zookeeper/README.md @@ -0,0 +1,5 @@ +# Notice + +This integration tests is designed for Zookeeper 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-zookeeper/consumer/pom.xml b/demo/demo-zookeeper/consumer/pom.xml new file mode 100644 index 00000000000..73fb82a25a3 --- /dev/null +++ b/demo/demo-zookeeper/consumer/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-zookeeper + 3.4.0-SNAPSHOT + + + zookeeper-consumer + Java Chassis::Demo::Zookeeper::CONSUMER + jar + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + registry-zookeeper + + + + + + + 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-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java new file mode 100644 index 00000000000..76fb2fb17db --- /dev/null +++ b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ClientWebsocketController.java @@ -0,0 +1,54 @@ +/* + * 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 -> { + System.out.println("send message " + m); + serverWebsocket.writeTextMessage(m); + }); + serverWebsocket.textMessageHandler(m -> { + System.out.println("receive message " + m); + providerWebSocket.writeTextMessage(m); + }); + } +} diff --git a/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.java new file mode 100644 index 00000000000..3e7a2a0e285 --- /dev/null +++ b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerApplication.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 ConsumerApplication { + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ConsumerApplication.class).run(args); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java new file mode 100644 index 00000000000..e5dd86d9d64 --- /dev/null +++ b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerController.java @@ -0,0 +1,42 @@ +/* + * 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.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@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); + } +} diff --git a/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerHeaderParamWithListSchema.java new file mode 100644 index 00000000000..f0e894d6745 --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ConsumerReactiveStreamController.java new file mode 100644 index 00000000000..aa169801cf7 --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java new file mode 100644 index 00000000000..fe71314c9f4 --- /dev/null +++ b/demo/demo-zookeeper/consumer/src/main/java/org/apache/servicecomb/samples/ProviderService.java @@ -0,0 +1,24 @@ +/* + * 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); +} diff --git a/demo/demo-zookeeper/consumer/src/main/resources/application.yml b/demo/demo-zookeeper/consumer/src/main/resources/application.yml new file mode 100644 index 00000000000..100797f83b4 --- /dev/null +++ b/demo/demo-zookeeper/consumer/src/main/resources/application.yml @@ -0,0 +1,36 @@ +# +## --------------------------------------------------------------------------- +## 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-zookeeper + version: 0.0.1 + name: consumer + properties: + group: red + registry: + zk: + enabled: true + connectString: 127.0.0.1:2181 + + rest: + address: 0.0.0.0:9092?websocketEnabled=true + server: + websocket-prefix: /ws + + highway: + address: 0.0.0.0:7092 diff --git a/demo/demo-zookeeper/consumer/src/main/resources/log4j2.xml b/demo/demo-zookeeper/consumer/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-zookeeper/consumer/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-zookeeper/gateway/pom.xml b/demo/demo-zookeeper/gateway/pom.xml new file mode 100644 index 00000000000..f2676b1ed6d --- /dev/null +++ b/demo/demo-zookeeper/gateway/pom.xml @@ -0,0 +1,107 @@ + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-zookeeper + 3.4.0-SNAPSHOT + + + zookeeper-gateway + Java Chassis::Demo::Zookeeper::GATEWAY + jar + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + edge-core + + + org.apache.servicecomb + registry-zookeeper + + + + + + 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-zookeeper/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java b/demo/demo-zookeeper/gateway/src/main/java/org/apache/servicecomb/samples/GatewayApplication.java new file mode 100644 index 00000000000..7d58caafd9d --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/gateway/src/main/resources/application.yml b/demo/demo-zookeeper/gateway/src/main/resources/application.yml new file mode 100644 index 00000000000..ea13ef73d91 --- /dev/null +++ b/demo/demo-zookeeper/gateway/src/main/resources/application.yml @@ -0,0 +1,53 @@ +# +## --------------------------------------------------------------------------- +## 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-zookeeper + version: 0.0.1 + name: gateway + registry: + zk: + enabled: true + connectString: 127.0.0.1:2181 + + 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-zookeeper/gateway/src/main/resources/log4j2.xml b/demo/demo-zookeeper/gateway/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-zookeeper/gateway/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-zookeeper/pom.xml b/demo/demo-zookeeper/pom.xml new file mode 100644 index 00000000000..aa1030de1ec --- /dev/null +++ b/demo/demo-zookeeper/pom.xml @@ -0,0 +1,61 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-parent + 3.4.0-SNAPSHOT + + demo-zookeeper + Java Chassis::Demo::Zookeeper + 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-zookeeper/provider/pom.xml b/demo/demo-zookeeper/provider/pom.xml new file mode 100644 index 00000000000..3b008bfb000 --- /dev/null +++ b/demo/demo-zookeeper/provider/pom.xml @@ -0,0 +1,116 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-zookeeper + 3.4.0-SNAPSHOT + + + zookeeper-provider + Java Chassis::Demo::Zookeeper::PROVIDER + jar + + + + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb + registry-zookeeper + + + org.apache.servicecomb + config-zookeeper + + + 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-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchema.java new file mode 100644 index 00000000000..8a773f91c72 --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.java new file mode 100644 index 00000000000..fde6f36b2e3 --- /dev/null +++ b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ProviderApplication.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 ProviderApplication { + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(ProviderApplication.class).run(args); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java new file mode 100644 index 00000000000..a238d77be24 --- /dev/null +++ b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ProviderController.java @@ -0,0 +1,105 @@ +/* + * 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.nio.charset.StandardCharsets; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.zookeeper.ZookeeperClient; +import org.apache.servicecomb.config.zookeeper.ZookeeperConfig; +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.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@RestSchema(schemaId = "ProviderController") +@RequestMapping(path = "/") +public class ProviderController implements InitializingBean { + private Environment environment; + + private ZookeeperConfig zookeeperConfig; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + this.zookeeperConfig = new ZookeeperConfig(environment); + } + + // a very simple service to echo the request parameter + @GetMapping("/sayHello") + public String sayHello(@RequestParam("name") String name) { + return "Hello " + name; + } + + @GetMapping("/getConfig") + public String getConfig(@RequestParam("key") String key) { + return environment.getProperty(key); + } + + @Override + public void afterPropertiesSet() throws Exception { + CuratorFramework client = CuratorFrameworkFactory.newClient(zookeeperConfig.getConnectString(), + zookeeperConfig.getSessionTimeoutMillis(), zookeeperConfig.getConnectionTimeoutMillis(), + new ExponentialBackoffRetry(1000, 3)); + client.start(); + client.blockUntilConnected(10, TimeUnit.SECONDS); + + String env = BootStrapProperties.readServiceEnvironment(environment); + if (StringUtils.isEmpty(env)) { + env = ZookeeperConfig.ZOOKEEPER_DEFAULT_ENVIRONMENT; + } + + String path = String.format(ZookeeperClient.PATH_ENVIRONMENT, env); + if (client.checkExists().forPath(path + "/config.properties") != null) { + client.delete().forPath(path + "/config.properties"); + } + client.create().creatingParentsIfNeeded(). + forPath(path + "/config.properties", "key1=1\nkey2=2".getBytes(StandardCharsets.UTF_8)); + + path = String.format(ZookeeperClient.PATH_VERSION, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment)); + if (client.checkExists().forPath(path + "/config.properties") != null) { + client.delete().forPath(path + "/config.properties"); + } + client.create().creatingParentsIfNeeded(). + forPath(path + "/config.properties", "key2=3\nkey3=4".getBytes(StandardCharsets.UTF_8)); + + path = String.format(ZookeeperClient.PATH_TAG, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment), + zookeeperConfig.getInstanceTag()); + if (client.checkExists().forPath(path + "/config.properties") != null) { + client.delete().forPath(path + "/config.properties"); + } + client.create().creatingParentsIfNeeded(). + forPath(path + "/config.properties", "key2=3\nkey3=5".getBytes(StandardCharsets.UTF_8)); + + client.close(); + } +} diff --git a/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/ReactiveStreamController.java new file mode 100644 index 00000000000..8108d15fd46 --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java b/demo/demo-zookeeper/provider/src/main/java/org/apache/servicecomb/samples/WebsocketController.java new file mode 100644 index 00000000000..6381ef1d54c --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/provider/src/main/resources/application.yml b/demo/demo-zookeeper/provider/src/main/resources/application.yml new file mode 100644 index 00000000000..dd777236bd8 --- /dev/null +++ b/demo/demo-zookeeper/provider/src/main/resources/application.yml @@ -0,0 +1,47 @@ +# +## --------------------------------------------------------------------------- +## 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-zookeeper + version: 0.0.1 + name: provider + properties: + group: green + registry: + zk: + connectString: 127.0.0.1:2181 + config: + zk: + connectString: 127.0.0.1:2181 + instance-tag: config-demo + + rest: + address: 0.0.0.0:9094?websocketEnabled=true + server: + websocket-prefix: /ws + + highway: + address: 0.0.0.0:7094 + + cors: + enabled: true + origin: "*" + allowCredentials: false + allowedMethod: "*" + maxAge: 3600 diff --git a/demo/demo-zookeeper/provider/src/main/resources/log4j2.xml b/demo/demo-zookeeper/provider/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-zookeeper/provider/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-zookeeper/test-client/pom.xml b/demo/demo-zookeeper/test-client/pom.xml new file mode 100644 index 00000000000..e527b630005 --- /dev/null +++ b/demo/demo-zookeeper/test-client/pom.xml @@ -0,0 +1,196 @@ + + + + + 4.0.0 + + + org.apache.servicecomb.demo + demo-zookeeper + 3.4.0-SNAPSHOT + + + zookeeper-test-client + Java Chassis::Demo::Zookeeper::TEST-CLIENT + jar + + + + + + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + + + org.apache.servicecomb.demo + demo-schema + + + org.apache.servicecomb + registry-local + + + + + + docker + + + + + io.fabric8 + docker-maven-plugin + + + + zookeeper:3.8.3 + zookeeper + + alias + + binding to port + + + 2181 + + + + + + zookeeper.port:2181 + + + + + zookeeper-provider:${project.version} + zookeeper-provider + + alias + + + -Dservicecomb.registry.zk.connectString=zookeeper:2181 -Dservicecomb.config.zk.connectString=zookeeper:2181 + + /maven/maven/zookeeper-provider-${project.version}.jar + + + zookeeper:zookeeper + + + ServiceComb is ready + + + 9094 + + + + + + 9094:9094 + + + + + zookeeper-consumer:${project.version} + zookeeper-consumer + + alias + + + -Dservicecomb.registry.zk.connectString=zookeeper:2181 + + /maven/maven/zookeeper-consumer-${project.version}.jar + + + zookeeper:zookeeper + + + ServiceComb is ready + + + 9092 + + + + + + 9092:9092 + + + + + zookeeper-gateway:${project.version} + zookeeper-gateway + + alias + + + -Dservicecomb.registry.zk.connectString=zookeeper:2181 + + /maven/maven/zookeeper-gateway-${project.version}.jar + + + zookeeper:zookeeper + + + 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-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/Config.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/Config.java new file mode 100644 index 00000000000..2e9105cdd4a --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/HeaderParamWithListSchemaIT.java new file mode 100644 index 00000000000..1b129acc2c6 --- /dev/null +++ b/demo/demo-zookeeper/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-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/HelloWorldIT.java new file mode 100644 index 00000000000..97e883fb45f --- /dev/null +++ b/demo/demo-zookeeper/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 entity = new HttpEntity(headers); + ResponseEntity response = + template.exchange(Config.GATEWAY_URL + "/sayHello?name=World", HttpMethod.GET, entity, String.class); + TestMgr.check(1, response.getHeaders().get("X-B3-TraceId").size()); + TestMgr.check("81de2eb7691c2bbb", response.getHeaders().getFirst("X-B3-TraceId")); + TestMgr.check("Hello World", response.getBody()); + } +} diff --git a/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java new file mode 100644 index 00000000000..488a6cf712a --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/ReactiveStreamIT.java @@ -0,0 +1,119 @@ +/* + * 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 org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.ReactiveStreamClient; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.ReactiveStreamClient.Model; +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +public class ReactiveStreamIT implements CategorizedTestCase { + @Autowired + @Qualifier("reactiveStreamProvider") + ReactiveStreamClient reactiveStreamProvider; + + @Autowired + @Qualifier("reactiveStreamGateway") + ReactiveStreamClient reactiveStreamGateway; + + @Override + public void testRestTransport() throws Exception { + testSseString(reactiveStreamProvider); + testSseModel(reactiveStreamProvider); + testSseString(reactiveStreamGateway); + testSseModel(reactiveStreamGateway); + } + + private void testSseModel(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseModel(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(Model s) { + buffer.append(s.getName()).append(s.getAge()); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("jack0jack1jack2jack3jack4", buffer.toString()); + } + + private void testSseString(ReactiveStreamClient client) throws Exception { + Publisher result = client.sseString(); + StringBuilder buffer = new StringBuilder(); + CountDownLatch countDownLatch = new CountDownLatch(1); + result.subscribe(new Subscriber<>() { + Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + subscription = s; + subscription.request(1); + } + + @Override + public void onNext(String s) { + buffer.append(s); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + subscription.cancel(); + countDownLatch.countDown(); + } + + @Override + public void onComplete() { + countDownLatch.countDown(); + } + }); + countDownLatch.await(10, TimeUnit.SECONDS); + TestMgr.check("abc", buffer.toString()); + } +} diff --git a/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java new file mode 100644 index 00000000000..26a2a491bbe --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/TestClientApplication.java @@ -0,0 +1,49 @@ +/* + * 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.CategorizedTestCaseRunner; +import org.apache.servicecomb.demo.TestMgr; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +@SpringBootApplication +public class TestClientApplication { + private static final Logger LOGGER = LoggerFactory.getLogger(TestClientApplication.class); + + public static void main(String[] args) throws Exception { + try { + new SpringApplicationBuilder().web(WebApplicationType.NONE).sources(TestClientApplication.class).run(args); + + run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + } + + public static void run() throws Exception { + CategorizedTestCaseRunner.runCategorizedTestCase("consumer"); + } +} diff --git a/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java new file mode 100644 index 00000000000..5f23c66cdac --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/ThirdSvcConfiguration.java @@ -0,0 +1,125 @@ +/* + * 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.core.CoreConst; +import org.apache.servicecomb.core.annotation.Transport; +import org.apache.servicecomb.localregistry.RegistryBean; +import org.apache.servicecomb.localregistry.RegistryBean.Instance; +import org.apache.servicecomb.localregistry.RegistryBean.Instances; +import org.apache.servicecomb.provider.pojo.Invoker; +import org.reactivestreams.Publisher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import io.vertx.core.http.WebSocket; + +@Configuration +public class ThirdSvcConfiguration { + @RequestMapping(path = "/ws") + public interface WebsocketClient { + @PostMapping("/websocket") + @Transport(name = CoreConst.WEBSOCKET) + WebSocket websocket(); + } + + @RequestMapping(path = "/") + public interface ReactiveStreamClient { + 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") + Publisher sseString(); + + @GetMapping("/sseModel") + Publisher sseModel(); + } + + @Bean + public RegistryBean providerServiceBean() { + return new RegistryBean() + .addSchemaInterface("ReactiveStreamController", ReactiveStreamClient.class) + .setAppId("demo-zookeeper") + .setServiceName("provider") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of( + new Instance().setEndpoints(List.of("rest://localhost:9094"))))); + } + + @Bean + public RegistryBean gatewayServiceBean() { + return new RegistryBean() + .addSchemaInterface("ReactiveStreamController", ReactiveStreamClient.class) + .addSchemaInterface("WebsocketController", WebsocketClient.class) + .setAppId("demo-zookeeper") + .setServiceName("gateway") + .setVersion("0.0.1") + .setInstances(new Instances().setInstances(List.of( + new Instance().setEndpoints(List.of("rest://localhost:9090?websocketEnabled=true"))))); + } + + @Bean("reactiveStreamProvider") + public ReactiveStreamClient reactiveStreamProvider() { + return Invoker.createProxy("provider", "ReactiveStreamController", ReactiveStreamClient.class); + } + + @Bean("reactiveStreamGateway") + public ReactiveStreamClient reactiveStreamGateway() { + return Invoker.createProxy("gateway", "ReactiveStreamController", ReactiveStreamClient.class); + } + + @Bean + public WebsocketClient gatewayWebsocketClient() { + return Invoker.createProxy("gateway", "WebsocketController", WebsocketClient.class); + } +} diff --git a/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java new file mode 100644 index 00000000000..c36f2d16d28 --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/main/java/org/apache/servicecomb/samples/WebsocketIT.java @@ -0,0 +1,73 @@ +/* + * 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.AtomicBoolean; + +import org.apache.servicecomb.demo.CategorizedTestCase; +import org.apache.servicecomb.demo.TestMgr; +import org.apache.servicecomb.samples.ThirdSvcConfiguration.WebsocketClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import io.vertx.core.http.WebSocket; + +@Component +public class WebsocketIT implements CategorizedTestCase { + @Autowired + private WebsocketClient websocketClient; + + @Override + public void testRestTransport() throws Exception { + StringBuffer sb = new StringBuffer(); + AtomicBoolean closed = new AtomicBoolean(false); + CountDownLatch latchStarted = new CountDownLatch(1); + CountDownLatch latch = new CountDownLatch(1); + + WebSocket webSocket = websocketClient.websocket(); + webSocket.textMessageHandler(s -> { + if ("started".equals(s)) { + latchStarted.countDown(); + return; + } + sb.append(s); + sb.append(" "); + webSocket.writeTextMessage(s); + }); + webSocket.closeHandler(v -> { + closed.set(true); + latch.countDown(); + }); + + webSocket.writeTextMessage("start"); + int i = 0; + for (; i < 10; i++) { + if (!latchStarted.await(3, TimeUnit.SECONDS)) { + webSocket.writeTextMessage("start"); + continue; + } + break; + } + TestMgr.check(i < 10, true); + latch.await(30, TimeUnit.SECONDS); + TestMgr.check(sb.toString(), "hello hello 0 hello 1 hello 2 hello 3 hello 4 total 6 "); + TestMgr.check(closed.get(), true); + } +} diff --git a/demo/demo-zookeeper/test-client/src/main/resources/application.yml b/demo/demo-zookeeper/test-client/src/main/resources/application.yml new file mode 100644 index 00000000000..6f8a74f5c9d --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/main/resources/application.yml @@ -0,0 +1,25 @@ +# +## --------------------------------------------------------------------------- +## 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-zookeeper + name: test-client + version: 0.0.1 + + rest: + address: 0.0.0.0:9097 # should be same with server.port to use web container diff --git a/demo/demo-zookeeper/test-client/src/main/resources/log4j2.xml b/demo/demo-zookeeper/test-client/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..c51f7ad5036 --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/main/resources/log4j2.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + diff --git a/demo/demo-zookeeper/test-client/src/test/java/org/apache/servicecomb/samples/ZookeeperIT.java b/demo/demo-zookeeper/test-client/src/test/java/org/apache/servicecomb/samples/ZookeeperIT.java new file mode 100644 index 00000000000..549cfe2a300 --- /dev/null +++ b/demo/demo-zookeeper/test-client/src/test/java/org/apache/servicecomb/samples/ZookeeperIT.java @@ -0,0 +1,53 @@ +/* + * 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.TestMgr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = TestClientApplication.class) +public class ZookeeperIT { + private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperIT.class); + + @BeforeEach + public void setUp() { + TestMgr.errors().clear(); + } + + @Test + public void clientGetsNoError() throws Exception { + try { + TestClientApplication.run(); + } catch (Exception e) { + TestMgr.failed("test case run failed", e); + LOGGER.error("-------------- test failed -------------"); + LOGGER.error("", e); + LOGGER.error("-------------- test failed -------------"); + } + TestMgr.summary(); + Assertions.assertTrue(TestMgr.errors().isEmpty()); + } +} diff --git a/demo/docker-build-config/pom.xml b/demo/docker-build-config/pom.xml deleted file mode 100644 index 2541fa71d4a..00000000000 --- a/demo/docker-build-config/pom.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - demo-parent - org.apache.servicecomb.demo - 2.6.0-SNAPSHOT - - 4.0.0 - - docker-build-config - Java Chassis::Demo::Docker Build Config - pom - - - - - - io.fabric8 - docker-maven-plugin - - - - ${project.artifactId}:${project.version} - ${project.artifactId} - - openjdk:8-jre-alpine - - 7070 - 8080 - - - tar - ${root.basedir}/assembly/assembly.xml - - - java -Xmx128m $JAVA_OPTS -jar $JAR_PATH - - - - - - - - build - package - - build - - - - - - org.commonjava.maven.plugins - directory-maven-plugin - - - directories - - directory-of - - initialize - - root.basedir - - org.apache.servicecomb.demo - demo-parent - - - - - - - - - diff --git a/demo/docker-run-config-edge/pom.xml b/demo/docker-run-config-edge/pom.xml deleted file mode 100644 index 6ca6fe46f6e..00000000000 --- a/demo/docker-run-config-edge/pom.xml +++ /dev/null @@ -1,333 +0,0 @@ - - - - - demo-parent - org.apache.servicecomb.demo - 2.6.0-SNAPSHOT - - 4.0.0 - - docker-run-config-edge - Java Chassis::Demo::Docker Run Config - - pom - - - - - - io.fabric8 - docker-maven-plugin - - - - servicecomb/service-center - service-center - - - server is ready - - - 30100 - - - - - - 30100:30100 - - - - - authentication:${project.version} - authentication - - - - -Dservicecomb.service.registry.address=http://sc.servicecomb.io:30100 - - /maven/maven/authentication-${project.version}.jar - - - service-center:sc.servicecomb.io - - - Register microservice instance success - - - - 7070 - - - - - - 7070:7070 - - - service-center - - - - - business-1-0-0:${project.version} - business-1-0-0 - - - - -Dservicecomb.service.registry.address=http://sc.servicecomb.io:30100 - - /maven/maven/business-1-0-0-${project.version}.jar - - - service-center:sc.servicecomb.io - - - Register microservice instance success - - - - 8080 - - - - - - 8080:8080 - - - service-center - - - - - business-1-1-0:${project.version} - business-1-1-0 - - - - -Dservicecomb.service.registry.address=http://sc.servicecomb.io:30100 - - /maven/maven/business-1-1-0-${project.version}.jar - - - service-center:sc.servicecomb.io - - - Register microservice instance success - - - - 8090 - - - - - - 8090:8090 - - - service-center - - - - - business-2-0-0:${project.version} - business-2-0-0 - - - - -Dservicecomb.service.registry.address=http://sc.servicecomb.io:30100 - - /maven/maven/business-2-0-0-${project.version}.jar - - - service-center:sc.servicecomb.io - - - Register microservice instance success - - - - 8091 - - - - - - 8091:8091 - - - service-center - - - - - edge-service:${project.version} - edge-service - - - - -Dservicecomb.service.registry.address=http://sc.servicecomb.io:30100 -Dservicecomb.service.publishAddress=${docker.hostname} - - /maven/maven/edge-service-${project.version}.jar - - - service-center:sc.servicecomb.io - - - Register microservice instance success - - - - 18080 - - - - - - 18080:18080 - - - service-center - - - - - - - - start - pre-integration-test - - start - - - - stop - post-integration-test - - stop - - - - - - - - - - - docker - - - - org.codehaus.gmaven - gmaven-plugin - - - add-default-properties - initialize - - execute - - - - project.properties.setProperty('docker.hostname', 'localhost') - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.19.1 - - - http://${docker.hostname}:30100 - - ${jacoco.failsafe.argLine} - - - - - integration-test - verify - - - - - - - - - docker-machine - - - - org.codehaus.gmaven - gmaven-plugin - - - add-dynamic-properties - prepare-package - - execute - - - - def process = "docker-machine ip default".execute() - process.waitFor() - project.properties.setProperty('docker.hostname', process.in.text.trim()) - - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - - - - diff --git a/demo/docker-run-config-local/pom.xml b/demo/docker-run-config-local/pom.xml deleted file mode 100644 index 1e488a83440..00000000000 --- a/demo/docker-run-config-local/pom.xml +++ /dev/null @@ -1,161 +0,0 @@ - - - - - demo-parent - org.apache.servicecomb.demo - 2.6.0-SNAPSHOT - - 4.0.0 - - docker-run-config-local - Java Chassis::Demo::Docker Run Config Local - - pom - - - - - - io.fabric8 - docker-maven-plugin - - - - ${demo.service.name}:${project.version} - ${demo.service.name} - - - - -Dservicecomb.service.publishAddress=${docker.hostname} - - /maven/maven/${demo.service.name}-${project.version}.jar - - - Register microservice instance success - - - 8080 - - - - - - 8080:8080 - - - - - - - - start - pre-integration-test - - start - - - - stop - post-integration-test - - stop - - - - - - - - - - - docker - - - - org.codehaus.gmaven - gmaven-plugin - - - add-default-properties - initialize - - execute - - - - project.properties.setProperty('docker.hostname', 'localhost') - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.19.1 - - ${jacoco.failsafe.argLine} - - - - - integration-test - verify - - - - - - - - - docker-machine - - - - org.codehaus.gmaven - gmaven-plugin - - - add-dynamic-properties - prepare-package - - execute - - - - def process = "docker-machine ip default".execute() - process.waitFor() - project.properties.setProperty('docker.hostname', process.in.text.trim()) - - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - - - - diff --git a/demo/docker-run-config/pom.xml b/demo/docker-run-config/pom.xml deleted file mode 100644 index 8e98e6f2db7..00000000000 --- a/demo/docker-run-config/pom.xml +++ /dev/null @@ -1,195 +0,0 @@ - - - - - demo-parent - org.apache.servicecomb.demo - 2.6.0-SNAPSHOT - - 4.0.0 - - docker-run-config - Java Chassis::Demo::Docker Run Config - - pom - - - - - - io.fabric8 - docker-maven-plugin - - - - servicecomb/service-center - service-center - - - server is ready - - - 30100 - - - - - - 30100:30100 - - - - - ${demo.service.name}:${project.version} - ${demo.service.name} - - - - -Dservicecomb.service.registry.address=http://sc.servicecomb.io:30100 -Dservicecomb.service.publishAddress=${docker.hostname} - - /maven/maven/${demo.service.name}-${project.version}.jar - - - service-center:sc.servicecomb.io - - - Register microservice instance success - - - - - 8080 - - - - - - 7070:7070 - 8080:8080 - - - service-center - - - - - - - - start - pre-integration-test - - start - - - - stop - post-integration-test - - stop - - - - - - - - - - - docker - - - - org.codehaus.gmaven - gmaven-plugin - - - add-default-properties - initialize - - execute - - - - project.properties.setProperty('docker.hostname', 'localhost') - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - 2.19.1 - - - http://${docker.hostname}:30100 - - ${jacoco.failsafe.argLine} - - - - - integration-test - verify - - - - - - - - - docker-machine - - - - org.codehaus.gmaven - gmaven-plugin - - - add-dynamic-properties - prepare-package - - execute - - - - def process = "docker-machine ip default".execute() - process.waitFor() - project.properties.setProperty('docker.hostname', process.in.text.trim()) - - log.info("Docker hostname is " + project.properties['docker.hostname']) - - - - - - - - - - diff --git a/demo/pom.xml b/demo/pom.xml index d955c62b57d..d0376883c6b 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -22,45 +22,44 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default org.apache.servicecomb.demo demo-parent Java Chassis::Demo + + + + pom - docker-build-config - docker-run-config - docker-run-config-edge - docker-run-config-local demo-schema demo-pojo + demo-filter demo-jaxrs demo-springmvc demo-crossapp demo-register-url-prefix demo-local-registry demo-multi-registries - demo-zeroconfig-schemadiscovery-registry - demo-spring-boot-provider + demo-zeroconfig-registry demo-spring-boot-transport demo-edge demo-multiple demo-multi-service-center - demo-signature demo-cse-v1 demo-cse-v2 + demo-nacos + + + demo-zookeeper + demo-consul - - org.apache.servicecomb.demo - demo-signature - ${project.version} - org.apache.servicecomb.demo demo-schema @@ -129,30 +128,30 @@ + + + org.junit.jupiter + junit-jupiter + compile + + + - - com.github.odavid.maven.plugins - mixin-maven-plugin - 0.1-alpha-39 - true - org.commonjava.maven.plugins directory-maven-plugin - 0.3.1 + 1.0 maven-deploy-plugin - 2.8.2 true maven-install-plugin - 2.5.2 false @@ -160,7 +159,6 @@ org.apache.maven.plugins maven-jar-plugin - 2.6 assembly @@ -177,52 +175,58 @@ + + org.commonjava.maven.plugins + directory-maven-plugin + + + directories + + directory-of + + initialize + + root.basedir + + org.apache.servicecomb.demo + demo-parent + + + + + + + + org.commonjava.maven.plugins + directory-maven-plugin + + - demo-run-release + docker - - - - org.apache.maven.plugins - maven-jar-plugin - - ${project.build.directory} - - - true - ./lib/ - ${demo.main} - - - . .. - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - ${project.build.directory}/lib - true - - - - - - + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + ${jacoco.failsafe.argLine} + + + + + integration-test + verify + + + + + diff --git a/dependencies/bom/pom.xml b/dependencies/bom/pom.xml index 1de19ec00a2..ed5e1bc91a2 100644 --- a/dependencies/bom/pom.xml +++ b/dependencies/bom/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb java-chassis-dependencies-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT java-chassis-bom @@ -34,28 +34,6 @@ - - - org.apache.servicecomb.archetypes - business-service-jaxrs-archetype - ${project.version} - - - org.apache.servicecomb.archetypes - business-service-pojo-archetype - ${project.version} - - - org.apache.servicecomb.archetypes - business-service-spring-boot2-starter-archetype - ${project.version} - - - org.apache.servicecomb.archetypes - business-service-springmvc-archetype - ${project.version} - - org.apache.servicecomb @@ -72,6 +50,11 @@ config-kie-client ${project.version} + + org.apache.servicecomb + dashboard-client + ${project.version} + org.apache.servicecomb http-client-common @@ -107,13 +90,6 @@ ${project.version} - - - org.apache.servicecomb - deployment - ${project.version} - - org.apache.servicecomb @@ -135,6 +111,16 @@ config-nacos ${project.version} + + org.apache.servicecomb + config-zookeeper + ${project.version} + + + org.apache.servicecomb + config-consul + ${project.version} + @@ -198,11 +184,6 @@ - - org.apache.servicecomb - handler-bizkeeper - ${project.version} - org.apache.servicecomb handler-fault-injection @@ -238,14 +219,8 @@ handler-tracing-zipkin ${project.version} - - - org.apache.servicecomb - inspector - ${project.version} - - + org.apache.servicecomb metrics-core @@ -290,47 +265,57 @@ org.apache.servicecomb - registry-schema-discovery + registry-service-center ${project.version} org.apache.servicecomb - registry-service-center + registry-zero-config ${project.version} org.apache.servicecomb - registry-zero-config + registry-nacos ${project.version} - org.apache.servicecomb - solution-basic + registry-zookeeper ${project.version} - org.apache.servicecomb - java-chassis-spring-boot-starter + registry-etcd ${project.version} org.apache.servicecomb - java-chassis-spring-boot-starter-servlet + config-etcd ${project.version} + + org.apache.servicecomb + registry-consul + ${project.version} + + org.apache.servicecomb - java-chassis-spring-boot-starter-standalone + solution-basic ${project.version} - + org.apache.servicecomb - servicestage-environment + java-chassis-spring-boot-starter-servlet ${project.version} + + org.apache.servicecomb + java-chassis-spring-boot-starter-standalone + ${project.version} + + org.apache.servicecomb servicestage @@ -426,4 +411,4 @@ - \ No newline at end of file + diff --git a/dependencies/default/pom.xml b/dependencies/default/pom.xml index 2760aabeaf8..22f2190ddd1 100644 --- a/dependencies/default/pom.xml +++ b/dependencies/default/pom.xml @@ -17,12 +17,12 @@ --> + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.apache.servicecomb java-chassis-dependencies-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT java-chassis-dependencies @@ -30,89 +30,66 @@ pom - - 0.7.7 - 1.6.2 - 1.9.3 - 3.0.0 - 3.11.1 - 5.6.0 - 1.5.0 - 1.9.4 - 1.10 - 2.8.0 + + 1.2.2 + 3.27.7 + 4.3.0 + 6.3.0 + 1.11.0 + 2.21.0 2.6 - 3.11 - 1.2 - 3.3.1 - 1.0.7.fixed.3500 - 4.0.2 - 2.0.0 + 3.20.0 + 1.3.5 + 1.15.0 + 5.9.0 + 1.0.3 3.0.2 - 1.14.2 - 1.12.10 - 30.0-jre - 1.0.1 - 4.2.0 + 1.17.12 + 1.17.13 + 33.5.0-jre + 5.1.0 1.3 - 2.1.10 - 6.0.2.Final - 6.1.5.Final - 4.5.13 + 2.2.2 + 9.1.0.Final + 4.5.14 1.5.18 - 2.12.1 - 0.26 + 2.20.1 + 1.6.0 1.3.2 1 1.5 - 1.2 - 2.1 - 2.27 - 1.4.0 - 1.30 - 2.4 - 4.12 - 5.6.2 + 4.0.2 + 1.34 + 4.13.2 + 5.13.4 1.2.17 - 2.13.2 - 1.2.3 - 1.10.19 - 3.10.4 - 5.3.2.Final + 2.25.3 + 3.9.12 + 1.16.4 + 5.21.0 + 5.2.0 + 5.15.0 + 3.1.1 0.3.0 - 4.1.67.Final - 3.14.2 - 1.6.2 - 0.6.0 - 3.7.1 - 1.5.9 - 2.2.25 - 2.3.0 - 1.1.6 - 0.4.9 - 1.0.0 - 0.12.25 - 4.0.3 - 1.2.1 - 1.7.30 - 1.27 - 0.83.0 - 5.2.9.RELEASE - 2.3.4.RELEASE - 4.2 - 1.6.2 - 1.3.3 - 2.0.40.Final - 0.10 - 2.6.0 - 4.1.2 - 1.4.11.1 - 2.19.1 - 2.7.13 - 3.4.14 - 1.1.4 + 0.16.0 + 3.23.4 + 1.8.0 + 2.2.27 + 1.0.4 1.7.0 - 1.5.1 + 2.7.18 + 3.1.12 + 1.0.0 + 0.13.2 + 6.0.0 + 1.7.36 + 2.5 + 2.2.41 + 5.0.8 + 3.5.1 + 3.4.0 + 0.8.6 + 1.8.0 ${basedir}/../.. @@ -120,56 +97,6 @@ - - ch.qos.logback - logback-classic - ${logback.version} - - - ch.qos.logback - logback-core - ${logback.version} - - - - com.101tec - zkclient - ${tec-zkclient.version} - - - - com.dyuproject.protostuff - protostuff-api - ${dyuproject-protostuff.version} - - - com.dyuproject.protostuff - protostuff-collectionschema - ${dyuproject-protostuff.version} - - - com.dyuproject.protostuff - protostuff-core - ${dyuproject-protostuff.version} - - - com.dyuproject.protostuff - protostuff-runtime - ${dyuproject-protostuff.version} - - - - com.esotericsoftware - kryo-shaded - ${esotericsoftware.version} - - - - com.fasterxml - classmate - ${classmate.version} - - com.fasterxml.jackson jackson-bom @@ -178,6 +105,20 @@ pom + + org.mockito + mockito-bom + ${mockito.version} + import + pom + + + org.mockito + mockito-inline + ${mockito-inline.version} + test + + com.github.seanyinx unit-scaffolding @@ -186,18 +127,21 @@ - com.github.tomakehurst - wiremock-standalone - ${tomakehurst.version} - test + org.apache.curator + curator-x-discovery + ${curator.version} - - com.google.code.findbugs - annotations - ${findbugs-annotations.version} - provided + org.apache.curator + curator-framework + ${curator.version} + + + org.apache.curator + curator-recipes + ${curator.version} + com.google.code.findbugs jsr305 @@ -233,125 +177,18 @@ + + com.google.inject.extensions + guice-assistedinject + ${guice.version} + + com.google.protobuf protobuf-java ${protobuf.version} - - - - com.netflix.archaius - archaius-core - ${archaius.version} - - - com.google.code.findbugs - annotations - - - - - - com.netflix.governator - governator-annotations - ${governator-annotations.version} - - - com.netflix.governator - governator-api - ${governator-api.version} - - - - com.netflix.hystrix - hystrix-core - ${hystrix.version} - - - - com.netflix.netflix-commons - netflix-eventbus - ${netflix-commons.version} - - - javax.servlet - servlet-api - - - - - com.netflix.netflix-commons - netflix-eventbus-rx - ${netflix-commons.version} - - - javax.servlet - servlet-api - - - com.netflix.rxjava - rxjava-core - - - - - - com.netflix.ribbon - ribbon - ${ribbon.version} - - - com.netflix.ribbon - ribbon-core - ${ribbon.version} - - - com.google.code.findbugs - annotations - - - - - com.netflix.ribbon - ribbon-loadbalancer - ${ribbon.version} - - - com.google.code.findbugs - annotations - - - - - - com.netflix.servo - servo-core - ${servo.version} - - - com.google.code.findbugs - annotations - - - - - - com.netflix.spectator - spectator-reg-servo - ${spectator.version} - - - - com.squareup.okhttp3 - okhttp - ${okhttp3.version} - - - - com.thoughtworks.xstream - xstream - ${xstream.version} + test @@ -360,12 +197,6 @@ ${commons-beanutils.version} - - commons-configuration - commons-configuration - ${commons-configuration.version} - - commons-io commons-io @@ -385,75 +216,24 @@ - de.javakaffee - kryo-serializers - ${javakaffee.version} - - - - io.github.swagger2markup - swagger2markup - ${swagger2markup.version} - - - io.swagger - swagger-compat-spec-parser - - - commons-collections - commons-collections - - + org.apache.maven + maven-model + ${maven-model.version} - io.netty - netty-bom - import - ${netty.version} + io.micrometer + micrometer-bom + ${micrometer.version} pom - - - io.netty - netty-tcnative-boringssl-static - ${tcnetty.version} - - - - io.reactivex - rxjava - ${rxjava.version} - - - io.reactivex - rxnetty - ${rxnetty.version} - - - - io.netty - netty-codec-http - - - io.netty - netty-handler - - - io.netty - netty-transport-native-epoll - - - - - - io.prometheus - simpleclient - ${prometheus.version} + import io.prometheus - simpleclient_httpserver + simpleclient_bom ${prometheus.version} + pom + import @@ -470,6 +250,10 @@ org.abego.treelayout org.abego.treelayout.core + + com.google.inject.extensions + guice-multibindings + @@ -479,71 +263,33 @@ - io.swagger - swagger-core + io.swagger.core.v3 + swagger-core-jakarta ${swagger.version} - io.vertx - vertx-codegen - ${vertx.version} - - - io.vertx - vertx-core - ${vertx.version} + io.reactivex.rxjava3 + rxjava + ${rxjava.version} - io.vertx - vertx-web - ${vertx.version} + org.reactivestreams + reactive-streams + ${reactive-streams.version} io.zipkin.brave - brave - ${brave.version} - - - io.zipkin.brave - brave-context-slf4j - ${brave.version} - - - io.zipkin.brave - brave-instrumentation-jaxrs2 - ${brave.version} - - - io.zipkin.brave - brave-instrumentation-servlet - ${brave.version} - - - io.zipkin.brave - brave-instrumentation-spring-web - ${brave.version} - - - io.zipkin.brave - brave-instrumentation-spring-webmvc - ${brave.version} - - - io.zipkin.brave - brave-spring-beans + brave-bom ${brave.version} + pom + import io.zipkin.reporter2 - zipkin-reporter - ${zipkin-reporter.version} - - - io.zipkin.reporter2 - zipkin-sender-okhttp3 + zipkin-reporter-bom ${zipkin-reporter.version} @@ -552,12 +298,6 @@ zipkin ${zipkin.version} - - io.zipkin.zipkin2 - zipkin-junit - ${zipkin.version} - test - jakarta.servlet @@ -587,18 +327,6 @@ ${javax-resource.version} - - javax.transaction - javax.transaction-api - ${javax-transaction.version} - - - - javax.ws.rs - javax.ws.rs-api - ${javax-ws-rs.version} - - junit junit @@ -613,19 +341,6 @@ import - - log4j - log4j - ${log4j.version} - - - - net.sf.json-lib - json-lib - ${json-lib.version} - jdk15 - - org.apache.commons commons-lang3 @@ -633,14 +348,9 @@ - org.apache.cxf - cxf-rt-frontend-jaxws - ${cxf.version} - - - org.apache.cxf - cxf-rt-transports-http - ${cxf.version} + org.apache.commons + commons-text + ${commons-text.version} @@ -665,32 +375,6 @@ ${log4j2.version} - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - provided - true - - - - org.asciidoctor - asciidoctorj - ${asciidoctorj.version} - - - com.jcraft - jzlib - - - - - - org.aspectj - aspectjweaver - ${aspectj.version} - - org.awaitility awaitility @@ -706,21 +390,14 @@ - org.codehaus.jettison - jettison - ${jettison.version} - runtime - - - - org.codehaus.woodstox - stax2-api - ${stax2-api.version} + org.glassfish.jersey.core + jersey-common + ${jersey.version} org.glassfish.jersey.core - jersey-common + jersey-client ${jersey.version} @@ -737,17 +414,6 @@ test - - org.hibernate - hibernate-validator - ${hibernate.version} - - - org.hibernate - hibernate-validator-annotation-processor - ${hibernate.version} - - org.hibernate.validator hibernate-validator @@ -756,7 +422,7 @@ org.hibernate.validator hibernate-validator-annotation-processor - ${hibernate.version} + ${hibernate-validator.version} @@ -772,76 +438,16 @@ test - - org.mockito - mockito-all - ${mockito.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - - org.mock-server - mockserver-netty - ${mock-server.version} - test - - - - org.powermock - powermock-api-mockito - ${powermock.version} - test - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-module-test-mockito-junit4-delegate - ${powermock.version} - test - - org.slf4j slf4j-api ${slf4j.version} - - org.slf4j - slf4j-ext - ${slf4j.version} - - - ch.qos.cal10n - cal10n-api - - - - - org.slf4j - slf4j-log4j12 - ${slf4j.version} - - - org.slf4j - log4j-over-slf4j - ${slf4j.version} - - org.springframework - spring-framework-bom - ${spring.version} + io.vertx + vertx-dependencies + ${vertx.version} pom import @@ -887,6 +493,18 @@ pom import + + + io.etcd + jetcd-core + ${jetcd-core.version} + + + + org.kiwiproject + consul-client + ${consul-client.version} + diff --git a/dependencies/pom.xml b/dependencies/pom.xml index e1ad71091d9..4ee9c9ea071 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb java-chassis - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT java-chassis-dependencies-parent diff --git a/deployment/README.md b/deployment/README.md deleted file mode 100644 index b2764cc0a49..00000000000 --- a/deployment/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# About Deployment Module - -Deployment is a mechanism to manage how microservics interact with external services. When running a microservice in a Cloud Native environment, it will interact with many external services, like service center, config center, an APM service to report tracing data, a dashboard service to report health data, etc. Deployment Service manages the meta data of these services. Deployment queries the addresses , the parameters, the authentication information of these services and so on. - -Deployment Service is some kind of service like service center, they are differ from two aspects: -1. All microservics will report their information to service center. But Deployment Service acts as a management system and knows the meta information in deploy time. -2. Service center provide some other functions like instance management and heartbeat, while Deployment Service only provides metadata query services and it is simple. - -This module does not provide a Deployment Service, it provides the interface to interacts with Deployment Service. Service providers can implement the interface. - -They are some design constraints need to be considered when implement Deployment interface: -1. Deployment can only read configurations of environment, microservics.yaml. It can not read dynamic configurations. -2. Deployment is initialized before bean initialization. diff --git a/deployment/pom.xml b/deployment/pom.xml deleted file mode 100644 index cc44d1bb4bd..00000000000 --- a/deployment/pom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - org.apache.servicecomb - java-chassis-parent - 2.6.0-SNAPSHOT - ../parents/default - - 4.0.0 - - deployment - Java Chassis::Deployment - - - - org.apache.servicecomb - foundation-config - - - org.apache.servicecomb - foundation-vertx - - - org.apache.servicecomb - foundation-common - - - - io.vertx - vertx-codegen - provided - - - - org.slf4j - slf4j-log4j12 - test - - - log4j - log4j - test - - - org.apache.servicecomb - foundation-test-scaffolding - - - org.apache.commons - commons-lang3 - - - diff --git a/deployment/src/main/java/org/apache/servicecomb/deployment/Deployment.java b/deployment/src/main/java/org/apache/servicecomb/deployment/Deployment.java deleted file mode 100644 index f26980e54de..00000000000 --- a/deployment/src/main/java/org/apache/servicecomb/deployment/Deployment.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.deployment; - -import java.util.List; - -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; - -public class Deployment { - private static List providerList = SPIServiceUtils.getSortedService(DeploymentProvider.class); - - public static SystemBootstrapInfo getSystemBootStrapInfo(String systemKey) { - for (DeploymentProvider provider : providerList) { - if (provider.getSystemBootStrapInfo(systemKey) != null) { - return provider.getSystemBootStrapInfo(systemKey); - } - } - return null; - } -} diff --git a/deployment/src/main/java/org/apache/servicecomb/deployment/DeploymentProvider.java b/deployment/src/main/java/org/apache/servicecomb/deployment/DeploymentProvider.java deleted file mode 100644 index e2e5396e590..00000000000 --- a/deployment/src/main/java/org/apache/servicecomb/deployment/DeploymentProvider.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.deployment; - -public interface DeploymentProvider { - - default int getOrder() { - return 100; - } - - SystemBootstrapInfo getSystemBootStrapInfo(String systemKey); -} diff --git a/deployment/src/main/java/org/apache/servicecomb/deployment/SystemBootstrapInfo.java b/deployment/src/main/java/org/apache/servicecomb/deployment/SystemBootstrapInfo.java deleted file mode 100644 index c98f93e6a64..00000000000 --- a/deployment/src/main/java/org/apache/servicecomb/deployment/SystemBootstrapInfo.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.deployment; - -import java.util.List; -import java.util.Map; - -public class SystemBootstrapInfo { - private List accessURL; - - private Map properties; - - public List getAccessURL() { - return accessURL; - } - - public void setAccessURL(List accessURL) { - this.accessURL = accessURL; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(Map properties) { - this.properties = properties; - } - - public Object getProperty(String key) { - return properties.get(key); - } -} diff --git a/deployment/src/test/java/org/apache/servicecomb/deployment/CustomDeploymentProvider.java b/deployment/src/test/java/org/apache/servicecomb/deployment/CustomDeploymentProvider.java deleted file mode 100644 index 43c0a717710..00000000000 --- a/deployment/src/test/java/org/apache/servicecomb/deployment/CustomDeploymentProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.deployment; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.servicecomb.config.ConfigUtil; - -import java.util.Arrays; - -public class CustomDeploymentProvider implements DeploymentProvider { - private static AbstractConfiguration configuration = ConfigUtil.createLocalConfig(); - - @Override - public int getOrder() { - return 0; - } - - @Override - public SystemBootstrapInfo getSystemBootStrapInfo(String systemKey) { - if (!systemKey.equals("TestCenter")) { - return null; - } - SystemBootstrapInfo cc = new SystemBootstrapInfo(); - cc.setAccessURL(Arrays.asList("http://localhost/custom")); - return cc; - } - - @VisibleForTesting - public static void setConfiguration(AbstractConfiguration configuration) { - CustomDeploymentProvider.configuration = configuration; - } -} diff --git a/deployment/src/test/java/org/apache/servicecomb/deployment/TestDeployment.java b/deployment/src/test/java/org/apache/servicecomb/deployment/TestDeployment.java deleted file mode 100644 index b626381cf7e..00000000000 --- a/deployment/src/test/java/org/apache/servicecomb/deployment/TestDeployment.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.deployment; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; - -public class TestDeployment { - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testConfiguration() { - CustomDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo("TestCenter"); - Assert.assertEquals(info.getAccessURL().get(0), "http://localhost/custom"); - Assert.assertNull(Deployment.getSystemBootStrapInfo("wrong")); - } -} diff --git a/deployment/src/test/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider b/deployment/src/test/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider deleted file mode 100644 index d07cc1e76c4..00000000000 --- a/deployment/src/test/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.deployment.CustomDeploymentProvider diff --git a/distribution/pom.xml b/distribution/pom.xml index 00507bdda1d..ddd1e3de25d 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default apache-servicecomb-java-chassis-distribution @@ -29,24 +29,6 @@ pom - - - org.apache.servicecomb.archetypes - business-service-jaxrs-archetype - - - org.apache.servicecomb.archetypes - business-service-pojo-archetype - - - org.apache.servicecomb.archetypes - business-service-spring-boot2-starter-archetype - - - org.apache.servicecomb.archetypes - business-service-springmvc-archetype - - org.apache.servicecomb @@ -60,6 +42,10 @@ org.apache.servicecomb config-kie-client + + org.apache.servicecomb + dashboard-client + org.apache.servicecomb http-client-common @@ -68,6 +54,10 @@ org.apache.servicecomb service-center-client + + org.apache.servicecomb + registry-nacos + @@ -89,12 +79,6 @@ java-chassis-core - - - org.apache.servicecomb - deployment - - org.apache.servicecomb @@ -164,10 +148,6 @@ - - org.apache.servicecomb - handler-bizkeeper - org.apache.servicecomb handler-fault-injection @@ -197,12 +177,6 @@ handler-tracing-zipkin - - - org.apache.servicecomb - inspector - - org.apache.servicecomb @@ -240,10 +214,6 @@ org.apache.servicecomb registry-local - - org.apache.servicecomb - registry-schema-discovery - org.apache.servicecomb registry-service-center @@ -260,10 +230,6 @@ - - org.apache.servicecomb - java-chassis-spring-boot-starter - org.apache.servicecomb java-chassis-spring-boot-starter-servlet @@ -274,11 +240,6 @@ - - org.apache.servicecomb - servicestage-environment - - org.apache.servicecomb servicestage diff --git a/distribution/src/release/LICENSE b/distribution/src/release/LICENSE index 924d70d7334..b75be79468a 100644 --- a/distribution/src/release/LICENSE +++ b/distribution/src/release/LICENSE @@ -221,12 +221,6 @@ For swagger/swagger-generator/generator-core/src/main/java/org/apache/servicecom This product bundles files from swagger which is licensed under the Apache License v2. For details, see https://github.com/swagger-api/swagger-core -================================================================ -For handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixCommandPropertiesExt.java -================================================================ -This product bundles files from Hystrix which is licensed under the Apache License v2. -For details, see https://github.com/Netflix/Hystrix - ================================================================ For foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/ArrayFieldMapEx.java foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/FieldMapEx.java diff --git a/distribution/src/release/NOTICE b/distribution/src/release/NOTICE index d1821a3491c..5ed927047d5 100644 --- a/distribution/src/release/NOTICE +++ b/distribution/src/release/NOTICE @@ -1,6 +1,5 @@ Apache ServiceComb Java Chassis -Copyright 2017-2019 The Apache Software Foundation +Copyright 2017-2024 The Apache Software Foundation This product includes software developed at The Apache Software Foundation (http://www.apache.org/). - diff --git a/distribution/src/release/licenses/LICENSE-abego b/distribution/src/release/licenses/LICENSE-abego index a4fe241d454..1620af43b30 100644 --- a/distribution/src/release/licenses/LICENSE-abego +++ b/distribution/src/release/licenses/LICENSE-abego @@ -2,26 +2,26 @@ Copyright (c) 2011, abego Software GmbH, Germany (http://www.abego.org) All rights reserved. -Redistribution and use in source and binary forms, with or without +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -1. Redistributions of source code must retain the above copyright notice, +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. -3. Neither the name of the abego Software GmbH nor the names of its - contributors may be used to endorse or promote products derived from this +3. Neither the name of the abego Software GmbH nor the names of its + contributors may be used to endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/distribution/src/release/licenses/LICENSE-animalsniffer b/distribution/src/release/licenses/LICENSE-animalsniffer index 719e6d7f0fd..4e28c7bc322 100644 --- a/distribution/src/release/licenses/LICENSE-animalsniffer +++ b/distribution/src/release/licenses/LICENSE-animalsniffer @@ -18,4 +18,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. + THE SOFTWARE. diff --git a/distribution/src/release/licenses/LICENSE-checkerqual b/distribution/src/release/licenses/LICENSE-checkerqual index f6743bb6980..7f197e96dec 100644 --- a/distribution/src/release/licenses/LICENSE-checkerqual +++ b/distribution/src/release/licenses/LICENSE-checkerqual @@ -17,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/distribution/src/release/licenses/LICENSE-edl-v10 b/distribution/src/release/licenses/LICENSE-edl-v10 index a4a267ef07f..90202907fd2 100644 --- a/distribution/src/release/licenses/LICENSE-edl-v10 +++ b/distribution/src/release/licenses/LICENSE-edl-v10 @@ -9,4 +9,4 @@ Redistribution and use in source and binary forms, with or without modification, Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/distribution/src/release/licenses/LICENSE-epl-v10 b/distribution/src/release/licenses/LICENSE-epl-v10 index 3fa00836fa4..b0476ee93e8 100644 --- a/distribution/src/release/licenses/LICENSE-epl-v10 +++ b/distribution/src/release/licenses/LICENSE-epl-v10 @@ -83,4 +83,4 @@ All Recipient's rights under this Agreement shall terminate if it fails to compl Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. -This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. \ No newline at end of file +This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. diff --git a/distribution/src/release/licenses/LICENSE-jcodings b/distribution/src/release/licenses/LICENSE-jcodings index f8031949305..f85e365de02 100644 --- a/distribution/src/release/licenses/LICENSE-jcodings +++ b/distribution/src/release/licenses/LICENSE-jcodings @@ -15,4 +15,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/distribution/src/release/licenses/LICENSE-jsonp b/distribution/src/release/licenses/LICENSE-jsonp index 07368a285ae..75372e3d2c9 100644 --- a/distribution/src/release/licenses/LICENSE-jsonp +++ b/distribution/src/release/licenses/LICENSE-jsonp @@ -1,5 +1,5 @@ 1. Definitions. - + 1.1. "Contributor" means each individual or entity that creates or contributes to the creation of Modifications. diff --git a/distribution/src/release/licenses/LICENSE-logback b/distribution/src/release/licenses/LICENSE-logback index 8953762a3cd..1f99506bfa4 100644 --- a/distribution/src/release/licenses/LICENSE-logback +++ b/distribution/src/release/licenses/LICENSE-logback @@ -11,4 +11,4 @@ the Eclipse Foundation or (per the licensee's choosing) under the terms of the GNU Lesser General Public License version 2.1 -as published by the Free Software Foundation. \ No newline at end of file +as published by the Free Software Foundation. diff --git a/distribution/src/release/licenses/NOTICE-protostuff b/distribution/src/release/licenses/NOTICE-protostuff index e1c9c379777..1f95779a7fb 100644 --- a/distribution/src/release/licenses/NOTICE-protostuff +++ b/distribution/src/release/licenses/NOTICE-protostuff @@ -3,13 +3,13 @@ Copyright 2009 David Yu dyuproject@gmail.com ============================================================== -protobuf is copyright Google inc unless otherwise noted. +protobuf is copyright Google inc unless otherwise noted. It is licensed under the BSD license. -jackson-core-asl is copyright FasterXml unless otherwise noted. +jackson-core-asl is copyright FasterXml unless otherwise noted. It is licensed under the apache 2.0 license. -antlr is copyright Terence Parr unless otherwise noted. +antlr is copyright Terence Parr unless otherwise noted. It is licensed under the BSD license. stringtemplate is copyright Terence Parr unless otherwise noted. @@ -17,10 +17,10 @@ It is licensed under the BSD license. velocity is licensed under the apache 2.0 license. -B64Code.java is copyright Mort Bay Consulting Pty Ltd unless otherwise noted. +B64Code.java is copyright Mort Bay Consulting Pty Ltd unless otherwise noted. It is licensed under the apache 2.0 license. -jarjar is copyright Google inc unless otherwise noted. +jarjar is copyright Google inc unless otherwise noted. It is licensed under the apache 2.0 license. guava is copyright Google inc unless otherwise noted. diff --git a/doap_ServiceComb_Java-Chassis.rdf b/doap_ServiceComb_Java-Chassis.rdf deleted file mode 100644 index f5dbe8a1ced..00000000000 --- a/doap_ServiceComb_Java-Chassis.rdf +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - 2021-03-25 - - Apache ServiceComb Java-Chassis - - - ServiceComb Java Chassis is a Software Development Kit (SDK) for rapid development of microservices in Java, providing service registration, service discovery, dynamic routing, and service management features - ServiceComb Java Chassis is a Software Development Kit (SDK) for rapid development of microservices in Java, providing service registration, service discovery, dynamic routing, and service management features - - - - Java - - - - ServiceComb Java-Chassis 2.2.0 - 2021-02-28 - 2.2.0 - - - - - - - - - - - liubao68 - - - - - - diff --git a/dynamic-config/config-apollo/pom.xml b/dynamic-config/config-apollo/pom.xml index d9432ac30a4..7cc03d182dd 100644 --- a/dynamic-config/config-apollo/pom.xml +++ b/dynamic-config/config-apollo/pom.xml @@ -22,7 +22,7 @@ dynamic-config org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 config-apollo diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloClient.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloClient.java new file mode 100644 index 00000000000..61c6a9c5c7d --- /dev/null +++ b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloClient.java @@ -0,0 +1,165 @@ +/* + * 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.config.apollo; + +import static org.apache.servicecomb.config.apollo.ConfigurationAction.CREATE; +import static org.apache.servicecomb.config.apollo.ConfigurationAction.DELETE; +import static org.apache.servicecomb.config.apollo.ConfigurationAction.SET; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.config.apollo.ApolloDynamicPropertiesSource.UpdateHandler; +import org.apache.servicecomb.foundation.common.utils.JsonUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.google.common.annotations.VisibleForTesting; + +import io.netty.handler.codec.http.HttpResponseStatus; + +public class ApolloClient { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApolloClient.class); + + private static final Map originalConfigMap = new ConcurrentHashMap<>(); + + private static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(1); + + private final ApolloConfig apolloConfig; + + private final UpdateHandler updateHandler; + + private static RestTemplate rest = new RestTemplate(); + + public ApolloClient(UpdateHandler updateHandler, ApolloConfig apolloConfig) { + this.updateHandler = updateHandler; + this.apolloConfig = apolloConfig; + } + + @VisibleForTesting + static Map getOriginalConfigMap() { + return originalConfigMap; + } + + @VisibleForTesting + static void setRest(RestTemplate rest) { + ApolloClient.rest = rest; + } + + public void refreshApolloConfig() { + EXECUTOR.scheduleWithFixedDelay(new ConfigRefresh(apolloConfig.getServerUri()), + apolloConfig.getFirstRefreshInterval(), + apolloConfig.getRefreshInterval(), TimeUnit.SECONDS); + } + + class ConfigRefresh implements Runnable { + private final String serviceUri; + + ConfigRefresh(String serviceUris) { + this.serviceUri = serviceUris; + } + + @Override + public void run() { + try { + refreshConfig(); + } catch (Throwable e) { + LOGGER.error("client refresh thread exception ", e); + } + } + + @SuppressWarnings("unchecked") + void refreshConfig() { + HttpHeaders headers = new HttpHeaders(); + headers.add("Content-Type", "application/json;charset=UTF-8"); + headers.add("Authorization", apolloConfig.getToken()); + HttpEntity entity = new HttpEntity<>(headers); + ResponseEntity exchange = rest.exchange(composeAPI(), HttpMethod.GET, entity, String.class); + if (HttpResponseStatus.OK.code() == exchange.getStatusCode().value()) { + try { + Map body = JsonUtils.OBJ_MAPPER.readValue(exchange.getBody(), + new TypeReference>() { + }); + refreshConfigItems((Map) body.get("configurations")); + } catch (IOException e) { + LOGGER.error("JsonObject parse config center response error: ", e); + } + } else { + LOGGER.error("fetch configuration failed, error code:{} for {}", + exchange.getStatusCode().value(), + exchange.getBody()); + } + } + + private String composeAPI() { + String api = serviceUri + "/openapi/v1/envs/" + apolloConfig.getEnv() + + "/apps/" + apolloConfig.getServiceName() + + "/clusters/" + apolloConfig.getServerClusters() + + "/namespaces/" + apolloConfig.getNamespace() + + "/releases/latest"; + return api; + } + + private void refreshConfigItems(Map map) { + compareChangedConfig(originalConfigMap, map); + originalConfigMap.clear(); + originalConfigMap.putAll(map); + } + + void compareChangedConfig(Map before, Map after) { + Map itemsCreated = new HashMap<>(); + Map itemsDeleted = new HashMap<>(); + Map itemsModified = new HashMap<>(); + if (before == null || before.isEmpty()) { + updateHandler.handle(CREATE, after); + return; + } + if (after == null || after.isEmpty()) { + updateHandler.handle(DELETE, before); + return; + } + after.forEach((itemKey, itemValue) -> { + if (!before.containsKey(itemKey)) { + itemsCreated.put(itemKey, itemValue); + } else if (!itemValue.equals(before.get(itemKey))) { + itemsModified.put(itemKey, itemValue); + } + }); + for (String itemKey : before.keySet()) { + if (!after.containsKey(itemKey)) { + itemsDeleted.put(itemKey, ""); + } + } + updateHandler.handle(CREATE, itemsCreated); + updateHandler.handle(SET, itemsModified); + updateHandler.handle(DELETE, itemsDeleted); + } + } +} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloConfig.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloConfig.java new file mode 100644 index 00000000000..97509b9ee15 --- /dev/null +++ b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloConfig.java @@ -0,0 +1,80 @@ +/* + * 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.config.apollo; + +import org.springframework.core.env.Environment; + +public class ApolloConfig { + private static final String SERVER_URL_KEY = "apollo.config.serverUri"; + + private static final String SERVER_NAMESPACE = "apollo.config.namespace"; + + private static final String SERVER_ENV = "apollo.config.env"; + + private static final String SERVER_CLUSTERS = "apollo.config.clusters"; + + private static final String APOLLO_SERVICE_NAME = "apollo.config.serviceName"; + + private static final String TOKEN = "apollo.config.token"; + + private static final String REFRESH_INTERVAL = "apollo.config.refreshInterval"; + + private static final String FIRST_REFRESH_INTERVAL = "apollo.config.firstRefreshInterval"; + + private static final int DEFAULT_REFRESH_INTERVAL = 3; + + private static final int DEFAULT_FIRST_REFRESH_INTERVAL = 0; + + private final Environment environment; + + public ApolloConfig(Environment environment) { + this.environment = environment; + } + + public String getServiceName() { + return environment.getProperty(APOLLO_SERVICE_NAME); + } + + public String getServerUri() { + return environment.getProperty(SERVER_URL_KEY); + } + + public String getToken() { + return environment.getProperty(TOKEN); + } + + public String getEnv() { + return environment.getProperty(SERVER_ENV); + } + + public String getNamespace() { + return environment.getProperty(SERVER_NAMESPACE); + } + + public String getServerClusters() { + return environment.getProperty(SERVER_CLUSTERS); + } + + public int getRefreshInterval() { + return environment.getProperty(REFRESH_INTERVAL, int.class, DEFAULT_REFRESH_INTERVAL); + } + + public int getFirstRefreshInterval() { + return environment.getProperty(FIRST_REFRESH_INTERVAL, int.class, DEFAULT_FIRST_REFRESH_INTERVAL); + } +} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloConfiguration.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloConfiguration.java new file mode 100644 index 00000000000..152f23962c2 --- /dev/null +++ b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloConfiguration.java @@ -0,0 +1,24 @@ +/* + * 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.config.apollo; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ApolloConfiguration { + +} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloDynamicPropertiesSource.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloDynamicPropertiesSource.java new file mode 100644 index 00000000000..4a1113283e0 --- /dev/null +++ b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ApolloDynamicPropertiesSource.java @@ -0,0 +1,83 @@ +/* + * 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.config.apollo; + +import static org.apache.servicecomb.config.apollo.ConfigurationAction.CREATE; +import static org.apache.servicecomb.config.apollo.ConfigurationAction.DELETE; +import static org.apache.servicecomb.config.apollo.ConfigurationAction.SET; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.servicecomb.config.ConfigMapping; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +public class ApolloDynamicPropertiesSource implements DynamicPropertiesSource { + public static final String SOURCE_NAME = "apollo"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ApolloDynamicPropertiesSource.class); + + private final Map valueCache = new ConcurrentHashMap<>(); + + private final ApolloDynamicPropertiesSource.UpdateHandler updateHandler = + new ApolloDynamicPropertiesSource.UpdateHandler(); + + public ApolloDynamicPropertiesSource() { + } + + @Override + public int getOrder() { + return 300; + } + + private void init(Environment environment) { + ApolloConfig apolloConfig = new ApolloConfig(environment); + ApolloClient apolloClient = new ApolloClient(updateHandler, apolloConfig); + apolloClient.refreshApolloConfig(); + } + + public class UpdateHandler { + public void handle(ConfigurationAction action, Map config) { + if (config == null || config.isEmpty()) { + return; + } + Map configuration = ConfigMapping.getConvertedMap(config); + if (CREATE.equals(action)) { + valueCache.putAll(configuration); + } else if (SET.equals(action)) { + valueCache.putAll(configuration); + } else if (DELETE.equals(action)) { + configuration.keySet().forEach(valueCache::remove); + } else { + LOGGER.error("action: {} is invalid.", action.name()); + return; + } + LOGGER.warn("Config value cache changed: action:{}; item:{}", action.name(), configuration.keySet()); + } + } + + @Override + public PropertySource create(Environment environment) { + init(environment); + return new MapPropertySource(SOURCE_NAME, valueCache); + } +} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ConfigurationAction.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ConfigurationAction.java new file mode 100644 index 00000000000..1a0047152b2 --- /dev/null +++ b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/apollo/ConfigurationAction.java @@ -0,0 +1,24 @@ +/* + * 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.config.apollo; + +public enum ConfigurationAction { + CREATE, + SET, + DELETE +} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/archaius/sources/ApolloConfigurationSourceImpl.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/archaius/sources/ApolloConfigurationSourceImpl.java deleted file mode 100644 index 646779cc0e6..00000000000 --- a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/archaius/sources/ApolloConfigurationSourceImpl.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.config.archaius.sources; - -import static com.netflix.config.WatchedUpdateResult.createIncremental; -import static org.apache.servicecomb.config.client.ConfigurationAction.CREATE; -import static org.apache.servicecomb.config.client.ConfigurationAction.DELETE; -import static org.apache.servicecomb.config.client.ConfigurationAction.SET; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.config.ConfigMapping; -import org.apache.servicecomb.config.client.ApolloClient; -import org.apache.servicecomb.config.client.ApolloConfig; -import org.apache.servicecomb.config.client.ConfigurationAction; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableMap; -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; - -public class ApolloConfigurationSourceImpl implements ConfigCenterConfigurationSource { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterConfigurationSource.class); - - private final Map valueCache = new ConcurrentHashMap<>(); - - private List listeners = new CopyOnWriteArrayList<>(); - - private static final String APOLLO_CONFIG_URL_KEY = "apollo.config.serverUri"; - - public ApolloConfigurationSourceImpl() { - } - - private final UpdateHandler updateHandler = new UpdateHandler(); - - @Override - public int getOrder() { - return ORDER_BASE * 3; - } - - @Override - public boolean isValidSource(Configuration localConfiguration) { - if (localConfiguration.getProperty(APOLLO_CONFIG_URL_KEY) == null) { - LOGGER.warn("Apollo configuration source is not configured!"); - return false; - } - return true; - } - - @Override - public void init(Configuration localConfiguration) { - ApolloConfig.setConcurrentCompositeConfiguration(localConfiguration); - init(); - } - - private void init() { - ApolloClient apolloClient = new ApolloClient(updateHandler); - apolloClient.refreshApolloConfig(); - } - - @Override - public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.add(watchedUpdateListener); - } - - @Override - public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.remove(watchedUpdateListener); - } - - private void updateConfiguration(WatchedUpdateResult result) { - for (WatchedUpdateListener l : listeners) { - try { - l.updateConfiguration(result); - } catch (Throwable ex) { - LOGGER.error("Error in invoking WatchedUpdateListener", ex); - } - } - } - - @Override - public Map getCurrentData() throws Exception { - return valueCache; - } - - public List getCurrentListeners() { - return listeners; - } - - public class UpdateHandler { - public void handle(ConfigurationAction action, Map config) { - if (config == null || config.isEmpty()) { - return; - } - Map configuration = ConfigMapping.getConvertedMap(config); - if (CREATE.equals(action)) { - valueCache.putAll(configuration); - - updateConfiguration(createIncremental(ImmutableMap.copyOf(configuration), - null, - null)); - } else if (SET.equals(action)) { - valueCache.putAll(configuration); - - updateConfiguration(createIncremental(null, - ImmutableMap.copyOf(configuration), - null)); - } else if (DELETE.equals(action)) { - configuration.keySet().forEach(valueCache::remove); - updateConfiguration(createIncremental(null, - null, - ImmutableMap.copyOf(configuration))); - } else { - LOGGER.error("action: {} is invalid.", action.name()); - return; - } - LOGGER.warn("Config value cache changed: action:{}; item:{}", action.name(), configuration.keySet()); - } - } -} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ApolloClient.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ApolloClient.java deleted file mode 100644 index 130fc93b7f4..00000000000 --- a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ApolloClient.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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.config.client; - -import static org.apache.servicecomb.config.client.ConfigurationAction.CREATE; -import static org.apache.servicecomb.config.client.ConfigurationAction.DELETE; -import static org.apache.servicecomb.config.client.ConfigurationAction.SET; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.config.archaius.sources.ApolloConfigurationSourceImpl.UpdateHandler; -import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; - -import com.fasterxml.jackson.core.type.TypeReference; - -import io.netty.handler.codec.http.HttpResponseStatus; - -public class ApolloClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(ApolloClient.class); - - private static final ApolloConfig APOLLO_CONFIG = ApolloConfig.INSTANCE; - - private static final Map originalConfigMap = new ConcurrentHashMap<>(); - - private static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(1); - - private final int refreshInterval = APOLLO_CONFIG.getRefreshInterval(); - - private final int firstRefreshInterval = APOLLO_CONFIG.getFirstRefreshInterval(); - - private final String serviceUri = APOLLO_CONFIG.getServerUri(); - - private final String serviceName = APOLLO_CONFIG.getServiceName(); - - private final String token = APOLLO_CONFIG.getToken(); - - private final String env = APOLLO_CONFIG.getEnv(); - - private final String clusters = APOLLO_CONFIG.getServerClusters(); - - private final String namespace = APOLLO_CONFIG.getNamespace(); - - private final UpdateHandler updateHandler; - - private static RestTemplate rest = new RestTemplate(); - - public ApolloClient(UpdateHandler updateHandler) { - this.updateHandler = updateHandler; - } - - public void refreshApolloConfig() { - EXECUTOR - .scheduleWithFixedDelay(new ConfigRefresh(serviceUri), firstRefreshInterval, refreshInterval, TimeUnit.SECONDS); - } - - class ConfigRefresh implements Runnable { - private final String serviceUri; - - ConfigRefresh(String serviceUris) { - this.serviceUri = serviceUris; - } - - @Override - public void run() { - try { - refreshConfig(); - } catch (Throwable e) { - LOGGER.error("client refresh thread exception ", e); - } - } - - @SuppressWarnings("unchecked") - void refreshConfig() { - HttpHeaders headers = new HttpHeaders(); - headers.add("Content-Type", "application/json;charset=UTF-8"); - headers.add("Authorization", token); - HttpEntity entity = new HttpEntity<>(headers); - ResponseEntity exchange = rest.exchange(composeAPI(), HttpMethod.GET, entity, String.class); - if (HttpResponseStatus.OK.code() == exchange.getStatusCode().value()) { - try { - Map body = JsonUtils.OBJ_MAPPER.readValue(exchange.getBody(), - new TypeReference>() { - }); - refreshConfigItems((Map) body.get("configurations")); - } catch (IOException e) { - LOGGER.error("JsonObject parse config center response error: ", e); - } - } else { - LOGGER.error("fetch configuration failed, error code:{} for {}", - exchange.getStatusCodeValue(), - exchange.getBody()); - } - } - - private String composeAPI() { - String api = serviceUri + "/openapi/v1/envs/" + env + - "/apps/" + serviceName + - "/clusters/" + clusters + - "/namespaces/" + namespace + - "/releases/latest"; - return api; - } - - private void refreshConfigItems(Map map) { - compareChangedConfig(originalConfigMap, map); - originalConfigMap.clear(); - originalConfigMap.putAll(map); - } - - void compareChangedConfig(Map before, Map after) { - Map itemsCreated = new HashMap<>(); - Map itemsDeleted = new HashMap<>(); - Map itemsModified = new HashMap<>(); - if (before == null || before.isEmpty()) { - updateHandler.handle(CREATE, after); - return; - } - if (after == null || after.isEmpty()) { - updateHandler.handle(DELETE, before); - return; - } - after.entrySet().forEach(stringObjectEntry -> { - String itemKey = stringObjectEntry.getKey(); - Object itemValue = stringObjectEntry.getValue(); - if (!before.containsKey(itemKey)) { - itemsCreated.put(itemKey, itemValue); - } else if (!itemValue.equals(before.get(itemKey))) { - itemsModified.put(itemKey, itemValue); - } - }); - for (String itemKey : before.keySet()) { - if (!after.containsKey(itemKey)) { - itemsDeleted.put(itemKey, ""); - } - } - updateHandler.handle(CREATE, itemsCreated); - updateHandler.handle(SET, itemsModified); - updateHandler.handle(DELETE, itemsDeleted); - } - } -} - diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ApolloConfig.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ApolloConfig.java deleted file mode 100644 index b8de462e3c6..00000000000 --- a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ApolloConfig.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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.config.client; - -import org.apache.commons.configuration.Configuration; - -public class ApolloConfig { - public static final ApolloConfig INSTANCE = new ApolloConfig(); - - private static Configuration finalConfig; - - private static final String SERVER_URL_KEY = "apollo.config.serverUri"; - - private static final String SERVER_NAMESPACE = "apollo.config.namespace"; - - private static final String SERVER_ENV = "apollo.config.env"; - - private static final String SERVER_CLUSTERS = "apollo.config.clusters"; - - private static final String APOLLO_SERVICE_NAME = "apollo.config.serviceName"; - - private static final String TOKEN = "apollo.config.token"; - - private static final String REFRESH_INTERVAL = "apollo.config.refreshInterval"; - - private static final String FIRST_REFRESH_INTERVAL = "apollo.config.firstRefreshInterval"; - - private static final int DEFAULT_REFRESH_INTERVAL = 3; - - private static final int DEFAULT_FIRST_REFRESH_INTERVAL = 0; - - private ApolloConfig() { - } - - public static void setConcurrentCompositeConfiguration(Configuration config) { - finalConfig = config; - } - - public Configuration getConcurrentCompositeConfiguration() { - return finalConfig; - } - - public String getServiceName() { - return finalConfig.getString(APOLLO_SERVICE_NAME); - } - - public String getServerUri() { - return finalConfig.getString(SERVER_URL_KEY); - } - - public String getToken() { - return finalConfig.getString(TOKEN); - } - - public String getEnv() { - return finalConfig.getString(SERVER_ENV); - } - - public String getNamespace() { - return finalConfig.getString(SERVER_NAMESPACE); - } - - public String getServerClusters() { - return finalConfig.getString(SERVER_CLUSTERS); - } - - public int getRefreshInterval() { - return finalConfig.getInt(REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL); - } - - public int getFirstRefreshInterval() { - return finalConfig.getInt(FIRST_REFRESH_INTERVAL, DEFAULT_FIRST_REFRESH_INTERVAL); - } -} diff --git a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ConfigurationAction.java b/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ConfigurationAction.java deleted file mode 100644 index 5daf1972cfd..00000000000 --- a/dynamic-config/config-apollo/src/main/java/org/apache/servicecomb/config/client/ConfigurationAction.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.config.client; - -public enum ConfigurationAction { - CREATE, - SET, - DELETE -} diff --git a/dynamic-config/config-apollo/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-apollo/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..aa0aae8be0b --- /dev/null +++ b/dynamic-config/config-apollo/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.apollo.ApolloDynamicPropertiesSource diff --git a/dynamic-config/config-apollo/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/dynamic-config/config-apollo/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource deleted file mode 100644 index fa6f9b75892..00000000000 --- a/dynamic-config/config-apollo/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.config.archaius.sources.ApolloConfigurationSourceImpl diff --git a/dynamic-config/config-apollo/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dynamic-config/config-apollo/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..31e45053446 --- /dev/null +++ b/dynamic-config/config-apollo/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.servicecomb.config.apollo.ApolloConfiguration diff --git a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/apollo/ApolloClientTest.java b/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/apollo/ApolloClientTest.java new file mode 100644 index 00000000000..65bc6632c72 --- /dev/null +++ b/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/apollo/ApolloClientTest.java @@ -0,0 +1,107 @@ +/* + * 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.config.apollo; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.config.apollo.ApolloClient.ConfigRefresh; +import org.apache.servicecomb.config.apollo.ApolloDynamicPropertiesSource.UpdateHandler; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +public class ApolloClientTest { + @BeforeAll + public static void setUpClass() { + + } + + @Test + public void refreshApolloConfig() { + ApolloConfig apolloConfig = Mockito.mock(ApolloConfig.class); + RestTemplate rest = Mockito.mock(RestTemplate.class); + ApolloClient.setRest(rest); + + ResponseEntity responseEntity = new ResponseEntity<>( + "{\"apollo\":\"mocked\", \"configurations\":{\"timeout\":1000}}", HttpStatus.OK); + Mockito.when(rest.exchange( + ArgumentMatchers.anyString(), + ArgumentMatchers.any(HttpMethod.class), + ArgumentMatchers.>any(), + ArgumentMatchers.>any())).thenReturn(responseEntity); + ApolloDynamicPropertiesSource impl = new ApolloDynamicPropertiesSource(); + UpdateHandler updateHandler = impl.new UpdateHandler(); + ApolloClient apolloClient = new ApolloClient(updateHandler, apolloConfig); + ConfigRefresh cr = apolloClient.new ConfigRefresh(apolloConfig.getServerUri()); + cr.run(); + + Assertions.assertEquals(1, ApolloClient.getOriginalConfigMap().size()); + } + + @Test + public void testCompareChangedConfig() { + ApolloConfig apolloConfig = Mockito.mock(ApolloConfig.class); + boolean status = true; + Map before = new HashMap<>(); + Map after = new HashMap<>(); + + ApolloDynamicPropertiesSource impl = new ApolloDynamicPropertiesSource(); + UpdateHandler updateHandler = impl.new UpdateHandler(); + ApolloClient apolloClient = new ApolloClient(updateHandler, apolloConfig); + + ConfigRefresh cr = apolloClient.new ConfigRefresh(""); + + try { + cr.compareChangedConfig(before, after); + } catch (Exception e) { + status = false; + } + Assertions.assertTrue(status); + + before.put("test", "testValue"); + try { + cr.compareChangedConfig(before, after); + } catch (Exception e) { + status = false; + } + Assertions.assertTrue(status); + + after.put("test", "testValue2"); + try { + cr.compareChangedConfig(before, after); + } catch (Exception e) { + status = false; + } + Assertions.assertTrue(status); + + try { + cr.compareChangedConfig(before, after); + } catch (Exception e) { + status = false; + } + Assertions.assertTrue(status); + } +} diff --git a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/archaius/sources/ApolloConfigurationSourceImplTest.java b/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/archaius/sources/ApolloConfigurationSourceImplTest.java deleted file mode 100644 index 6c8790d3536..00000000000 --- a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/archaius/sources/ApolloConfigurationSourceImplTest.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.config.archaius.sources; - -import static org.apache.servicecomb.config.client.ConfigurationAction.CREATE; -import static org.apache.servicecomb.config.client.ConfigurationAction.DELETE; -import static org.apache.servicecomb.config.client.ConfigurationAction.SET; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.config.archaius.sources.ApolloConfigurationSourceImpl.UpdateHandler; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.config.WatchedUpdateListener; - -import mockit.Deencapsulation; - -public class ApolloConfigurationSourceImplTest { - @Test - public void testCreate() throws Exception { - - ApolloConfigurationSourceImpl apolloConfigurationSource = new ApolloConfigurationSourceImpl(); - apolloConfigurationSource.addUpdateListener(result -> Assert.assertTrue(!result.getAdded().isEmpty())); - UpdateHandler udateHandler = Deencapsulation.getField(apolloConfigurationSource, UpdateHandler.class); - Map createItems = new HashMap<>(); - createItems.put("testKey", "testValue"); - udateHandler.handle(CREATE, createItems); - } - - @Test - public void testUpdate() throws Exception { - - ApolloConfigurationSourceImpl apolloConfigurationSource = new ApolloConfigurationSourceImpl(); - apolloConfigurationSource.addUpdateListener(result -> Assert.assertTrue(!result.getChanged().isEmpty())); - UpdateHandler udateHandler = Deencapsulation.getField(apolloConfigurationSource, UpdateHandler.class); - Map updateItems = new HashMap<>(); - updateItems.put("testKey", "testValue"); - udateHandler.handle(SET, updateItems); - } - - @Test - public void testDelete() throws Exception { - ApolloConfigurationSourceImpl apolloConfigurationSource = new ApolloConfigurationSourceImpl(); - apolloConfigurationSource.addUpdateListener(result -> Assert.assertTrue(!result.getDeleted().isEmpty())); - UpdateHandler udateHandler = Deencapsulation.getField(apolloConfigurationSource, UpdateHandler.class); - Map deleteItems = new HashMap<>(); - deleteItems.put("testKey", "testValue"); - - apolloConfigurationSource.getCurrentData().put("testKey", "testValue"); - udateHandler.handle(DELETE, deleteItems); - Assert.assertTrue(apolloConfigurationSource.getCurrentData().isEmpty()); - } - - @Test - public void testRemoveUpdateListener() { - ApolloConfigurationSourceImpl apolloConfigurationSource = new ApolloConfigurationSourceImpl(); - WatchedUpdateListener watchedUpdateListener = Mockito.mock(WatchedUpdateListener.class); - apolloConfigurationSource.addUpdateListener(watchedUpdateListener); - apolloConfigurationSource.removeUpdateListener(watchedUpdateListener); - Assert.assertTrue(apolloConfigurationSource.getCurrentListeners().isEmpty()); - } -} diff --git a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/client/ApolloClientTest.java b/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/client/ApolloClientTest.java deleted file mode 100644 index 774356caf1c..00000000000 --- a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/client/ApolloClientTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.config.client; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.config.archaius.sources.ApolloConfigurationSourceImpl; -import org.apache.servicecomb.config.archaius.sources.ApolloConfigurationSourceImpl.UpdateHandler; -import org.apache.servicecomb.config.client.ApolloClient.ConfigRefresh; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mockito.Matchers; -import org.mockito.Mockito; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.client.RestTemplate; - -import mockit.Deencapsulation; - -public class ApolloClientTest { - @BeforeClass - public static void setUpClass() { - - ApolloConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig()); - } - - @Test - public void refreshApolloConfig() { - ApolloConfig apolloConfig = ApolloConfig.INSTANCE; - RestTemplate rest = Mockito.mock(RestTemplate.class); - - ResponseEntity responseEntity = new ResponseEntity<>( - "{\"apollo\":\"mocked\", \"configurations\":{\"timeout\":1000}}", HttpStatus.OK); - Mockito.when(rest.exchange( - Matchers.anyString(), - Matchers.any(HttpMethod.class), - Matchers.>any(), - Matchers.>any())).thenReturn(responseEntity); - ApolloConfigurationSourceImpl impl = new ApolloConfigurationSourceImpl(); - UpdateHandler updateHandler = impl.new UpdateHandler(); - ApolloClient apolloClient = new ApolloClient(updateHandler); - Deencapsulation.setField(apolloClient, "rest", rest); - ConfigRefresh cr = apolloClient.new ConfigRefresh(apolloConfig.getServerUri()); - cr.run(); - - Map originMap = Deencapsulation.getField(apolloClient, "originalConfigMap"); - Assert.assertEquals(1, originMap.size()); - } - - @Test - public void testCompareChangedConfig() { - boolean status = true; - Map before = new HashMap<>(); - Map after = new HashMap<>(); - - ApolloConfigurationSourceImpl impl = new ApolloConfigurationSourceImpl(); - UpdateHandler updateHandler = impl.new UpdateHandler(); - ApolloClient apolloClient = new ApolloClient(updateHandler); - - ConfigRefresh cr = apolloClient.new ConfigRefresh(""); - - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - - status = true; - before.put("test", "testValue"); - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - - status = true; - after.put("test", "testValue2"); - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - - status = true; - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - } -} diff --git a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/client/ApolloConfigTest.java b/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/client/ApolloConfigTest.java deleted file mode 100644 index d96b5d894ec..00000000000 --- a/dynamic-config/config-apollo/src/test/java/org/apache/servicecomb/config/client/ApolloConfigTest.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.config.client; - -import org.apache.servicecomb.config.ConfigUtil; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -public class ApolloConfigTest { - @BeforeClass - public static void setUpClass() { - ApolloConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig()); - } - - @Test - public void getServiceName() { - ApolloConfig instance = ApolloConfig.INSTANCE; - Assert.assertEquals("apollo-test", instance.getServiceName()); - Assert.assertEquals("http://127.0.0.1:8070", instance.getServerUri()); - Assert.assertEquals("DEV", instance.getEnv()); - Assert.assertEquals("test-cluster", instance.getServerClusters()); - Assert.assertEquals("application", instance.getNamespace()); - Assert.assertEquals("xxx", instance.getToken()); - Assert.assertEquals(30, instance.getRefreshInterval()); - Assert.assertEquals(0, instance.getFirstRefreshInterval()); - } -} diff --git a/dynamic-config/config-apollo/src/test/resources/microservice.yaml b/dynamic-config/config-apollo/src/test/resources/microservice.yaml index 3b19383a224..4932794e5d7 100644 --- a/dynamic-config/config-apollo/src/test/resources/microservice.yaml +++ b/dynamic-config/config-apollo/src/test/resources/microservice.yaml @@ -40,12 +40,3 @@ servicecomb: address: 0.0.0.0:8080 highway: address: 0.0.0.0:7070 - handler: - chain: - Provider: - default: bizkeeper-provider - #executors: - #default: test - #Provider: - #server: test - #server.wrapParam: test \ No newline at end of file diff --git a/dynamic-config/config-cc/pom.xml b/dynamic-config/config-cc/pom.xml index e50e7cf760e..0e8f6addcc6 100644 --- a/dynamic-config/config-cc/pom.xml +++ b/dynamic-config/config-cc/pom.xml @@ -21,7 +21,7 @@ dynamic-config org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -33,10 +33,6 @@ org.apache.servicecomb foundation-config - - org.apache.servicecomb - deployment - org.apache.servicecomb foundation-ssl @@ -65,4 +61,4 @@ - \ No newline at end of file + diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java deleted file mode 100644 index 5a4030b47c0..00000000000 --- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfig.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.config; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import org.apache.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.foundation.vertx.VertxConst; - -import com.netflix.config.ConcurrentCompositeConfiguration; - -public final class ConfigCenterConfig { - public static final ConfigCenterConfig INSTANCE = new ConfigCenterConfig(); - - public static final String SSL_TAG = "cc.consumer"; - - private static ConcurrentCompositeConfiguration finalConfig; - - private static final String AUTO_DISCOVERY_ENABLED = "servicecomb.service.registry.autodiscovery"; - - private static final String DOMAIN_NAME = "servicecomb.config.client.domainName"; - - private static final String REFRESH_INTERVAL = "servicecomb.config.client.refresh_interval"; - - private static final String FIRST_REFRESH_INTERVAL = "servicecomb.config.client.first_refresh_interval"; - - private static final String FIRST_PULL_REQUIRED = "servicecomb.config.client.firstPullRequired"; - - public static final String FILE_SOURCE = "servicecomb.config.client.fileSource"; - - private static final int DEFAULT_REFRESH_INTERVAL = 30000; - - private static final int DEFAULT_FIRST_REFRESH_INTERVAL = 0; - - private ConfigCenterConfig() { - } - - public static void setConcurrentCompositeConfiguration(ConcurrentCompositeConfiguration config) { - finalConfig = config; - } - - public static ConcurrentCompositeConfiguration getConcurrentCompositeConfiguration() { - return finalConfig; - } - - - public String getDomainName() { - return finalConfig.getString(DOMAIN_NAME, "default"); - } - - public boolean firstPullRequired() { - return finalConfig.getBoolean(FIRST_PULL_REQUIRED, false); - } - - @SuppressWarnings("unchecked") - public List getFileSources() { - Object property = finalConfig.getProperty(FILE_SOURCE); - if (property instanceof String) { - List result = new ArrayList<>(); - result.add((String) property); - return result; - } - if (property instanceof List) { - return (List) property; - } - return Collections.EMPTY_LIST; - } - - public int getRefreshInterval() { - return finalConfig.getInt(REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL); - } - - public int getFirstRefreshInterval() { - return finalConfig.getInt(FIRST_REFRESH_INTERVAL, DEFAULT_FIRST_REFRESH_INTERVAL); - } - - public Boolean isProxyEnable() { - return finalConfig.getBoolean(VertxConst.PROXY_ENABLE, false); - } - - public String getProxyHost() { - return finalConfig.getString(VertxConst.PROXY_HOST, "127.0.0.1"); - } - - public int getProxyPort() { - return finalConfig.getInt(VertxConst.PROXY_PORT, 8080); - } - - public String getProxyUsername() { - return finalConfig.getString(VertxConst.PROXY_USERNAME, null); - } - - public String getProxyPasswd() { - return finalConfig.getString(VertxConst.PROXY_PASSWD, null); - } - - public String getServiceName() { - return BootStrapProperties.readServiceName(finalConfig); - } - - public String getAppName() { - return BootStrapProperties.readApplication(finalConfig); - } - - public String getServiceVersion() { - return BootStrapProperties.readServiceVersion(finalConfig); - } - - public List getServerUri() { - return Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER) - .getAccessURL(); - } - - public boolean getAutoDiscoveryEnabled() { - return finalConfig.getBoolean(AUTO_DISCOVERY_ENABLED, false); - } - - public String getEnvironment() { - return BootStrapProperties.readServiceEnvironment(finalConfig); - } -} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java deleted file mode 100644 index 91059b80518..00000000000 --- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/ConfigCenterConfigurationSourceImpl.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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.config; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.commons.configuration.Configuration; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.servicecomb.config.center.client.AddressManager; -import org.apache.servicecomb.config.center.client.ConfigCenterClient; -import org.apache.servicecomb.config.center.client.ConfigCenterManager; -import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest; -import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse; -import org.apache.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider; -import org.apache.servicecomb.config.common.ConfigConverter; -import org.apache.servicecomb.config.common.ConfigurationChangedEvent; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; -import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; -import org.apache.servicecomb.http.client.common.HttpTransport; -import org.apache.servicecomb.http.client.common.HttpTransportFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.eventbus.Subscribe; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; - -public class ConfigCenterConfigurationSourceImpl implements ConfigCenterConfigurationSource { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterConfigurationSourceImpl.class); - - private final List listeners = new CopyOnWriteArrayList<>(); - - private ConfigCenterManager configCenterManager; - - private ConfigConverter configConverter; - - @Override - public int getOrder() { - return ORDER_BASE * 2; - } - - @Override - public boolean isValidSource(Configuration localConfiguration) { - ConfigCenterConfig.setConcurrentCompositeConfiguration((ConcurrentCompositeConfiguration) localConfiguration); - SystemBootstrapInfo address = Deployment - .getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER); - - if (address == null) { - LOGGER.info("config center server is not configured."); - return false; - } - return true; - } - - @Override - public void init(Configuration localConfiguration) { - configConverter = new ConfigConverter(ConfigCenterConfig.INSTANCE.getFileSources()); - - AddressManager kieAddressManager = configKieAddressManager(); - - HttpTransport httpTransport = createHttpTransport(kieAddressManager, - HttpTransportFactory.defaultRequestConfig().build(), - localConfiguration); - ConfigCenterClient configCenterClient = new ConfigCenterClient(kieAddressManager, httpTransport); - EventManager.register(this); - - QueryConfigurationsRequest queryConfigurationsRequest = firstPull(configCenterClient); - - configCenterManager = new ConfigCenterManager(configCenterClient, EventManager.getEventBus(), - configConverter); - configCenterManager.setQueryConfigurationsRequest(queryConfigurationsRequest); - configCenterManager.startConfigCenterManager(); - } - - private QueryConfigurationsRequest firstPull(ConfigCenterClient configCenterClient) { - QueryConfigurationsRequest queryConfigurationsRequest = createQueryConfigurationsRequest(); - try { - QueryConfigurationsResponse response = configCenterClient - .queryConfigurations(queryConfigurationsRequest); - if (response.isChanged()) { - configConverter.updateData(response.getConfigurations()); - updateConfiguration(WatchedUpdateResult.createIncremental(configConverter.getCurrentData(), null, null)); - queryConfigurationsRequest.setRevision(response.getRevision()); - } - } catch (Exception e) { - if (ConfigCenterConfig.INSTANCE.firstPullRequired()) { - throw e; - } - LOGGER.warn("first pull failed, and ignore {}", e.getMessage()); - } - return queryConfigurationsRequest; - } - - @Subscribe - public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { - updateConfiguration( - WatchedUpdateResult.createIncremental(event.getAdded(), event.getUpdated(), event.getDeleted())); - } - - private QueryConfigurationsRequest createQueryConfigurationsRequest() { - QueryConfigurationsRequest request = new QueryConfigurationsRequest(); - request.setApplication(ConfigCenterConfig.INSTANCE.getAppName()); - request.setServiceName(ConfigCenterConfig.INSTANCE.getServiceName()); - request.setVersion(ConfigCenterConfig.INSTANCE.getServiceVersion()); - request.setEnvironment(ConfigCenterConfig.INSTANCE.getEnvironment()); - // 需要设置为 null, 并且 query 参数为 revision=null 才会返回 revision 信息。 revision = 是不行的。 - request.setRevision(null); - return request; - } - - private HttpTransport createHttpTransport(AddressManager kieAddressManager, RequestConfig requestConfig, - Configuration localConfiguration) { - List authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class); - - if (ConfigCenterConfig.INSTANCE.isProxyEnable()) { - HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(). - setDefaultRequestConfig(requestConfig); - HttpHost proxy = new HttpHost(ConfigCenterConfig.INSTANCE.getProxyHost(), - ConfigCenterConfig.INSTANCE.getProxyPort(), "http"); // now only support http proxy - httpClientBuilder.setProxy(proxy); - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(proxy), - new UsernamePasswordCredentials(ConfigCenterConfig.INSTANCE.getProxyUsername(), - ConfigCenterConfig.INSTANCE.getProxyPasswd())); - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - - return HttpTransportFactory - .createHttpTransport( - TransportUtils - .createSSLProperties(kieAddressManager.sslEnabled(), localConfiguration, ConfigCenterConfig.SSL_TAG), - getRequestAuthHeaderProvider(authHeaderProviders), httpClientBuilder); - } - - return HttpTransportFactory - .createHttpTransport( - TransportUtils - .createSSLProperties(kieAddressManager.sslEnabled(), localConfiguration, ConfigCenterConfig.SSL_TAG), - getRequestAuthHeaderProvider(authHeaderProviders), requestConfig); - } - - private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List authHeaderProviders) { - return signRequest -> { - Map headers = new HashMap<>(); - authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders())); - return headers; - }; - } - - private AddressManager configKieAddressManager() { - return new AddressManager(ConfigCenterConfig.INSTANCE.getDomainName(), - Deployment - .getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER).getAccessURL()); - } - - private void updateConfiguration(WatchedUpdateResult result) { - LOGGER.info("configuration changed keys, added=[{}], updated=[{}], deleted=[{}]", - result.getAdded() == null ? "" : result.getAdded().keySet(), - result.getChanged() == null ? "" : result.getChanged().keySet(), - result.getDeleted() == null ? "" : result.getDeleted().keySet()); - for (WatchedUpdateListener l : listeners) { - try { - l.updateConfiguration(result); - } catch (Throwable ex) { - LOGGER.error("Error in invoking WatchedUpdateListener", ex); - } - } - } - - @Override - public void destroy() { - if (configCenterManager == null) { - return; - } - configCenterManager.stop(); - } - - @Override - public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.add(watchedUpdateListener); - } - - @Override - public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.remove(watchedUpdateListener); - } - - @Override - public Map getCurrentData() throws Exception { - // data will updated by first pull, set empty to DynamicWatchedConfiguration first. - return Collections.emptyMap(); - } -} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java deleted file mode 100644 index 21a510ac413..00000000000 --- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/TransportUtils.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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.config; - -import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.foundation.ssl.SSLCustom; -import org.apache.servicecomb.foundation.ssl.SSLOption; -import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; - -public class TransportUtils { - public static SSLProperties createSSLProperties(boolean sslEnabled, Configuration configuration, String tag) { - SSLProperties sslProperties = new SSLProperties(); - sslProperties.setEnabled(sslEnabled); - - if (!sslEnabled) { - return sslProperties; - } - - SSLOption option = new SSLOption(); - option.setEngine(getStringProperty(configuration, - DEFAULT_OPTION.getEngine(), - "ssl." + tag + ".engine", - "ssl.engine")); - option.setProtocols( - getStringProperty(configuration, - DEFAULT_OPTION.getProtocols(), - "ssl." + tag + ".protocols", - "ssl.protocols")); - option.setCiphers( - getStringProperty(configuration, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers")); - option.setAuthPeer( - getBooleanProperty(configuration, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer")); - option.setCheckCNHost( - getBooleanProperty(configuration, - DEFAULT_OPTION.isCheckCNHost(), - "ssl." + tag + ".checkCN.host", - "ssl.checkCN.host")); - option.setCheckCNWhite( - getBooleanProperty(configuration, - DEFAULT_OPTION.isCheckCNWhite(), - "ssl." + tag + ".checkCN.white", - "ssl.checkCN.white")); - option.setCheckCNWhiteFile(getStringProperty(configuration, - DEFAULT_OPTION.getCiphers(), - "ssl." + tag + ".checkCN.white.file", - "ssl.checkCN.white.file")); - option.setAllowRenegociate(getBooleanProperty(configuration, - DEFAULT_OPTION.isAllowRenegociate(), - "ssl." + tag + ".allowRenegociate", - "ssl.allowRenegociate")); - option.setStorePath( - getStringProperty(configuration, - DEFAULT_OPTION.getStorePath(), - "ssl." + tag + ".storePath", - "ssl.storePath")); - option.setClientAuth( - getStringProperty(configuration, - DEFAULT_OPTION.getClientAuth(), - "ssl." + tag + ".clientAuth", - "ssl.clientAuth")); - option.setTrustStore( - getStringProperty(configuration, - DEFAULT_OPTION.getTrustStore(), - "ssl." + tag + ".trustStore", - "ssl.trustStore")); - option.setTrustStoreType(getStringProperty(configuration, - DEFAULT_OPTION.getTrustStoreType(), - "ssl." + tag + ".trustStoreType", - "ssl.trustStoreType")); - option.setTrustStoreValue(getStringProperty(configuration, - DEFAULT_OPTION.getTrustStoreValue(), - "ssl." + tag + ".trustStoreValue", - "ssl.trustStoreValue")); - option.setKeyStore( - getStringProperty(configuration, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore")); - option.setKeyStoreType( - getStringProperty(configuration, - DEFAULT_OPTION.getKeyStoreType(), - "ssl." + tag + ".keyStoreType", - "ssl.keyStoreType")); - option.setKeyStoreValue(getStringProperty(configuration, - DEFAULT_OPTION.getKeyStoreValue(), - "ssl." + tag + ".keyStoreValue", - "ssl.keyStoreValue")); - option.setCrl(getStringProperty(configuration, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl")); - option.setSslCustomClass( - getStringProperty(configuration, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass")); - - sslProperties.setSslOption(option); - sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass())); - return sslProperties; - } - - private static String getStringProperty(Configuration configuration, String defaultValue, String... keys) { - for (String key : keys) { - if (configuration.containsKey(key)) { - return configuration.getString(key); - } - } - return defaultValue; - } - - private static boolean getBooleanProperty(Configuration configuration, boolean defaultValue, String... keys) { - for (String key : keys) { - if (configuration.containsKey(key)) { - return configuration.getBoolean(key); - } - } - return defaultValue; - } -} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterConfig.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterConfig.java new file mode 100644 index 00000000000..c1cf7c1b683 --- /dev/null +++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterConfig.java @@ -0,0 +1,107 @@ +/* + * 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.config.cc; + +import java.util.Collections; +import java.util.List; + +import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.foundation.vertx.VertxConst; +import org.springframework.core.env.Environment; + +public final class ConfigCenterConfig { + public static final String SSL_TAG = "cc.consumer"; + + private static final String ADDRESS = "servicecomb.config.client.serverUri"; + + private static final String DOMAIN_NAME = "servicecomb.config.client.domainName"; + + private static final String REFRESH_INTERVAL = "servicecomb.config.client.refresh_interval"; + + private static final String FIRST_PULL_REQUIRED = "servicecomb.config.client.firstPullRequired"; + + public static final String FILE_SOURCE = "servicecomb.config.client.fileSource"; + + private static final int DEFAULT_REFRESH_INTERVAL = 15000; + + private static final String CLIENT_CONNECT_TIMEOUT = "servicecomb.config.client.timeout.connect"; + + private static final String CLIENT_REQUEST_TIMEOUT = "servicecomb.config.client.timeout.request"; + + private static final String CLIENT_SOCKET_TIMEOUT = "servicecomb.config.client.timeout.socket"; + + private final Environment environment; + + public ConfigCenterConfig(Environment environment) { + this.environment = environment; + } + + public String getDomainName() { + return environment.getProperty(DOMAIN_NAME, "default"); + } + + public boolean firstPullRequired() { + return environment.getProperty(FIRST_PULL_REQUIRED, boolean.class, false); + } + + @SuppressWarnings("unchecked") + public List getFileSources() { + return environment.getProperty(FILE_SOURCE, List.class, Collections.emptyList()); + } + + public long getRefreshInterval() { + return environment.getProperty( + REFRESH_INTERVAL, long.class, (long) DEFAULT_REFRESH_INTERVAL); + } + + public Boolean isProxyEnable() { + return environment.getProperty(VertxConst.PROXY_ENABLE, boolean.class, false); + } + + public String getProxyHost() { + return environment.getProperty(VertxConst.PROXY_HOST, "127.0.0.1"); + } + + public int getProxyPort() { + return environment.getProperty(VertxConst.PROXY_PORT, int.class, 8080); + } + + public String getProxyUsername() { + return environment.getProperty(VertxConst.PROXY_USERNAME); + } + + public String getProxyPasswd() { + return environment.getProperty(VertxConst.PROXY_PASSWD); + } + + public List getServerUri() { + return ConfigUtil.parseArrayValue(environment.getProperty(ADDRESS, "")); + } + + public int getConnectTimeout() { + return environment.getProperty(CLIENT_CONNECT_TIMEOUT, int.class, 5000); + } + + public int getConnectionRequestTimeout() { + return environment.getProperty(CLIENT_REQUEST_TIMEOUT, int.class, 5000); + } + + public int getSocketTimeout() { + return environment.getProperty(CLIENT_SOCKET_TIMEOUT, int.class, 5000); + } +} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterConfiguration.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterConfiguration.java new file mode 100644 index 00000000000..672a5931faf --- /dev/null +++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterConfiguration.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.config.cc; + +import org.springframework.context.annotation.Bean; + +public class ConfigCenterConfiguration { + @Bean + public ConfigCenterInformationCollector configCenterInformationCollector() { + return new ConfigCenterInformationCollector(); + } +} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterDynamicPropertiesSource.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterDynamicPropertiesSource.java new file mode 100644 index 00000000000..23c0a7af196 --- /dev/null +++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterDynamicPropertiesSource.java @@ -0,0 +1,203 @@ +/* + * 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.config.cc; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.apache.servicecomb.config.center.client.ConfigCenterAddressManager; +import org.apache.servicecomb.config.center.client.ConfigCenterClient; +import org.apache.servicecomb.config.center.client.ConfigCenterConfigurationChangedEvent; +import org.apache.servicecomb.config.center.client.ConfigCenterManager; +import org.apache.servicecomb.config.center.client.model.ConfigCenterConfiguration; +import org.apache.servicecomb.config.center.client.model.QueryConfigurationsRequest; +import org.apache.servicecomb.config.center.client.model.QueryConfigurationsResponse; +import org.apache.servicecomb.config.common.ConfigConverter; +import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; +import org.apache.servicecomb.http.client.common.HttpTransport; +import org.apache.servicecomb.http.client.common.HttpTransportFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import com.google.common.eventbus.Subscribe; + +public class ConfigCenterDynamicPropertiesSource implements DynamicPropertiesSource { + public static final String SOURCE_NAME = "config-center"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterDynamicPropertiesSource.class); + + private final Map data = new ConcurrentHashMapEx<>(); + + private ConfigConverter configConverter; + + public ConfigCenterDynamicPropertiesSource() { + } + + private void init(Environment environment) { + ConfigCenterConfig configCenterConfig = new ConfigCenterConfig(environment); + configConverter = new ConfigConverter(configCenterConfig.getFileSources()); + + ConfigCenterAddressManager configCenterAddressManager = configCenterAddressManager(configCenterConfig, environment); + + HttpTransport httpTransport = createHttpTransport(configCenterAddressManager, + buildRequestConfig(configCenterConfig), environment, configCenterConfig); + ConfigCenterClient configCenterClient = new ConfigCenterClient(configCenterAddressManager, httpTransport); + EventManager.register(this); + + ConfigCenterConfiguration configCenterConfiguration = + createConfigCenterConfiguration(configCenterConfig); + + QueryConfigurationsRequest queryConfigurationsRequest = firstPull(configCenterConfig, configCenterClient, + environment, configCenterAddressManager); + + ConfigCenterManager configCenterManager = new ConfigCenterManager(configCenterClient, EventManager.getEventBus(), + configConverter, configCenterConfiguration, configCenterAddressManager); + configCenterManager.setQueryConfigurationsRequest(queryConfigurationsRequest); + configCenterManager.startConfigCenterManager(); + data.putAll(configConverter.getCurrentData()); + } + + private RequestConfig buildRequestConfig(ConfigCenterConfig config) { + RequestConfig.Builder builder = HttpTransportFactory.defaultRequestConfig(); + builder.setConnectTimeout(config.getConnectTimeout()); + builder.setConnectionRequestTimeout(config.getConnectionRequestTimeout()); + builder.setSocketTimeout(config.getSocketTimeout()); + return builder.build(); + } + + private QueryConfigurationsRequest firstPull(ConfigCenterConfig configCenterConfig, + ConfigCenterClient configCenterClient, Environment environment, + ConfigCenterAddressManager configCenterAddressManager) { + QueryConfigurationsRequest queryConfigurationsRequest = createQueryConfigurationsRequest(environment); + try { + QueryConfigurationsResponse response = configCenterClient + .queryConfigurations(queryConfigurationsRequest, configCenterAddressManager.address()); + if (response.isChanged()) { + configConverter.updateData(response.getConfigurations()); + queryConfigurationsRequest.setRevision(response.getRevision()); + } + } catch (Exception e) { + if (configCenterConfig.firstPullRequired()) { + throw e; + } + LOGGER.warn("first pull failed, and ignore {}", e.getMessage()); + } + return queryConfigurationsRequest; + } + + @Subscribe + public void onConfigurationChangedEvent(ConfigCenterConfigurationChangedEvent event) { + LOGGER.info("Dynamic configuration changed: {}", event.getChanged()); + data.putAll(event.getAdded()); + data.putAll(event.getUpdated()); + event.getDeleted().forEach((k, v) -> data.remove(k)); + EventManager.post(ConfigurationChangedEvent.createIncremental(event.getAdded(), + event.getUpdated(), event.getDeleted())); + } + + private QueryConfigurationsRequest createQueryConfigurationsRequest(Environment environment) { + QueryConfigurationsRequest request = new QueryConfigurationsRequest(); + request.setApplication(BootStrapProperties.readApplication(environment)); + request.setServiceName(BootStrapProperties.readServiceName(environment)); + request.setVersion(BootStrapProperties.readServiceVersion(environment)); + request.setEnvironment(BootStrapProperties.readServiceEnvironment(environment)); + // 需要设置为 null, 并且 query 参数为 revision=null 才会返回 revision 信息。 revision = 是不行的。 + request.setRevision(null); + return request; + } + + private ConfigCenterConfiguration createConfigCenterConfiguration( + ConfigCenterConfig configCenterConfig) { + return new ConfigCenterConfiguration().setRefreshIntervalInMillis(configCenterConfig.getRefreshInterval()); + } + + private HttpTransport createHttpTransport(ConfigCenterAddressManager configCenterAddressManager, + RequestConfig requestConfig, + Environment environment, ConfigCenterConfig configCenterConfig) { + List authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class); + + if (configCenterConfig.isProxyEnable()) { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(). + setDefaultRequestConfig(requestConfig); + HttpHost proxy = new HttpHost(configCenterConfig.getProxyHost(), + configCenterConfig.getProxyPort(), "http"); // now only support http proxy + httpClientBuilder.setProxy(proxy); + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(proxy), + new UsernamePasswordCredentials(configCenterConfig.getProxyUsername(), + configCenterConfig.getProxyPasswd())); + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + + return HttpTransportFactory + .createHttpTransport( + TransportUtils + .createSSLProperties(configCenterAddressManager.sslEnabled(), environment, ConfigCenterConfig.SSL_TAG), + getRequestAuthHeaderProvider(authHeaderProviders), httpClientBuilder); + } + + return HttpTransportFactory + .createHttpTransport( + TransportUtils + .createSSLProperties(configCenterAddressManager.sslEnabled(), environment, ConfigCenterConfig.SSL_TAG), + getRequestAuthHeaderProvider(authHeaderProviders), requestConfig); + } + + private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List authHeaderProviders) { + return signRequest -> { + String host = signRequest != null && signRequest.getEndpoint() != null ? signRequest.getEndpoint().getHost() : ""; + Map headers = new HashMap<>(); + authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders(host))); + return headers; + }; + } + + private ConfigCenterAddressManager configCenterAddressManager(ConfigCenterConfig configCenterConfig, Environment environment) { + String region = environment.getProperty("servicecomb.datacenter.region"); + String availableZone = environment.getProperty("servicecomb.datacenter.availableZone"); + return new ConfigCenterAddressManager(configCenterConfig.getDomainName(), + configCenterConfig.getServerUri(), EventManager.getEventBus(), region, availableZone); + } + + @Override + public PropertySource create(Environment environment) { + init(environment); + return new MapPropertySource(SOURCE_NAME, data); + } + + @Override + public int getOrder() { + return 200; + } +} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterInformationCollector.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterInformationCollector.java new file mode 100644 index 00000000000..ab91f368013 --- /dev/null +++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/ConfigCenterInformationCollector.java @@ -0,0 +1,43 @@ +/* + * 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.config.cc; + +import org.apache.servicecomb.core.bootup.BootUpInformationCollector; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.lang.NonNull; + + +public class ConfigCenterInformationCollector implements BootUpInformationCollector, EnvironmentAware { + private ConfigCenterConfig configCenterConfig; + + @Override + public void setEnvironment(@NonNull Environment environment) { + this.configCenterConfig = new ConfigCenterConfig(environment); + } + + @Override + public String collect() { + return "Config Center: " + configCenterConfig.getServerUri(); + } + + @Override + public int getOrder() { + return 1; + } +} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/TransportUtils.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/TransportUtils.java new file mode 100644 index 00000000000..25a4dac0543 --- /dev/null +++ b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/cc/TransportUtils.java @@ -0,0 +1,128 @@ +/* + * 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.config.cc; + +import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION; + +import org.apache.servicecomb.foundation.ssl.SSLCustom; +import org.apache.servicecomb.foundation.ssl.SSLOption; +import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; +import org.springframework.core.env.Environment; + +public class TransportUtils { + public static SSLProperties createSSLProperties(boolean sslEnabled, Environment environment, String tag) { + SSLProperties sslProperties = new SSLProperties(); + sslProperties.setEnabled(sslEnabled); + + if (!sslEnabled) { + return sslProperties; + } + + SSLOption option = new SSLOption(); + option.setEngine(getStringProperty(environment, + DEFAULT_OPTION.getEngine(), + "ssl." + tag + ".engine", + "ssl.engine")); + option.setProtocols( + getStringProperty(environment, + DEFAULT_OPTION.getProtocols(), + "ssl." + tag + ".protocols", + "ssl.protocols")); + option.setCiphers( + getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers")); + option.setAuthPeer( + getBooleanProperty(environment, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer")); + option.setCheckCNHost( + getBooleanProperty(environment, + DEFAULT_OPTION.isCheckCNHost(), + "ssl." + tag + ".checkCN.host", + "ssl.checkCN.host")); + option.setCheckCNWhite( + getBooleanProperty(environment, + DEFAULT_OPTION.isCheckCNWhite(), + "ssl." + tag + ".checkCN.white", + "ssl.checkCN.white")); + option.setCheckCNWhiteFile(getStringProperty(environment, + DEFAULT_OPTION.getCiphers(), + "ssl." + tag + ".checkCN.white.file", + "ssl.checkCN.white.file")); + option.setAllowRenegotiate(getBooleanProperty(environment, + DEFAULT_OPTION.isAllowRenegotiate(), + "ssl." + tag + ".allowRenegotiate", + "ssl.allowRenegotiate")); + option.setStorePath( + getStringProperty(environment, + DEFAULT_OPTION.getStorePath(), + "ssl." + tag + ".storePath", + "ssl.storePath")); + option.setClientAuth( + getStringProperty(environment, + DEFAULT_OPTION.getClientAuth(), + "ssl." + tag + ".clientAuth", + "ssl.clientAuth")); + option.setTrustStore( + getStringProperty(environment, + DEFAULT_OPTION.getTrustStore(), + "ssl." + tag + ".trustStore", + "ssl.trustStore")); + option.setTrustStoreType(getStringProperty(environment, + DEFAULT_OPTION.getTrustStoreType(), + "ssl." + tag + ".trustStoreType", + "ssl.trustStoreType")); + option.setTrustStoreValue(getStringProperty(environment, + DEFAULT_OPTION.getTrustStoreValue(), + "ssl." + tag + ".trustStoreValue", + "ssl.trustStoreValue")); + option.setKeyStore( + getStringProperty(environment, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore")); + option.setKeyStoreType( + getStringProperty(environment, + DEFAULT_OPTION.getKeyStoreType(), + "ssl." + tag + ".keyStoreType", + "ssl.keyStoreType")); + option.setKeyStoreValue(getStringProperty(environment, + DEFAULT_OPTION.getKeyStoreValue(), + "ssl." + tag + ".keyStoreValue", + "ssl.keyStoreValue")); + option.setCrl(getStringProperty(environment, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl")); + option.setSslCustomClass( + getStringProperty(environment, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass")); + + sslProperties.setSslOption(option); + sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass())); + return sslProperties; + } + + private static String getStringProperty(Environment environment, String defaultValue, String... keys) { + for (String key : keys) { + if (environment.getProperty(key) != null) { + return environment.getProperty(key); + } + } + return defaultValue; + } + + private static boolean getBooleanProperty(Environment environment, boolean defaultValue, String... keys) { + for (String key : keys) { + if (environment.getProperty(key) != null) { + return environment.getProperty(key, boolean.class, false); + } + } + return defaultValue; + } +} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/collect/ConfigCenterDefaultDeploymentProvider.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/collect/ConfigCenterDefaultDeploymentProvider.java deleted file mode 100644 index 287f1ac7f36..00000000000 --- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/collect/ConfigCenterDefaultDeploymentProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.config.collect; - -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.lang3.ArrayUtils; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.deployment.DeploymentProvider; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; - -import com.google.common.annotations.VisibleForTesting; - -public class ConfigCenterDefaultDeploymentProvider implements DeploymentProvider { - public static final String SYSTEM_KEY_CONFIG_CENTER = "ConfigCenter"; - - private static AbstractConfiguration configuration = ConfigUtil.createLocalConfig(); - - @Override - public SystemBootstrapInfo getSystemBootStrapInfo(String systemKey) { - if (!systemKey.equals(SYSTEM_KEY_CONFIG_CENTER)) { - return null; - } - List ccAddresses = ConfigUtil - .parseArrayValue(configuration.getString("servicecomb.config.client.serverUri")); - if (ccAddresses.isEmpty()) { - return null; - } - SystemBootstrapInfo cc = new SystemBootstrapInfo(); - cc.setAccessURL(ccAddresses); - return cc; - } - - @VisibleForTesting - public static void setConfiguration(AbstractConfiguration configuration) { - ConfigCenterDefaultDeploymentProvider.configuration = configuration; - } -} diff --git a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/collect/ConfigCenterInformationCollector.java b/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/collect/ConfigCenterInformationCollector.java deleted file mode 100644 index 89568debc29..00000000000 --- a/dynamic-config/config-cc/src/main/java/org/apache/servicecomb/config/collect/ConfigCenterInformationCollector.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.config.collect; - -import org.apache.servicecomb.core.bootup.BootUpInformationCollector; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; - -import java.util.Objects; - - -public class ConfigCenterInformationCollector implements BootUpInformationCollector { - @Override - public String collect() { - return "Config Center: " + getCenterInfo(Deployment.getSystemBootStrapInfo("ConfigCenter")); - } - - @Override - public int getOrder() { - return 1; - } - - private String getCenterInfo(SystemBootstrapInfo systemBootstrapInfo) { - return Objects.isNull(systemBootstrapInfo) ? "not exist" : systemBootstrapInfo.getAccessURL().toString(); - } -} diff --git a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..94d24b08be8 --- /dev/null +++ b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.cc.ConfigCenterDynamicPropertiesSource diff --git a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource deleted file mode 100644 index d38ec076ab0..00000000000 --- a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.config.ConfigCenterConfigurationSourceImpl \ No newline at end of file diff --git a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector index 58062576e91..9b7c91cf3d9 100644 --- a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector +++ b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -org.apache.servicecomb.config.collect.ConfigCenterInformationCollector \ No newline at end of file +org.apache.servicecomb.config.cc.ConfigCenterInformationCollector diff --git a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider b/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider deleted file mode 100644 index 39efa46f702..00000000000 --- a/dynamic-config/config-cc/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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.servicecomb.config.collect.ConfigCenterDefaultDeploymentProvider \ No newline at end of file diff --git a/dynamic-config/config-cc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dynamic-config/config-cc/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..febb8943865 --- /dev/null +++ b/dynamic-config/config-cc/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.servicecomb.config.cc.ConfigCenterConfiguration diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/cc/ConfigCenterAddressManagerTest.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/cc/ConfigCenterAddressManagerTest.java new file mode 100644 index 00000000000..50d39bc19db --- /dev/null +++ b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/cc/ConfigCenterAddressManagerTest.java @@ -0,0 +1,86 @@ +/* + * 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.config.cc; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.config.center.client.ConfigCenterAddressManager; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import com.google.common.eventbus.EventBus; + +class ConfigCenterAddressManagerTest { + private static final List addresses = new ArrayList<>(); + + private static ConfigCenterAddressManager addressManager1; + + private static ConfigCenterAddressManager addressManager2; + + @Test + public void addressManagerTest() throws NoSuchFieldException, IllegalAccessException { + addresses.add("http://127.0.0.1:30103"); + addresses.add("https://127.0.0.2:30103"); + addressManager1 = new ConfigCenterAddressManager("project", addresses, new EventBus(), "", ""); + addressManager2 = new ConfigCenterAddressManager(null, addresses, new EventBus(), "", ""); + Field addressManagerField = addressManager1.getClass().getSuperclass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager1, 0); + addressManagerField = addressManager2.getClass().getSuperclass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager2, 0); + + Assertions.assertNotNull(addressManager1); + Assertions.assertNotNull(addressManager2); + + List addresses = addressManager1.getAddresses(); + Assertions.assertEquals(2, addresses.size()); + Assertions.assertEquals("http://127.0.0.1:30103/v3/project", addresses.get(0)); + + Assertions.assertEquals("https://127.0.0.2:30103/v3/project", addressManager1.address()); + Assertions.assertEquals("http://127.0.0.1:30103/v3/project", addressManager1.address()); + Assertions.assertEquals("https://127.0.0.2:30103/v3/default", addressManager2.address()); + } + + @Test + public void onRefreshEndpointEvent() { + List addressAZ = new ArrayList<>(); + addressAZ.add("http://127.0.0.3:30100"); + List addressRG = new ArrayList<>(); + addressRG.add("http://127.0.0.4:30100"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", addressRG); + addressManager1 = new ConfigCenterAddressManager("project", addresses, new EventBus(), "", ""); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "CseConfigCenter"); + addressManager1.refreshEndpoint(event, "CseConfigCenter"); + + List availableZone = addressManager1.getAvailableZone(); + Assertions.assertEquals("http://127.0.0.3:30100/v3/project", availableZone.get(0)); + + List availableRegion = addressManager1.getAvailableRegion(); + Assertions.assertEquals("http://127.0.0.4:30100/v3/project", availableRegion.get(0)); + + Assertions.assertEquals("http://127.0.0.3:30100/v3/project", addressManager1.address()); + } +} diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/cc/ConfigCenterConfigurationSourceImplTest.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/cc/ConfigCenterConfigurationSourceImplTest.java new file mode 100644 index 00000000000..3298d95bb19 --- /dev/null +++ b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/cc/ConfigCenterConfigurationSourceImplTest.java @@ -0,0 +1,76 @@ +/* + * 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.config.cc; + + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.config.center.client.ConfigCenterAddressManager; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.http.client.event.RefreshEndpointEvent; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +class ConfigCenterConfigurationSourceImplTest { + @Test + void configAddressManagerTest() throws IllegalAccessException, NoSuchFieldException { + List addresses = new ArrayList<>(); + addresses.add("http://127.0.0.1:30103"); + addresses.add("http://127.0.0.2:30103"); + ConfigCenterAddressManager addressManager = new ConfigCenterAddressManager("test", addresses, + EventManager.getEventBus(), "", ""); + Field addressManagerField = addressManager.getClass().getSuperclass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager, 0); + Assertions.assertNotNull(addressManager); + + String address = addressManager.address(); + Assertions.assertEquals("http://127.0.0.2:30103/v3/test", address); + address = addressManager.address(); + Assertions.assertEquals("http://127.0.0.1:30103/v3/test", address); + + addressManager = new ConfigCenterAddressManager(null, addresses, EventManager.getEventBus(), "", ""); + addressManagerField = addressManager.getClass().getSuperclass().getDeclaredField("index"); + addressManagerField.setAccessible(true); + addressManagerField.set(addressManager, 0); + address = addressManager.address(); + Assertions.assertEquals("http://127.0.0.2:30103/v3/default", address); + } + + @Test + void onRefreshEndpointEventTest() { + List addresses = new ArrayList<>(); + addresses.add("http://127.0.0.1:30103"); + List addressAZ = new ArrayList<>(); + addressAZ.add("rest://127.0.0.1:30100?sslEnabled=true"); + Map> zoneAndRegion = new HashMap<>(); + zoneAndRegion.put("sameZone", addressAZ); + zoneAndRegion.put("sameRegion", new ArrayList<>()); + RefreshEndpointEvent event = new RefreshEndpointEvent(zoneAndRegion, "CseConfigCenter"); + ConfigCenterAddressManager addressManager = new ConfigCenterAddressManager("test", addresses, + EventManager.getEventBus(), "", ""); + addressManager.onRefreshEndpointEvent(event); + + List availableAZ = addressManager.getAvailableZone(); + Assertions.assertEquals("https://127.0.0.1:30100/v3/test", availableAZ.get(0)); + } +} diff --git a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvider.java b/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvider.java deleted file mode 100644 index 597c31f3d0b..00000000000 --- a/dynamic-config/config-cc/src/test/java/org/apache/servicecomb/config/collect/TestConfigCenterDefaultDeploymentProvider.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.config.collect; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestConfigCenterDefaultDeploymentProvider { - @Before - public void start() { - ArchaiusUtils.resetConfig(); - } - - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testConfiguration() { - ConfigCenterDefaultDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER); - Assert.assertEquals(info.getAccessURL().get(0), "https://172.16.8.7:30103"); - Assert.assertNull(Deployment.getSystemBootStrapInfo("wrong")); - } - - @Test - public void testConfigurationEnv() { - System.setProperty("servicecomb.config.client.serverUri", "https://localhost:9988"); - ConfigCenterDefaultDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER); - Assert.assertEquals(info.getAccessURL().get(0), "https://localhost:9988"); - System.getProperties().remove("servicecomb.config.client.serverUri"); - } - - @Test - public void testConfigurationEnvTwo() { - System.setProperty("servicecomb.config.client.serverUri", "https://localhost:9988,https://localhost:9987"); - ConfigCenterDefaultDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(ConfigCenterDefaultDeploymentProvider.SYSTEM_KEY_CONFIG_CENTER); - Assert.assertEquals(info.getAccessURL().size(), 2); - Assert.assertEquals(info.getAccessURL().get(0), "https://localhost:9988"); - Assert.assertEquals(info.getAccessURL().get(1), "https://localhost:9987"); - System.getProperties().remove("servicecomb.config.client.serverUri"); - } -} diff --git a/dynamic-config/config-consul/pom.xml b/dynamic-config/config-consul/pom.xml new file mode 100644 index 00000000000..af890c0e6ec --- /dev/null +++ b/dynamic-config/config-consul/pom.xml @@ -0,0 +1,54 @@ + + + + + 4.0.0 + + org.apache.servicecomb + dynamic-config + 3.4.0-SNAPSHOT + + + config-consul + Java Chassis::Dynamic Config::Consul + + + + org.apache.servicecomb + foundation-common + + + org.apache.servicecomb + foundation-registry + + + org.apache.servicecomb + java-chassis-core + + + org.kiwiproject + consul-client + + + com.google.code.gson + gson + + + diff --git a/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfig.java b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfig.java new file mode 100644 index 00000000000..57613037eb4 --- /dev/null +++ b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfig.java @@ -0,0 +1,79 @@ +/* + * 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.config.consul; + +import org.springframework.core.env.Environment; + +public class ConsulConfig { + + public static final String CONSUL_CONFIG_PREFIX = "servicecomb.config.consul"; + + public static final String CONSUL_DEFAULT_ENVIRONMENT = "production"; + + public static final String PROPERTY_CONSUL_HOST = "servicecomb.config.consul.host"; + + public static final String PROPERTY_CONSUL_PORT = "servicecomb.config.consul.port"; + + public static final String PROPERTY_CONSUL_SCHEME = "servicecomb.config.consul.scheme"; + + public static final String PROPERTY_CONSUL_ACL_TOKEN = "servicecomb.config.consul.acl-token"; + + public static final String PROPERTY_CONSUL_WATCH_SECONDS = "servicecomb.config.consul.watch-seconds"; + + public static final String PROPERTY_INSTANCE_TAG = "servicecomb.config.consul.instance-tag"; + + public static final String PATH_ENVIRONMENT = "/servicecomb/config/environment/%s"; + + public static final String PATH_APPLICATION = "/servicecomb/config/application/%s/%s"; + + public static final String PATH_SERVICE = "/servicecomb/config/service/%s/%s/%s"; + + public static final String PATH_VERSION = "/servicecomb/config/version/%s/%s/%s/%s"; + + public static final String PATH_TAG = "/servicecomb/config/tag/%s/%s/%s/%s/%s"; + + private final Environment environment; + + public ConsulConfig(Environment environment) { + this.environment = environment; + } + + public String getConsulHost() { + return environment.getProperty(PROPERTY_CONSUL_HOST, String.class, "127.0.0.1"); + } + + public int getConsulPort() { + return environment.getProperty(PROPERTY_CONSUL_PORT, int.class, 8500); + } + + public String getConsulScheme() { + return environment.getProperty(PROPERTY_CONSUL_SCHEME); + } + + public String getConsulAclToken() { + return environment.getProperty(PROPERTY_CONSUL_ACL_TOKEN); + } + + public int getConsulWatchSeconds() { + return environment.getProperty(PROPERTY_CONSUL_WATCH_SECONDS, int.class, 8); + } + + public String getInstanceTag() { + return environment.getProperty(PROPERTY_INSTANCE_TAG); + } +} diff --git a/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfigClient.java b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfigClient.java new file mode 100644 index 00000000000..ae18e11ff48 --- /dev/null +++ b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfigClient.java @@ -0,0 +1,305 @@ +/* + * 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.config.consul; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.BootStrapProperties; +import org.jetbrains.annotations.NotNull; +import org.kiwiproject.consul.Consul; +import org.kiwiproject.consul.KeyValueClient; +import org.kiwiproject.consul.cache.KVCache; +import org.kiwiproject.consul.model.kv.Value; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ByteArrayResource; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Properties; + +import static org.apache.servicecomb.config.consul.ConsulConfig.PATH_APPLICATION; +import static org.apache.servicecomb.config.consul.ConsulConfig.PATH_ENVIRONMENT; +import static org.apache.servicecomb.config.consul.ConsulConfig.PATH_SERVICE; +import static org.apache.servicecomb.config.consul.ConsulConfig.PATH_TAG; +import static org.apache.servicecomb.config.consul.ConsulConfig.PATH_VERSION; + +public class ConsulConfigClient { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulConfigClient.class); + + public class GetDataRunnable implements Runnable { + + private Map dataMap; + + private String path; + + public GetDataRunnable(String path, Map dataMap) { + this.dataMap = dataMap; + this.path = path; + } + + @Override + public void run() { + try { + if (path.equals("tagData")) { + tagData = dataMap; + } else if (path.equals("versionData")) { + versionData = dataMap; + } else if (path.equals("serviceData")) { + serviceData = dataMap; + } else if (path.equals("applicationData")) { + applicationData = dataMap; + } else { + environmentData = dataMap; + } + refreshConfigItems(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + private ConsulDynamicPropertiesSource.UpdateHandler updateHandler; + + private ConsulConfig consulConfig; + + private Environment environment; + + private final Object lock = new Object(); + + private Consul consulClient; + + private KeyValueClient kvClient; + + private ConsulConfigProperties consulConfigProperties; + + private Map environmentData = new HashMap<>(); + + private Map applicationData = new HashMap<>(); + + private Map serviceData = new HashMap<>(); + + private Map versionData = new HashMap<>(); + + private Map tagData = new HashMap<>(); + + private Map allLast = new HashMap<>(); + + public ConsulConfigClient(ConsulDynamicPropertiesSource.UpdateHandler updateHandler, Environment environment, ConsulConfigProperties consulConfigProperties, Consul consulClient) { + this.updateHandler = updateHandler; + this.consulConfig = new ConsulConfig(environment); + this.environment = environment; + this.consulConfigProperties = consulConfigProperties; + this.consulClient = consulClient; + this.kvClient = consulClient.keyValueClient(); + } + + public void refreshConsulConfig() { + String env = BootStrapProperties.readServiceEnvironment(environment); + if (StringUtils.isEmpty(env)) { + env = ConsulConfig.CONSUL_DEFAULT_ENVIRONMENT; + } + addEnvironmentConfig(env); + addApplicationConfig(env); + addServiceConfig(env); + addVersionConfig(env); + addTagConfig(env); + + refreshConfigItems(); + } + + private void addTagConfig(String env) { + if (StringUtils.isBlank(consulConfig.getInstanceTag())) { + return; + } + String path = String.format(PATH_TAG, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment), + consulConfig.getInstanceTag()); + + this.tagData = parseData(path); + try (KVCache cache = KVCache.newCache(kvClient, path, consulConfig.getConsulWatchSeconds())) { + cache.addListener(newValues -> { + Optional newValue = newValues.values().stream() + .filter(value -> value.getKey().equals(path)) + .findAny(); + + newValue.ifPresent(value -> { + Optional decodedValue = newValue.get().getValueAsString(); + decodedValue.ifPresent(v -> new Thread(new GetDataRunnable("tagData", getValues(path))).start()); + }); + }); + cache.start(); + } + } + + private void addVersionConfig(String env) { + String path = String.format(PATH_VERSION, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment)); + + this.versionData = parseData(path); + try (KVCache cache = KVCache.newCache(kvClient, path, consulConfig.getConsulWatchSeconds())) { + cache.addListener(newValues -> { + Optional newValue = newValues.values().stream() + .filter(value -> value.getKey().equals(path)) + .findAny(); + + newValue.ifPresent(value -> { + Optional decodedValue = newValue.get().getValueAsString(); + decodedValue.ifPresent(v -> new Thread(new GetDataRunnable("versionData", getValues(path))).start()); + }); + }); + cache.start(); + } + } + + private void addServiceConfig(String env) { + String path = String.format(PATH_SERVICE, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment)); + + this.serviceData = parseData(path); + try (KVCache cache = KVCache.newCache(kvClient, path, consulConfig.getConsulWatchSeconds())) { + cache.addListener(newValues -> { + Optional newValue = newValues.values().stream() + .filter(value -> value.getKey().equals(path)) + .findAny(); + + newValue.ifPresent(value -> { + Optional decodedValue = newValue.get().getValueAsString(); + decodedValue.ifPresent(v -> new Thread(new GetDataRunnable("serviceData", getValues(path))).start()); + }); + }); + cache.start(); + } + } + + private void addApplicationConfig(String env) { + String path = String.format(PATH_APPLICATION, env, BootStrapProperties.readApplication(environment)); + this.applicationData = parseData(path); + try (KVCache cache = KVCache.newCache(kvClient, path, consulConfig.getConsulWatchSeconds())) { + cache.addListener(newValues -> { + Optional newValue = newValues.values().stream() + .filter(value -> value.getKey().equals(path)) + .findAny(); + + newValue.ifPresent(value -> { + Optional decodedValue = newValue.get().getValueAsString(); + decodedValue.ifPresent(v -> new Thread(new GetDataRunnable("applicationData", getValues(path))).start()); + }); + }); + cache.start(); + } + } + + private void addEnvironmentConfig(String env) { + String path = String.format(PATH_ENVIRONMENT, env); + + this.environmentData = parseData(path); + try (KVCache cache = KVCache.newCache(kvClient, path, consulConfig.getConsulWatchSeconds())) { + cache.addListener(newValues -> { + Optional newValue = newValues.values().stream() + .filter(value -> value.getKey().equals(path)) + .findAny(); + + newValue.ifPresent(value -> { + Optional decodedValue = newValue.get().getValueAsString(); + decodedValue.ifPresent(v -> new Thread(new GetDataRunnable("environmentData", getValues(path))).start()); + }); + }); + cache.start(); + } + } + + public Map parseData(String path) { + try { + return getValues(path); + } catch (Exception e) { + LOGGER.error(e.getMessage(), e); + } + return new HashMap<>(); + } + + private Map getValues(String path) { + Map values = new HashMap<>(); + KeyValueClient keyValueClient = consulClient.keyValueClient(); + String decodedValue = keyValueClient.getValueAsString(path).orElseThrow(); + if (StringUtils.isBlank(decodedValue)) { + return values; + } + return getValues(path, decodedValue); + } + + private @NotNull Map getValues(String path, String decodedValue) { + Map values = new HashMap<>(); + if (path.endsWith(".yaml") || path.endsWith(".yml")) { + YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); + yamlFactory.setResources(new ByteArrayResource(decodedValue.getBytes(StandardCharsets.UTF_8))); + values.putAll(toMap(yamlFactory.getObject())); + } else if (path.endsWith(".properties")) { + Properties properties = new Properties(); + try { + properties.load(new StringReader(decodedValue)); + } catch (IOException e) { + LOGGER.error(e.getMessage(), e); + } + values.putAll(toMap(properties)); + } else { + values.put(path, decodedValue); + } + return values; + } + + private void refreshConfigItems() { + synchronized (lock) { + Map all = new HashMap<>(); + all.putAll(environmentData); + all.putAll(applicationData); + all.putAll(serviceData); + all.putAll(versionData); + all.putAll(tagData); + updateHandler.handle(all, allLast); + this.allLast = all; + } + } + + @SuppressWarnings("unchecked") + private Map toMap(Properties properties) { + if (properties == null) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + Enumeration keys = (Enumeration) properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + Object value = properties.getProperty(key); + result.put(key, value); + } + return result; + } +} diff --git a/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfigProperties.java b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfigProperties.java new file mode 100644 index 00000000000..fe3a278678a --- /dev/null +++ b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulConfigProperties.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.config.consul; + +public class ConsulConfigProperties { + + private String host = "localhost"; + + private Integer port = 8500; + + private String scheme = "http"; + + private String aclToken; + + private Integer watchSeconds = 8; + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + public String getScheme() { + return scheme; + } + + public void setScheme(String scheme) { + this.scheme = scheme; + } + + public String getAclToken() { + return aclToken; + } + + public void setAclToken(String aclToken) { + this.aclToken = aclToken; + } + + public Integer getWatchSeconds() { + return watchSeconds; + } + + public void setWatchSeconds(Integer watchSeconds) { + this.watchSeconds = watchSeconds; + } +} diff --git a/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulDynamicPropertiesSource.java b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulDynamicPropertiesSource.java new file mode 100644 index 00000000000..9f0b3649249 --- /dev/null +++ b/dynamic-config/config-consul/src/main/java/org/apache/servicecomb/config/consul/ConsulDynamicPropertiesSource.java @@ -0,0 +1,99 @@ +/* + * 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.config.consul; + +import com.google.common.net.HostAndPort; +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.kiwiproject.consul.Consul; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class ConsulDynamicPropertiesSource implements DynamicPropertiesSource { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsulDynamicPropertiesSource.class); + + public static final String SOURCE_NAME = "consul"; + + private final Map valueCache = new ConcurrentHashMap<>(); + + private ConsulConfigClient consulConfigClient; + + public ConsulDynamicPropertiesSource() { + } + + private final UpdateHandler updateHandler = new UpdateHandler(); + public class UpdateHandler { + public void handle(Map current, Map last) { + ConfigurationChangedEvent event = ConfigurationChangedEvent.createIncremental(current, last); + LOGGER.info("Dynamic configuration changed: {}", event.getChanged()); + valueCache.putAll(event.getAdded()); + valueCache.putAll(event.getUpdated()); + event.getDeleted().forEach((k, v) -> valueCache.remove(k)); + EventManager.post(event); + } + } + + private ConsulConfigProperties consulConfigProperties(Environment environment) { + ConsulConfig consulConfig = new ConsulConfig(environment); + ConsulConfigProperties consulConfigProperties = new ConsulConfigProperties(); + consulConfigProperties.setHost(consulConfig.getConsulHost()); + consulConfigProperties.setPort(consulConfig.getConsulPort()); + consulConfigProperties.setScheme(consulConfig.getConsulScheme()); + consulConfigProperties.setAclToken(consulConfig.getConsulAclToken()); + consulConfigProperties.setWatchSeconds(consulConfig.getConsulWatchSeconds()); + return consulConfigProperties; + } + + private Consul consulClient(ConsulConfigProperties consulConfigProperties) { + Consul.Builder builder = Consul.builder().withHostAndPort(HostAndPort.fromParts(consulConfigProperties.getHost(), consulConfigProperties.getPort())); + if (StringUtils.isNotBlank(consulConfigProperties.getAclToken())) { + builder.withAclToken(consulConfigProperties.getAclToken()); + } + return builder.build(); + } + + private ConsulConfigClient consulConfigClient(Environment environment) { + ConsulConfigProperties consulConfigProperties = consulConfigProperties(environment); + Consul consulClient = consulClient(consulConfigProperties); + return new ConsulConfigClient(updateHandler, environment, consulConfigProperties, consulClient); + } + + @Override + public PropertySource create(Environment environment) { + try { + consulConfigClient = consulConfigClient(environment); + consulConfigClient.refreshConsulConfig(); + } catch (Exception e) { + throw new IllegalStateException("Set up consul config failed.", e); + } + return new MapPropertySource(SOURCE_NAME, valueCache); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/dynamic-config/config-consul/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-consul/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..7b1c73e1195 --- /dev/null +++ b/dynamic-config/config-consul/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.consul.ConsulDynamicPropertiesSource diff --git a/dynamic-config/config-etcd/pom.xml b/dynamic-config/config-etcd/pom.xml new file mode 100644 index 00000000000..8aa6b2cf963 --- /dev/null +++ b/dynamic-config/config-etcd/pom.xml @@ -0,0 +1,44 @@ + + + + + + + dynamic-config + org.apache.servicecomb + 3.4.0-SNAPSHOT + + 4.0.0 + config-etcd + Java Chassis::Dynamic Config::Zookeeper + + + org.apache.servicecomb + foundation-config + + + org.apache.servicecomb + foundation-vertx + + + io.etcd + jetcd-core + + + diff --git a/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdClient.java b/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdClient.java new file mode 100644 index 00000000000..9a7743add07 --- /dev/null +++ b/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdClient.java @@ -0,0 +1,275 @@ +/* + * 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.config.etcd; + +import java.io.IOException; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.etcd.EtcdDynamicPropertiesSource.UpdateHandler; +import org.apache.servicecomb.foundation.common.utils.MuteExceptionUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ByteArrayResource; + +import io.etcd.jetcd.ByteSequence; +import io.etcd.jetcd.Client; +import io.etcd.jetcd.KeyValue; +import io.etcd.jetcd.Watch; +import io.etcd.jetcd.kv.GetResponse; +import io.etcd.jetcd.options.GetOption; +import io.etcd.jetcd.options.WatchOption; + +public class EtcdClient { + + public class GetDataRunnable implements Runnable { + + private Map dataMap; + + private EtcdClient etcdClient; + + private String path; + + public GetDataRunnable(Map dataMap, EtcdClient etcdClient, String path) { + this.dataMap = dataMap; + this.etcdClient = etcdClient; + this.path = path; + } + + @Override + public void run() { + try { + dataMap.clear(); + dataMap.putAll(etcdClient.parseData(path)); + refreshConfigItems(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + private static final Logger LOGGER = LoggerFactory.getLogger(EtcdClient.class); + + public static final String PATH_ENVIRONMENT = "/servicecomb/config/environment/%s"; + + public static final String PATH_APPLICATION = "/servicecomb/config/application/%s/%s"; + + public static final String PATH_SERVICE = "/servicecomb/config/service/%s/%s/%s"; + + public static final String PATH_VERSION = "/servicecomb/config/version/%s/%s/%s/%s"; + + public static final String PATH_TAG = "/servicecomb/config/tag/%s/%s/%s/%s/%s"; + + private final UpdateHandler updateHandler; + + private final EtcdConfig etcdConfig; + + private final Environment environment; + + private final Object lock = new Object(); + + private Map environmentData = new HashMap<>(); + + private Map applicationData = new HashMap<>(); + + private Map serviceData = new HashMap<>(); + + private Map versionData = new HashMap<>(); + + private Map tagData = new HashMap<>(); + + private Map allLast = new HashMap<>(); + + private Client client; + + public EtcdClient(UpdateHandler updateHandler, Environment environment) { + this.updateHandler = updateHandler; + this.etcdConfig = new EtcdConfig(environment); + this.environment = environment; + } + + public void getClient() { + if (StringUtils.isEmpty(etcdConfig.getAuthInfo())) { + this.client = Client.builder().endpoints(etcdConfig.getConnectString()).build(); + } else { + String[] authInfo = etcdConfig.getAuthInfo().split(":"); + this.client = Client.builder().endpoints(etcdConfig.getConnectString()) + .user(ByteSequence.from(authInfo[0], StandardCharsets.UTF_8)) + .password(ByteSequence.from(authInfo[1], StandardCharsets.UTF_8)).build(); + } + } + + public void refreshEtcdConfig() throws Exception { + + getClient(); + String env = BootStrapProperties.readServiceEnvironment(environment); + if (StringUtils.isEmpty(env)) { + env = EtcdConfig.ZOOKEEPER_DEFAULT_ENVIRONMENT; + } + addEnvironmentConfig(env); + addApplicationConfig(env); + addServiceConfig(env); + addVersionConfig(env); + addTagConfig(env); + + refreshConfigItems(); + } + + private void addTagConfig(String env) throws Exception { + if (StringUtils.isEmpty(etcdConfig.getInstanceTag())) { + return; + } + String path = String.format(PATH_TAG, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment), + etcdConfig.getInstanceTag()); + + ByteSequence prefixByteSeq = ByteSequence.from(path, StandardCharsets.UTF_8); + Watch watchClient = client.getWatchClient(); + watchClient.watch(prefixByteSeq, WatchOption.builder().withPrefix(prefixByteSeq).build(), + resp -> new Thread(new GetDataRunnable(tagData, this, path)).start()); + this.tagData = parseData(path); + } + + private void addVersionConfig(String env) throws Exception { + String path = String.format(PATH_VERSION, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment)); + + ByteSequence prefixByteSeq = ByteSequence.from(path, StandardCharsets.UTF_8); + Watch watchClient = client.getWatchClient(); + watchClient.watch(prefixByteSeq, WatchOption.builder().withPrefix(prefixByteSeq).build(), + resp -> new Thread(new GetDataRunnable(versionData, this, path)).start()); + this.versionData = parseData(path); + } + + private void addServiceConfig(String env) throws Exception { + String path = String.format(PATH_SERVICE, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment)); + + ByteSequence prefixByteSeq = ByteSequence.from(path, StandardCharsets.UTF_8); + Watch watchClient = client.getWatchClient(); + watchClient.watch(prefixByteSeq, WatchOption.builder().withPrefix(prefixByteSeq).build(), + resp -> new Thread(new GetDataRunnable(serviceData, this, path)).start()); + this.serviceData = parseData(path); + } + + private void addApplicationConfig(String env) throws Exception { + String path = String.format(PATH_APPLICATION, env, BootStrapProperties.readApplication(environment)); + + ByteSequence prefixByteSeq = ByteSequence.from(path, StandardCharsets.UTF_8); + Watch watchClient = client.getWatchClient(); + watchClient.watch(prefixByteSeq, WatchOption.builder().withPrefix(prefixByteSeq).build(), + resp -> new Thread(new GetDataRunnable(applicationData, this, path)).start()); + this.applicationData = parseData(path); + } + + private void addEnvironmentConfig(String env) throws Exception { + String path = String.format(PATH_ENVIRONMENT, env); + + ByteSequence prefixByteSeq = ByteSequence.from(path, StandardCharsets.UTF_8); + Watch watchClient = client.getWatchClient(); + watchClient.watch(prefixByteSeq, WatchOption.builder().withPrefix(prefixByteSeq).build(), + resp -> new Thread(new GetDataRunnable(environmentData, this, path)).start()); + this.environmentData = parseData(path); + } + + public Map parseData(String path) throws Exception { + + List endpointKv = getValuesByPrefix(path); + return getValues(path, endpointKv); + } + + private Map getValues(String path, List endpointKv) { + Map values = new HashMap<>(); + for (KeyValue keyValue : endpointKv) { + String key = new String(keyValue.getKey().getBytes(), StandardCharsets.UTF_8); + String value = new String(keyValue.getValue().getBytes(), StandardCharsets.UTF_8); + if (key.equals(path)) { + continue; + } + if (key.endsWith(".yaml") || key.endsWith(".yml")) { + YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); + yamlFactory.setResources(new ByteArrayResource(value.getBytes(StandardCharsets.UTF_8))); + values.putAll(toMap(yamlFactory.getObject())); + } else if (key.endsWith(".properties")) { + Properties properties = new Properties(); + try { + properties.load(new StringReader(value)); + } catch (IOException e) { + LOGGER.error("load error"); + } + values.putAll(toMap(properties)); + } else { + values.put(key, value); + } + } + return values; + } + + private List getValuesByPrefix(String prefix) { + + CompletableFuture getFuture = client.getKVClient() + .get(ByteSequence.from(prefix, StandardCharsets.UTF_8), + GetOption.builder().withPrefix(ByteSequence.from(prefix, StandardCharsets.UTF_8)).build()); + GetResponse response = MuteExceptionUtil.builder().withLog("get kv by prefix error") + .executeCompletableFuture(getFuture); + return response.getKvs(); + } + + private void refreshConfigItems() { + synchronized (lock) { + Map all = new HashMap<>(); + all.putAll(environmentData); + all.putAll(applicationData); + all.putAll(serviceData); + all.putAll(versionData); + all.putAll(tagData); + updateHandler.handle(all, allLast); + this.allLast = all; + } + } + + @SuppressWarnings("unchecked") + private Map toMap(Properties properties) { + if (properties == null) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + Enumeration keys = (Enumeration) properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + Object value = properties.getProperty(key); + result.put(key, value); + } + return result; + } +} diff --git a/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdConfig.java b/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdConfig.java new file mode 100644 index 00000000000..ee04204c28a --- /dev/null +++ b/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdConfig.java @@ -0,0 +1,65 @@ +/* + * 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.config.etcd; + +import org.springframework.core.env.Environment; + +public class EtcdConfig { + public static final String ZOOKEEPER_DEFAULT_ENVIRONMENT = "production"; + + public static final String PROPERTY_CONNECT_STRING = "servicecomb.config.etcd.connectString"; + + public static final String PROPERTY_SESSION_TIMEOUT = "servicecomb.config.etcd.sessionTimeoutMillis"; + + public static final String PROPERTY_CONNECTION_TIMEOUT = "servicecomb.config.etcd.connectionTimeoutMills"; + + public static final String PROPERTY_AUTH_SCHEMA = "servicecomb.config.etcd.authenticationSchema"; + + public static final String PROPERTY_AUTH_INFO = "servicecomb.config.etcd.authenticationInfo"; + + public static final String PROPERTY_INSTANCE_TAG = "servicecomb.config.etcd.instanceTag"; + + private final Environment environment; + + public EtcdConfig(Environment environment) { + this.environment = environment; + } + + public String getConnectString() { + return environment.getProperty(PROPERTY_CONNECT_STRING, "http://127.0.0.1:2379"); + } + + public int getSessionTimeoutMillis() { + return environment.getProperty(PROPERTY_SESSION_TIMEOUT, int.class, 60000); + } + + public int getConnectionTimeoutMillis() { + return environment.getProperty(PROPERTY_CONNECTION_TIMEOUT, int.class, 1000); + } + + public String getAuthSchema() { + return environment.getProperty(PROPERTY_AUTH_SCHEMA); + } + + public String getAuthInfo() { + return environment.getProperty(PROPERTY_AUTH_INFO); + } + + public String getInstanceTag() { + return environment.getProperty(PROPERTY_INSTANCE_TAG); + } +} diff --git a/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdDynamicPropertiesSource.java b/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdDynamicPropertiesSource.java new file mode 100644 index 00000000000..a86de892180 --- /dev/null +++ b/dynamic-config/config-etcd/src/main/java/org/apache/servicecomb/config/etcd/EtcdDynamicPropertiesSource.java @@ -0,0 +1,73 @@ +/* + * 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.config.etcd; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +public class EtcdDynamicPropertiesSource implements DynamicPropertiesSource { + public static final String SOURCE_NAME = "etcd"; + + private static final Logger LOGGER = LoggerFactory.getLogger(EtcdDynamicPropertiesSource.class); + + private final Map valueCache = new ConcurrentHashMap<>(); + + public EtcdDynamicPropertiesSource() { + } + + private final UpdateHandler updateHandler = new UpdateHandler(); + + private void init(Environment environment) { + EtcdClient etcdClient = new EtcdClient(updateHandler, environment); + try { + etcdClient.refreshEtcdConfig(); + } catch (Exception e) { + throw new IllegalStateException("Set up etcd config failed.", e); + } + } + + public class UpdateHandler { + public void handle(Map current, Map last) { + ConfigurationChangedEvent event = ConfigurationChangedEvent.createIncremental(current, last); + LOGGER.info("Dynamic configuration changed: {}", event.getChanged()); + valueCache.putAll(event.getAdded()); + valueCache.putAll(event.getUpdated()); + event.getDeleted().forEach((k, v) -> valueCache.remove(k)); + EventManager.post(event); + } + } + + @Override + public PropertySource create(Environment environment) { + init(environment); + return new MapPropertySource(SOURCE_NAME, valueCache); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/dynamic-config/config-etcd/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-etcd/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..d10124395fa --- /dev/null +++ b/dynamic-config/config-etcd/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.etcd.EtcdDynamicPropertiesSource diff --git a/dynamic-config/config-kie/pom.xml b/dynamic-config/config-kie/pom.xml index 43d83b6b9d2..4bf61b5801f 100644 --- a/dynamic-config/config-kie/pom.xml +++ b/dynamic-config/config-kie/pom.xml @@ -23,7 +23,7 @@ dynamic-config org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -35,10 +35,6 @@ org.apache.servicecomb foundation-config - - org.apache.servicecomb - deployment - org.apache.servicecomb foundation-ssl @@ -66,4 +62,4 @@ config-kie-client - \ No newline at end of file + diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java index 7f93e1d1c5f..79e40786f8f 100644 --- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java +++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfig.java @@ -17,21 +17,13 @@ package org.apache.servicecomb.config.kie; -import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.foundation.vertx.VertxConst; - -import com.netflix.config.ConcurrentCompositeConfiguration; +import org.springframework.core.env.Environment; public class KieConfig { - - public static final KieConfig INSTANCE = new KieConfig(); - - private static ConcurrentCompositeConfiguration finalConfig; - public static final String SSL_TAG = "kie.consumer"; private static final String SERVER_URL_KEY = "servicecomb.kie.serverUri"; @@ -56,11 +48,13 @@ public class KieConfig { private static final String ENABLE_SERVICE_CONFIG = "servicecomb.kie.enableServiceConfig"; + private static final String ENABLE_VERSION_CONFIG = "servicecomb.kie.enableVersionConfig"; + private static final String ENABLE_CUSTOM_CONFIG = "servicecomb.kie.enableCustomConfig"; public static final String FILE_SOURCE = "servicecomb.config.client.fileSource"; - private static final int DEFAULT_REFRESH_INTERVAL = 3000; + private static final int DEFAULT_REFRESH_INTERVAL = 15000; private static final int DEFAULT_POLLING_WAIT_TIME = 10; @@ -72,116 +66,104 @@ public class KieConfig { private static final String CUSTOM_LABEL_VALUE_DEFAULT = ""; - private KieConfig() { - } - - public static ConcurrentCompositeConfiguration getFinalConfig() { - return finalConfig; - } + private static final String CLIENT_CONNECT_TIMEOUT = "servicecomb.kie.client.timeout.connect"; - public static void setFinalConfig(ConcurrentCompositeConfiguration finalConfig) { - KieConfig.finalConfig = finalConfig; - } + private static final String CLIENT_REQUEST_TIMEOUT = "servicecomb.kie.client.timeout.request"; - @SuppressWarnings("unchecked") - public List getFileSources() { - Object property = finalConfig.getProperty(FILE_SOURCE); - if (property instanceof String) { - List result = new ArrayList<>(); - result.add((String) property); - return result; - } - if (property instanceof List) { - return (List) property; - } - return Collections.EMPTY_LIST; - } + private static final String CLIENT_SOCKET_TIMEOUT = "servicecomb.kie.client.timeout.socket"; - public String getVersion() { - return BootStrapProperties.readServiceVersion(finalConfig); - } + private final Environment environment; - public String getServiceName() { - return BootStrapProperties.readServiceName(finalConfig); + public KieConfig(Environment environment) { + this.environment = environment; } - public String getTags() { - return BootStrapProperties.readServiceInstanceTags(finalConfig); - } - - public String getEnvironment() { - return BootStrapProperties.readServiceEnvironment(finalConfig); - } - - public String getAppName() { - return BootStrapProperties.readApplication(finalConfig); + @SuppressWarnings("unchecked") + public List getFileSources() { + return environment.getProperty(FILE_SOURCE, List.class, Collections.emptyList()); } public String getDomainName() { - return finalConfig.getString(DOMAIN_NAME, "default"); + return environment.getProperty(DOMAIN_NAME, "default"); } public String getServerUri() { - return finalConfig.getString(SERVER_URL_KEY); + return environment.getProperty(SERVER_URL_KEY); } public int getRefreshInterval() { - return finalConfig.getInt(REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL); + return environment.getProperty(REFRESH_INTERVAL, int.class, DEFAULT_REFRESH_INTERVAL); } public int getFirstRefreshInterval() { - return finalConfig.getInt(FIRST_REFRESH_INTERVAL, DEFAULT_FIRST_REFRESH_INTERVAL); + return environment.getProperty(FIRST_REFRESH_INTERVAL, int.class, DEFAULT_FIRST_REFRESH_INTERVAL); } public boolean enableAppConfig() { - return finalConfig.getBoolean(ENABLE_APP_CONFIG, true); + return environment.getProperty(ENABLE_APP_CONFIG, boolean.class, true); } public boolean enableServiceConfig() { - return finalConfig.getBoolean(ENABLE_SERVICE_CONFIG, true); + return environment.getProperty(ENABLE_SERVICE_CONFIG, boolean.class, true); + } + + public boolean enableVersionConfig() { + return environment.getProperty(ENABLE_VERSION_CONFIG, boolean.class, true); } public boolean enableCustomConfig() { - return finalConfig.getBoolean(ENABLE_CUSTOM_CONFIG, true); + return environment.getProperty(ENABLE_CUSTOM_CONFIG, boolean.class, true); } public boolean enableLongPolling() { - return finalConfig.getBoolean(ENABLE_LONG_POLLING, DEFAULT_ENABLE_LONG_POLLING); + return environment.getProperty(ENABLE_LONG_POLLING, boolean.class, DEFAULT_ENABLE_LONG_POLLING); } public int getPollingWaitTime() { - return finalConfig.getInt(POLLING_WAIT_TIME, DEFAULT_POLLING_WAIT_TIME); + return environment.getProperty(POLLING_WAIT_TIME, int.class, DEFAULT_POLLING_WAIT_TIME); } public boolean firstPullRequired() { - return finalConfig.getBoolean(FIRST_PULL_REQUIRED, false); + return environment.getProperty(FIRST_PULL_REQUIRED, boolean.class, false); } public String getCustomLabel() { - return finalConfig.getString(CUSTOM_LABEL, CUSTOM_LABEL_DEFAULT); + return environment.getProperty(CUSTOM_LABEL, CUSTOM_LABEL_DEFAULT); } public String getCustomLabelValue() { - return finalConfig.getString(CUSTOM_LABEL_VALUE, CUSTOM_LABEL_VALUE_DEFAULT); + return environment.getProperty(CUSTOM_LABEL_VALUE, CUSTOM_LABEL_VALUE_DEFAULT); } public Boolean isProxyEnable() { - return finalConfig.getBoolean(VertxConst.PROXY_ENABLE, false); + return environment.getProperty(VertxConst.PROXY_ENABLE, boolean.class, false); } public String getProxyHost() { - return finalConfig.getString(VertxConst.PROXY_HOST, "127.0.0.1"); + return environment.getProperty(VertxConst.PROXY_HOST, "127.0.0.1"); } public int getProxyPort() { - return finalConfig.getInt(VertxConst.PROXY_PORT, 8080); + return environment.getProperty(VertxConst.PROXY_PORT, int.class, 8080); } public String getProxyUsername() { - return finalConfig.getString(VertxConst.PROXY_USERNAME, null); + return environment.getProperty(VertxConst.PROXY_USERNAME); } public String getProxyPasswd() { - return finalConfig.getString(VertxConst.PROXY_PASSWD, null); + return environment.getProperty(VertxConst.PROXY_PASSWD); + } + + public int getConnectTimeout() { + return environment.getProperty(CLIENT_CONNECT_TIMEOUT, int.class, 5000); + } + + public int getConnectionRequestTimeout() { + return environment.getProperty(CLIENT_REQUEST_TIMEOUT, int.class, 5000); + } + + public int getSocketTimeout() { + return environment.getProperty(CLIENT_SOCKET_TIMEOUT, int.class, 5000); } } diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigConfiguration.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigConfiguration.java new file mode 100644 index 00000000000..7b8e35bd6e4 --- /dev/null +++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigConfiguration.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.config.kie; + +import org.apache.servicecomb.config.kie.collect.KieClientInformationCollector; +import org.springframework.context.annotation.Bean; + +public class KieConfigConfiguration { + @Bean + public KieClientInformationCollector kieClientInformationCollector() { + return new KieClientInformationCollector(); + } +} diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java deleted file mode 100644 index cd06a824b44..00000000000 --- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieConfigurationSourceImpl.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * 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.config.kie; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang3.StringUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.servicecomb.config.common.ConfigConverter; -import org.apache.servicecomb.config.common.ConfigurationChangedEvent; -import org.apache.servicecomb.config.kie.client.KieClient; -import org.apache.servicecomb.config.kie.client.KieConfigManager; -import org.apache.servicecomb.config.kie.client.model.KieAddressManager; -import org.apache.servicecomb.config.kie.client.model.KieConfiguration; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; -import org.apache.servicecomb.http.client.common.HttpTransport; -import org.apache.servicecomb.http.client.common.HttpTransportFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.eventbus.Subscribe; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; - -public class KieConfigurationSourceImpl implements ConfigCenterConfigurationSource { - - private static final Logger LOGGER = LoggerFactory.getLogger(KieConfigurationSourceImpl.class); - - private List listeners = new CopyOnWriteArrayList<>(); - - private KieConfigManager kieConfigManager; - - private ConfigConverter configConverter; - - @Override - public int getOrder() { - return ORDER_BASE * 2; - } - - @Override - public boolean isValidSource(Configuration localConfiguration) { - KieConfig.setFinalConfig((ConcurrentCompositeConfiguration) localConfiguration); - - if (StringUtils.isEmpty(KieConfig.INSTANCE.getServerUri())) { - LOGGER.info("Kie server is not configured."); - return false; - } - return true; - } - - @Override - public void init(Configuration localConfiguration) { - configConverter = new ConfigConverter(KieConfig.INSTANCE.getFileSources()); - KieAddressManager kieAddressManager = configKieAddressManager(); - - RequestConfig.Builder requestBuilder = HttpTransportFactory.defaultRequestConfig(); - if (KieConfig.INSTANCE.enableLongPolling() - && KieConfig.INSTANCE.getPollingWaitTime() >= 0) { - requestBuilder.setConnectionRequestTimeout(KieConfig.INSTANCE.getPollingWaitTime() * 2 * 1000); - requestBuilder.setSocketTimeout(KieConfig.INSTANCE.getPollingWaitTime() * 2 * 1000); - } - HttpTransport httpTransport = createHttpTransport(kieAddressManager, requestBuilder.build(), - localConfiguration); - KieConfiguration kieConfiguration = createKieConfiguration(); - KieClient kieClient = new KieClient(kieAddressManager, httpTransport, kieConfiguration); - EventManager.register(this); - kieConfigManager = new KieConfigManager(kieClient, EventManager.getEventBus(), kieConfiguration, configConverter); - kieConfigManager.firstPull(); - kieConfigManager.startConfigKieManager(); - updateConfiguration(WatchedUpdateResult.createIncremental(configConverter.getCurrentData(), null, null)); - } - - @Subscribe - public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { - updateConfiguration( - WatchedUpdateResult.createIncremental(event.getAdded(), event.getUpdated(), event.getDeleted())); - } - - private KieConfiguration createKieConfiguration() { - return new KieConfiguration().setAppName(KieConfig.INSTANCE.getAppName()) - .setFirstPullRequired(KieConfig.INSTANCE.firstPullRequired()) - .setCustomLabel(KieConfig.INSTANCE.getCustomLabel()) - .setCustomLabelValue(KieConfig.INSTANCE.getCustomLabelValue()) - .setEnableAppConfig(KieConfig.INSTANCE.enableAppConfig()) - .setEnableCustomConfig(KieConfig.INSTANCE.enableCustomConfig()) - .setEnableLongPolling(KieConfig.INSTANCE.enableLongPolling()) - .setEnableServiceConfig(KieConfig.INSTANCE.enableServiceConfig()) - .setEnvironment(KieConfig.INSTANCE.getEnvironment()) - .setPollingWaitInSeconds(KieConfig.INSTANCE.getPollingWaitTime()) - .setProject(KieConfig.INSTANCE.getDomainName()) - .setServiceName(KieConfig.INSTANCE.getServiceName()); - } - - private HttpTransport createHttpTransport(KieAddressManager kieAddressManager, RequestConfig requestConfig, - Configuration localConfiguration) { - List authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class); - - if (KieConfig.INSTANCE.isProxyEnable()) { - HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(). - setDefaultRequestConfig(requestConfig); - HttpHost proxy = new HttpHost(KieConfig.INSTANCE.getProxyHost(), - KieConfig.INSTANCE.getProxyPort(),"http"); // now only support http proxy - httpClientBuilder.setProxy(proxy); - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(proxy), - new UsernamePasswordCredentials(KieConfig.INSTANCE.getProxyUsername(), - KieConfig.INSTANCE.getProxyPasswd())); - httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); - - return HttpTransportFactory - .createHttpTransport( - TransportUtils - .createSSLProperties(kieAddressManager.sslEnabled(), localConfiguration, KieConfig.SSL_TAG), - getRequestAuthHeaderProvider(authHeaderProviders), httpClientBuilder); - } - - return HttpTransportFactory - .createHttpTransport( - TransportUtils - .createSSLProperties(kieAddressManager.sslEnabled(), localConfiguration, KieConfig.SSL_TAG), - getRequestAuthHeaderProvider(authHeaderProviders), requestConfig); - } - - private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List authHeaderProviders) { - return signRequest -> { - Map headers = new HashMap<>(); - authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders())); - return headers; - }; - } - - private KieAddressManager configKieAddressManager() { - KieAddressManager kieAddressManager = new KieAddressManager( - Arrays.asList(KieConfig.INSTANCE.getServerUri().split(","))); - return kieAddressManager; - } - - private void updateConfiguration(WatchedUpdateResult result) { - LOGGER.info("configuration changed keys, added=[{}], updated=[{}], deleted=[{}]", - result.getAdded() == null ? "" : result.getAdded().keySet(), - result.getChanged() == null ? "" : result.getChanged().keySet(), - result.getDeleted() == null ? "" : result.getDeleted().keySet()); - - for (WatchedUpdateListener l : listeners) { - try { - l.updateConfiguration(result); - } catch (Throwable ex) { - LOGGER.error("Error in invoking WatchedUpdateListener", ex); - } - } - } - - @Override - public void destroy() { - if (kieConfigManager == null) { - return; - } - kieConfigManager.stop(); - } - - @Override - public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.add(watchedUpdateListener); - } - - @Override - public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.remove(watchedUpdateListener); - } - - @Override - public Map getCurrentData() throws Exception { - // data will updated by first pull, set empty to DynamicWatchedConfiguration first. - return Collections.emptyMap(); - } -} diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieDynamicPropertiesSource.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieDynamicPropertiesSource.java new file mode 100644 index 00000000000..6683b84fb09 --- /dev/null +++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/KieDynamicPropertiesSource.java @@ -0,0 +1,188 @@ +/* + * 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.config.kie; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.apache.servicecomb.config.common.ConfigConverter; +import org.apache.servicecomb.config.kie.client.KieClient; +import org.apache.servicecomb.config.kie.client.KieConfigManager; +import org.apache.servicecomb.config.kie.client.KieConfigurationChangedEvent; +import org.apache.servicecomb.config.kie.client.model.KieAddressManager; +import org.apache.servicecomb.config.kie.client.model.KieConfiguration; +import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; +import org.apache.servicecomb.http.client.common.HttpTransport; +import org.apache.servicecomb.http.client.common.HttpTransportFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +import com.google.common.eventbus.Subscribe; + +public class KieDynamicPropertiesSource implements DynamicPropertiesSource { + private static final Logger LOGGER = LoggerFactory.getLogger(KieDynamicPropertiesSource.class); + + public static final String SOURCE_NAME = "kie"; + + private final Map data = new ConcurrentHashMapEx<>(); + + private KieConfigManager kieConfigManager; + + private ConfigConverter configConverter; + + public KieDynamicPropertiesSource() { + + } + + private void init(Environment environment) { + KieConfig kieConfig = new KieConfig(environment); + configConverter = new ConfigConverter(kieConfig.getFileSources()); + KieAddressManager kieAddressManager = configKieAddressManager(kieConfig, environment); + + RequestConfig.Builder requestBuilder = buildRequestConfigBuilder(kieConfig); + if (kieConfig.enableLongPolling() + && kieConfig.getPollingWaitTime() >= 0) { + requestBuilder.setConnectionRequestTimeout(kieConfig.getPollingWaitTime() * 2 * 1000); + requestBuilder.setSocketTimeout(kieConfig.getPollingWaitTime() * 2 * 1000); + } + HttpTransport httpTransport = createHttpTransport(kieAddressManager, requestBuilder.build(), + kieConfig, environment); + KieConfiguration kieConfiguration = createKieConfiguration(kieConfig, environment); + KieClient kieClient = new KieClient(kieAddressManager, httpTransport, kieConfiguration); + EventManager.register(this); + kieConfigManager = new KieConfigManager(kieClient, EventManager.getEventBus(), kieConfiguration, configConverter, + kieAddressManager); + kieConfigManager.firstPull(); + kieConfigManager.startConfigKieManager(); + data.putAll(configConverter.getCurrentData()); + } + + private Builder buildRequestConfigBuilder(KieConfig kieConfig) { + Builder builder = HttpTransportFactory.defaultRequestConfig(); + builder.setConnectTimeout(kieConfig.getConnectTimeout()); + builder.setConnectionRequestTimeout(kieConfig.getConnectionRequestTimeout()); + builder.setSocketTimeout(kieConfig.getSocketTimeout()); + return builder; + } + + @Subscribe + public void onConfigurationChangedEvent(KieConfigurationChangedEvent event) { + LOGGER.info("Dynamic configuration changed: {}", event.getChanged()); + data.putAll(event.getAdded()); + data.putAll(event.getUpdated()); + event.getDeleted().forEach((k, v) -> data.remove(k)); + EventManager.post(ConfigurationChangedEvent.createIncremental(event.getAdded(), + event.getUpdated(), event.getDeleted())); + } + + private KieConfiguration createKieConfiguration(KieConfig kieConfig, Environment environment) { + return new KieConfiguration() + .setAppName(BootStrapProperties.readApplication(environment)) + .setServiceName(BootStrapProperties.readServiceName(environment)) + .setEnvironment(BootStrapProperties.readServiceEnvironment(environment)) + .setVersion(BootStrapProperties.readServiceVersion(environment)) + .setFirstPullRequired(kieConfig.firstPullRequired()) + .setCustomLabel(kieConfig.getCustomLabel()) + .setCustomLabelValue(kieConfig.getCustomLabelValue()) + .setEnableAppConfig(kieConfig.enableAppConfig()) + .setEnableCustomConfig(kieConfig.enableCustomConfig()) + .setEnableLongPolling(kieConfig.enableLongPolling()) + .setEnableServiceConfig(kieConfig.enableServiceConfig()) + .setEnableVersionConfig(kieConfig.enableVersionConfig()) + .setPollingWaitInSeconds(kieConfig.getPollingWaitTime()) + .setProject(kieConfig.getDomainName()) + .setRefreshIntervalInMillis(kieConfig.getRefreshInterval()); + } + + private HttpTransport createHttpTransport(KieAddressManager kieAddressManager, + RequestConfig requestConfig, KieConfig kieConfig, + Environment environment) { + List authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class); + + if (kieConfig.isProxyEnable()) { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(). + setDefaultRequestConfig(requestConfig); + HttpHost proxy = new HttpHost(kieConfig.getProxyHost(), + kieConfig.getProxyPort(), "http"); // now only support http proxy + httpClientBuilder.setProxy(proxy); + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(proxy), + new UsernamePasswordCredentials(kieConfig.getProxyUsername(), + kieConfig.getProxyPasswd())); + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + + return HttpTransportFactory + .createHttpTransport( + TransportUtils + .createSSLProperties(kieAddressManager.sslEnabled(), environment, KieConfig.SSL_TAG), + getRequestAuthHeaderProvider(authHeaderProviders), httpClientBuilder); + } + + return HttpTransportFactory + .createHttpTransport( + TransportUtils + .createSSLProperties(kieAddressManager.sslEnabled(), environment, KieConfig.SSL_TAG), + getRequestAuthHeaderProvider(authHeaderProviders), requestConfig); + } + + private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List authHeaderProviders) { + return signRequest -> { + String host = signRequest != null && signRequest.getEndpoint() != null ? signRequest.getEndpoint().getHost() : ""; + Map headers = new HashMap<>(); + authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders(host))); + return headers; + }; + } + + private KieAddressManager configKieAddressManager(KieConfig kieConfig, Environment environment) { + String region = environment.getProperty("servicecomb.datacenter.region"); + String availableZone = environment.getProperty("servicecomb.datacenter.availableZone"); + return new KieAddressManager( + Arrays.asList(kieConfig.getServerUri().split(",")), EventManager.getEventBus(), region, availableZone); + } + + @Override + public PropertySource create(Environment environment) { + init(environment); + return new MapPropertySource(SOURCE_NAME, data); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java index 56afa18ed3b..8be7ec00c1a 100644 --- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java +++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/TransportUtils.java @@ -19,13 +19,13 @@ import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION; -import org.apache.commons.configuration.Configuration; import org.apache.servicecomb.foundation.ssl.SSLCustom; import org.apache.servicecomb.foundation.ssl.SSLOption; import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; +import org.springframework.core.env.Environment; public class TransportUtils { - public static SSLProperties createSSLProperties(boolean sslEnabled, Configuration configuration, String tag) { + public static SSLProperties createSSLProperties(boolean sslEnabled, Environment environment, String tag) { SSLProperties sslProperties = new SSLProperties(); sslProperties.setEnabled(sslEnabled); @@ -34,93 +34,93 @@ public static SSLProperties createSSLProperties(boolean sslEnabled, Configuratio } SSLOption option = new SSLOption(); - option.setEngine(getStringProperty(configuration, + option.setEngine(getStringProperty(environment, DEFAULT_OPTION.getEngine(), "ssl." + tag + ".engine", "ssl.engine")); option.setProtocols( - getStringProperty(configuration, + getStringProperty(environment, DEFAULT_OPTION.getProtocols(), "ssl." + tag + ".protocols", "ssl.protocols")); option.setCiphers( - getStringProperty(configuration, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers")); + getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers")); option.setAuthPeer( - getBooleanProperty(configuration, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer")); + getBooleanProperty(environment, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer")); option.setCheckCNHost( - getBooleanProperty(configuration, + getBooleanProperty(environment, DEFAULT_OPTION.isCheckCNHost(), "ssl." + tag + ".checkCN.host", "ssl.checkCN.host")); option.setCheckCNWhite( - getBooleanProperty(configuration, + getBooleanProperty(environment, DEFAULT_OPTION.isCheckCNWhite(), "ssl." + tag + ".checkCN.white", "ssl.checkCN.white")); - option.setCheckCNWhiteFile(getStringProperty(configuration, + option.setCheckCNWhiteFile(getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".checkCN.white.file", "ssl.checkCN.white.file")); - option.setAllowRenegociate(getBooleanProperty(configuration, - DEFAULT_OPTION.isAllowRenegociate(), - "ssl." + tag + ".allowRenegociate", - "ssl.allowRenegociate")); + option.setAllowRenegotiate(getBooleanProperty(environment, + DEFAULT_OPTION.isAllowRenegotiate(), + "ssl." + tag + ".allowRenegotiate", + "ssl.allowRenegotiate")); option.setStorePath( - getStringProperty(configuration, + getStringProperty(environment, DEFAULT_OPTION.getStorePath(), "ssl." + tag + ".storePath", "ssl.storePath")); option.setClientAuth( - getStringProperty(configuration, + getStringProperty(environment, DEFAULT_OPTION.getClientAuth(), "ssl." + tag + ".clientAuth", "ssl.clientAuth")); option.setTrustStore( - getStringProperty(configuration, + getStringProperty(environment, DEFAULT_OPTION.getTrustStore(), "ssl." + tag + ".trustStore", "ssl.trustStore")); - option.setTrustStoreType(getStringProperty(configuration, + option.setTrustStoreType(getStringProperty(environment, DEFAULT_OPTION.getTrustStoreType(), "ssl." + tag + ".trustStoreType", "ssl.trustStoreType")); - option.setTrustStoreValue(getStringProperty(configuration, + option.setTrustStoreValue(getStringProperty(environment, DEFAULT_OPTION.getTrustStoreValue(), "ssl." + tag + ".trustStoreValue", "ssl.trustStoreValue")); option.setKeyStore( - getStringProperty(configuration, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore")); + getStringProperty(environment, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore")); option.setKeyStoreType( - getStringProperty(configuration, + getStringProperty(environment, DEFAULT_OPTION.getKeyStoreType(), "ssl." + tag + ".keyStoreType", "ssl.keyStoreType")); - option.setKeyStoreValue(getStringProperty(configuration, + option.setKeyStoreValue(getStringProperty(environment, DEFAULT_OPTION.getKeyStoreValue(), "ssl." + tag + ".keyStoreValue", "ssl.keyStoreValue")); - option.setCrl(getStringProperty(configuration, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl")); + option.setCrl(getStringProperty(environment, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl")); option.setSslCustomClass( - getStringProperty(configuration, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass")); + getStringProperty(environment, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass")); sslProperties.setSslOption(option); sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass())); return sslProperties; } - private static String getStringProperty(Configuration configuration, String defaultValue, String... keys) { + private static String getStringProperty(Environment environment, String defaultValue, String... keys) { for (String key : keys) { - if (configuration.containsKey(key)) { - return configuration.getString(key); + if (environment.getProperty(key) != null) { + return environment.getProperty(key); } } return defaultValue; } - private static boolean getBooleanProperty(Configuration configuration, boolean defaultValue, String... keys) { + private static boolean getBooleanProperty(Environment environment, boolean defaultValue, String... keys) { for (String key : keys) { - if (configuration.containsKey(key)) { - return configuration.getBoolean(key); + if (environment.getProperty(key) != null) { + return environment.getProperty(key, boolean.class, false); } } return defaultValue; diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieCenterDefaultDeploymentProvider.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieCenterDefaultDeploymentProvider.java deleted file mode 100644 index 9412314d42e..00000000000 --- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieCenterDefaultDeploymentProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.config.kie.collect; - -import java.util.List; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.deployment.DeploymentProvider; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; - -import com.google.common.annotations.VisibleForTesting; - -public class KieCenterDefaultDeploymentProvider implements DeploymentProvider { - public static final String SYSTEM_KEY_KIE_CENTER = "KieCenter"; - - private static AbstractConfiguration configuration = ConfigUtil.createLocalConfig(); - - @Override - public SystemBootstrapInfo getSystemBootStrapInfo(String systemKey) { - if (!systemKey.equals(SYSTEM_KEY_KIE_CENTER)) { - return null; - } - List kieAddresses = ConfigUtil - .parseArrayValue(configuration.getString("servicecomb.kie.serverUri")); - if (kieAddresses.isEmpty()) { - return null; - } - SystemBootstrapInfo kie = new SystemBootstrapInfo(); - kie.setAccessURL(kieAddresses); - return kie; - } - - @VisibleForTesting - public static void setConfiguration(AbstractConfiguration configuration) { - KieCenterDefaultDeploymentProvider.configuration = configuration; - } -} diff --git a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieClientInformationCollector.java b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieClientInformationCollector.java index eed0c9d4c52..d689aaec2e1 100644 --- a/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieClientInformationCollector.java +++ b/dynamic-config/config-kie/src/main/java/org/apache/servicecomb/config/kie/collect/KieClientInformationCollector.java @@ -17,25 +17,27 @@ package org.apache.servicecomb.config.kie.collect; +import org.apache.servicecomb.config.kie.KieConfig; import org.apache.servicecomb.core.bootup.BootUpInformationCollector; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; +import org.springframework.context.EnvironmentAware; +import org.springframework.core.env.Environment; +import org.springframework.lang.NonNull; -import java.util.Objects; +public class KieClientInformationCollector implements BootUpInformationCollector, EnvironmentAware { + private KieConfig kieConfig; + @Override + public void setEnvironment(@NonNull Environment environment) { + this.kieConfig = new KieConfig(environment); + } -public class KieClientInformationCollector implements BootUpInformationCollector { @Override public String collect() { - return "Kie Center: " + getCenterInfo(Deployment.getSystemBootStrapInfo("KieCenter")); + return "Kie Center: " + kieConfig.getServerUri(); } @Override public int getOrder() { return 2; } - - private String getCenterInfo(SystemBootstrapInfo systemBootstrapInfo) { - return Objects.isNull(systemBootstrapInfo) ? "not exist" : systemBootstrapInfo.getAccessURL().toString(); - } } diff --git a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..1ff1d0d0bb4 --- /dev/null +++ b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.kie.KieDynamicPropertiesSource diff --git a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource deleted file mode 100644 index 67520d4dc32..00000000000 --- a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.config.kie.KieConfigurationSourceImpl \ No newline at end of file diff --git a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector index cb357c9c3f8..4ff2984a1b2 100644 --- a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector +++ b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -org.apache.servicecomb.config.kie.collect.KieClientInformationCollector \ No newline at end of file +org.apache.servicecomb.config.kie.collect.KieClientInformationCollector diff --git a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider b/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider deleted file mode 100644 index c712d01e397..00000000000 --- a/dynamic-config/config-kie/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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.servicecomb.config.kie.collect.KieCenterDefaultDeploymentProvider \ No newline at end of file diff --git a/dynamic-config/config-kie/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/dynamic-config/config-kie/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..347d30ccef4 --- /dev/null +++ b/dynamic-config/config-kie/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.servicecomb.config.kie.KieConfigConfiguration diff --git a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/collect/TestKieCenterDefaultDeploymentProvider.java b/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/collect/TestKieCenterDefaultDeploymentProvider.java deleted file mode 100644 index 852b9dd1023..00000000000 --- a/dynamic-config/config-kie/src/test/java/org/apache/servicecomb/config/kie/collect/TestKieCenterDefaultDeploymentProvider.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.config.kie.collect; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestKieCenterDefaultDeploymentProvider { - @Before - public void start() { - ArchaiusUtils.resetConfig(); - } - - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testConfiguration() { - KieCenterDefaultDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(KieCenterDefaultDeploymentProvider.SYSTEM_KEY_KIE_CENTER); - Assert.assertEquals(info.getAccessURL().get(0), "https://172.16.8.7:30110"); - Assert.assertNull(Deployment.getSystemBootStrapInfo("wrong")); - } - - @Test - public void testConfigurationEnv() { - System.setProperty("servicecomb.kie.serverUri", "https://localhost:30110"); - KieCenterDefaultDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(KieCenterDefaultDeploymentProvider.SYSTEM_KEY_KIE_CENTER); - Assert.assertEquals(info.getAccessURL().get(0), "https://localhost:30110"); - System.getProperties().remove("servicecomb.kie.serverUri"); - } - - @Test - public void testConfigurationEnvTwo() { - System.setProperty("servicecomb.kie.serverUri", "http://127.0.0.1:30110,http://127.0.0.2:30110"); - KieCenterDefaultDeploymentProvider.setConfiguration(ConfigUtil.createLocalConfig()); - - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo(KieCenterDefaultDeploymentProvider.SYSTEM_KEY_KIE_CENTER); - Assert.assertEquals(info.getAccessURL().size(), 2); - Assert.assertEquals(info.getAccessURL().get(0), "http://127.0.0.1:30110"); - Assert.assertEquals(info.getAccessURL().get(1), "http://127.0.0.2:30110"); - - System.getProperties().remove("servicecomb.kie.serverUri"); - } -} diff --git a/dynamic-config/config-nacos/README.md b/dynamic-config/config-nacos/README.md index 8e817fc043a..e09d8db761d 100644 --- a/dynamic-config/config-nacos/README.md +++ b/dynamic-config/config-nacos/README.md @@ -1,5 +1,4 @@ # Dynamic configurations implementation with [Nacos](https://github.com/alibaba/nacos) Read [developers guide](https://docs.servicecomb.io/java-chassis/zh_CN/config/general-config/) -for details. - +for details. diff --git a/dynamic-config/config-nacos/pom.xml b/dynamic-config/config-nacos/pom.xml index 4f2cd447343..395603f9fd6 100644 --- a/dynamic-config/config-nacos/pom.xml +++ b/dynamic-config/config-nacos/pom.xml @@ -22,7 +22,7 @@ dynamic-config org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 config-nacos diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosClient.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosClient.java new file mode 100644 index 00000000000..de9527b17ab --- /dev/null +++ b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosClient.java @@ -0,0 +1,261 @@ +/* + * 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.config.nacos; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.Executor; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.nacos.NacosDynamicPropertiesSource.UpdateHandler; +import org.apache.servicecomb.config.parser.Parser; +import org.springframework.core.env.Environment; + +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.config.listener.Listener; +import com.alibaba.nacos.api.exception.NacosException; + +public class NacosClient { + private final UpdateHandler updateHandler; + + private final NacosConfig nacosConfig; + + private final Environment environment; + + private final Object lock = new Object(); + + private Map application = new HashMap<>(); + + private Map service = new HashMap<>(); + + private Map version = new HashMap<>(); + + private Map profile = new HashMap<>(); + + private Map custom = new HashMap<>(); + + private Map allLast = new HashMap<>(); + + public NacosClient(UpdateHandler updateHandler, Environment environment) { + this.updateHandler = updateHandler; + this.nacosConfig = new NacosConfig(environment); + this.environment = environment; + } + + public void refreshNacosConfig() throws NacosException { + Properties properties = nacosProperties(environment, nacosConfig); + + ConfigService configService = NacosFactory.createConfigService(properties); + addApplicationConfig(configService); + addServiceConfig(configService); + addVersionConfig(configService); + addProfileConfig(configService); + addCustomConfig(configService); + + refreshConfigItems(); + } + + private void addApplicationConfig(ConfigService configService) throws NacosException { + String content = configService.getConfig(BootStrapProperties.readApplication(environment), + BootStrapProperties.readApplication(environment), 5000); + processApplicationConfig(content); + configService.addListener(BootStrapProperties.readApplication(environment), + BootStrapProperties.readApplication(environment), new Listener() { + @Override + public void receiveConfigInfo(String configInfo) { + processApplicationConfig(configInfo); + refreshConfigItems(); + } + + @Override + public Executor getExecutor() { + return null; + } + }); + } + + private void processApplicationConfig(String content) { + if (StringUtils.isEmpty(content)) { + this.application = new HashMap<>(); + return; + } + Parser contentParser = Parser.findParser("yaml"); + this.application = contentParser.parse(content, "", false); + } + + private void addServiceConfig(ConfigService configService) throws NacosException { + String content = configService.getConfig(BootStrapProperties.readServiceName(environment), + BootStrapProperties.readApplication(environment), + 5000); + processServiceConfig(content); + configService.addListener(BootStrapProperties.readServiceName(environment), + BootStrapProperties.readApplication(environment), new Listener() { + @Override + public void receiveConfigInfo(String configInfo) { + processServiceConfig(configInfo); + refreshConfigItems(); + } + + @Override + public Executor getExecutor() { + return null; + } + }); + } + + private void processServiceConfig(String content) { + if (StringUtils.isEmpty(content)) { + this.service = new HashMap<>(); + return; + } + Parser contentParser = Parser.findParser("yaml"); + this.service = contentParser.parse(content, "", false); + } + + private void addVersionConfig(ConfigService configService) throws NacosException { + String content = configService.getConfig( + BootStrapProperties.readServiceName(environment) + "-" + + BootStrapProperties.readServiceVersion(environment), + BootStrapProperties.readApplication(environment), + 5000); + processVersionConfig(content); + configService.addListener(BootStrapProperties.readServiceName(environment) + "-" + + BootStrapProperties.readServiceVersion(environment), + BootStrapProperties.readApplication(environment), new Listener() { + @Override + public void receiveConfigInfo(String configInfo) { + processVersionConfig(configInfo); + refreshConfigItems(); + } + + @Override + public Executor getExecutor() { + return null; + } + }); + } + + private void processVersionConfig(String content) { + if (StringUtils.isEmpty(content)) { + this.version = new HashMap<>(); + return; + } + Parser contentParser = Parser.findParser("yaml"); + this.version = contentParser.parse(content, "", false); + } + + private void addProfileConfig(ConfigService configService) throws NacosException { + String profile = environment.getProperty("spring.profiles.active"); + if (StringUtils.isEmpty(profile)) { + return; + } + String content = configService.getConfig(BootStrapProperties.readServiceName(environment) + "-" + profile, + BootStrapProperties.readApplication(environment), 5000); + processProfileConfig(content); + configService.addListener(BootStrapProperties.readServiceName(environment) + "-" + profile, + BootStrapProperties.readApplication(environment), new Listener() { + @Override + public void receiveConfigInfo(String configInfo) { + processProfileConfig(configInfo); + refreshConfigItems(); + } + + @Override + public Executor getExecutor() { + return null; + } + }); + } + + private void processProfileConfig(String content) { + if (StringUtils.isEmpty(content)) { + this.profile = new HashMap<>(); + return; + } + Parser contentParser = Parser.findParser("yaml"); + this.profile = contentParser.parse(content, "", false); + } + + private void addCustomConfig(ConfigService configService) throws NacosException { + if (StringUtils.isEmpty(nacosConfig.getDataId()) || StringUtils.isEmpty(nacosConfig.getGroup())) { + return; + } + String content = configService.getConfig(nacosConfig.getDataId(), + nacosConfig.getGroup(), 5000); + processCustomConfig(content); + configService.addListener(nacosConfig.getDataId(), + nacosConfig.getGroup(), new Listener() { + @Override + public void receiveConfigInfo(String configInfo) { + processCustomConfig(configInfo); + refreshConfigItems(); + } + + @Override + public Executor getExecutor() { + return null; + } + }); + } + + private void processCustomConfig(String content) { + if (StringUtils.isEmpty(content)) { + this.custom = new HashMap<>(); + return; + } + Parser contentParser = Parser.findParser(nacosConfig.getContentType()); + String keyPrefix = nacosConfig.getGroup() + "." + + nacosConfig.getDataId(); + this.custom = contentParser.parse(content, keyPrefix, nacosConfig.getAddPrefix()); + } + + private void refreshConfigItems() { + synchronized (lock) { + Map all = new HashMap<>(); + all.putAll(application); + all.putAll(service); + all.putAll(version); + all.putAll(profile); + all.putAll(custom); + updateHandler.handle(all, allLast); + this.allLast = all; + } + } + + private static Properties nacosProperties(Environment environment, NacosConfig nacosConfig) { + Properties properties = new Properties(); + properties.put(NacosConfig.PROP_NAMESPACE, BootStrapProperties.readServiceEnvironment(environment)); + properties.put(NacosConfig.PROP_ADDRESS, nacosConfig.getServerAddr()); + if (nacosConfig.getUsername() != null) { + properties.put(NacosConfig.PROP_USERNAME, nacosConfig.getUsername()); + } + if (nacosConfig.getPassword() != null) { + properties.put(NacosConfig.PROP_PASSWORD, nacosConfig.getPassword()); + } + if (nacosConfig.getAccessKey() != null) { + properties.put(NacosConfig.PROP_ACCESS_KEY, nacosConfig.getAccessKey()); + } + if (nacosConfig.getSecretKey() != null) { + properties.put(NacosConfig.PROP_SECRET_KEY, nacosConfig.getSecretKey()); + } + return properties; + } +} diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosConfig.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosConfig.java new file mode 100644 index 00000000000..8963bd75c2d --- /dev/null +++ b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosConfig.java @@ -0,0 +1,94 @@ +/* + * 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.config.nacos; + +import org.springframework.core.env.Environment; + +public class NacosConfig { + public static final String PROPERTY_DATA_ID = "servicecomb.nacos.dataId"; + + public static final String PROPERTY_SERVER_ADDR = "servicecomb.nacos.serverAddr"; + + public static final String PROPERTY_GROUP = "servicecomb.nacos.group"; + + public static final String PROPERTY_ADD_PREFIX = "servicecomb.nacos.addPrefix"; + + public static final String PROPERTY_CONTENT_TYPE = "servicecomb.nacos.contentType"; + + public static final String PROPERTY_USERNAME = "servicecomb.nacos.username"; + + public static final String PROPERTY_PASSWORD = "servicecomb.nacos.password"; + + public static final String PROPERTY_ACCESS_KEY = "servicecomb.nacos.accessKey"; + + public static final String PROPERTY_SECRET_KEY = "servicecomb.nacos.secretKey"; + + public static final String PROP_NAMESPACE = "namespace"; + + public static final String PROP_ADDRESS = "serverAddr"; + + public static final String PROP_USERNAME = "username"; + + public static final String PROP_PASSWORD = "password"; + + public static final String PROP_ACCESS_KEY = "accessKey"; + + public static final String PROP_SECRET_KEY = "secretKey"; + + private final Environment environment; + + public NacosConfig(Environment environment) { + this.environment = environment; + } + + public String getServerAddr() { + return environment.getProperty(PROPERTY_SERVER_ADDR, "http://127.0.0.1:8848"); + } + + public String getDataId() { + return environment.getProperty(PROPERTY_DATA_ID); + } + + public String getGroup() { + return environment.getProperty(PROPERTY_GROUP); + } + + public String getUsername() { + return environment.getProperty(PROPERTY_USERNAME); + } + + public String getPassword() { + return environment.getProperty(PROPERTY_PASSWORD); + } + + public String getAccessKey() { + return environment.getProperty(PROPERTY_ACCESS_KEY); + } + + public String getSecretKey() { + return environment.getProperty(PROPERTY_SECRET_KEY); + } + + public String getContentType() { + return environment.getProperty(PROPERTY_CONTENT_TYPE, "yaml"); + } + + public boolean getAddPrefix() { + return environment.getProperty(PROPERTY_ADD_PREFIX, boolean.class, false); + } +} diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosDynamicPropertiesSource.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosDynamicPropertiesSource.java new file mode 100644 index 00000000000..308b6337615 --- /dev/null +++ b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/NacosDynamicPropertiesSource.java @@ -0,0 +1,73 @@ +/* + * 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.config.nacos; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +public class NacosDynamicPropertiesSource implements DynamicPropertiesSource { + public static final String SOURCE_NAME = "nacos"; + + private static final Logger LOGGER = LoggerFactory.getLogger(NacosDynamicPropertiesSource.class); + + private final Map valueCache = new ConcurrentHashMap<>(); + + public NacosDynamicPropertiesSource() { + } + + private final UpdateHandler updateHandler = new UpdateHandler(); + + private void init(Environment environment) { + NacosClient nacosClient = new NacosClient(updateHandler, environment); + try { + nacosClient.refreshNacosConfig(); + } catch (Exception e) { + throw new IllegalStateException("Set up nacos config failed.", e); + } + } + + public class UpdateHandler { + public void handle(Map current, Map last) { + ConfigurationChangedEvent event = ConfigurationChangedEvent.createIncremental(current, last); + LOGGER.info("Dynamic configuration changed: {}", event.getChanged()); + valueCache.putAll(event.getAdded()); + valueCache.putAll(event.getUpdated()); + event.getDeleted().forEach((k, v) -> valueCache.remove(k)); + EventManager.post(event); + } + } + + @Override + public PropertySource create(Environment environment) { + init(environment); + return new MapPropertySource(SOURCE_NAME, valueCache); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java deleted file mode 100644 index 97c3d7b8162..00000000000 --- a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImpl.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.config.nacos.archaius.sources; - -import static com.netflix.config.WatchedUpdateResult.createIncremental; -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.CREATE; -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.DELETE; -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.SET; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.config.ConfigMapping; -import org.apache.servicecomb.config.nacos.client.ConfigurationAction; -import org.apache.servicecomb.config.nacos.client.NacosClient; -import org.apache.servicecomb.config.nacos.client.NacosConfig; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableMap; -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; - -public class NacosConfigurationSourceImpl implements ConfigCenterConfigurationSource { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCenterConfigurationSource.class); - - private final Map valueCache = new ConcurrentHashMap<>(); - - private List listeners = new CopyOnWriteArrayList<>(); - - public NacosConfigurationSourceImpl() { - } - - private final UpdateHandler updateHandler = new UpdateHandler(); - - @Override - public int getOrder() { - return ORDER_BASE * 4; - } - - @Override - public boolean isValidSource(Configuration localConfiguration) { - if (localConfiguration.getProperty(NacosConfig.SERVER_ADDR) == null) { - LOGGER.warn("Nacos configuration source is not configured!"); - return false; - } - return true; - } - - @Override - public void init(Configuration localConfiguration) { - NacosConfig.setConcurrentCompositeConfiguration(localConfiguration); - init(); - } - - private void init() { - NacosClient nacosClient = new NacosClient(updateHandler); - nacosClient.refreshNacosConfig(); - } - - @Override - public void addUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.add(watchedUpdateListener); - } - - @Override - public void removeUpdateListener(WatchedUpdateListener watchedUpdateListener) { - listeners.remove(watchedUpdateListener); - } - - private void updateConfiguration(WatchedUpdateResult result) { - for (WatchedUpdateListener l : listeners) { - try { - l.updateConfiguration(result); - } catch (Throwable ex) { - LOGGER.error("Error in invoking WatchedUpdateListener", ex); - } - } - } - - @Override - public Map getCurrentData() throws Exception { - return valueCache; - } - - public List getCurrentListeners() { - return listeners; - } - - public class UpdateHandler { - public void handle(ConfigurationAction action, Map config) { - if (config == null || config.isEmpty()) { - return; - } - Map configuration = ConfigMapping.getConvertedMap(config); - if (CREATE.equals(action)) { - valueCache.putAll(configuration); - - updateConfiguration(createIncremental(ImmutableMap.copyOf(configuration), - null, - null)); - } else if (SET.equals(action)) { - valueCache.putAll(configuration); - - updateConfiguration(createIncremental(null, - ImmutableMap.copyOf(configuration), - null)); - } else if (DELETE.equals(action)) { - configuration.keySet().forEach(valueCache::remove); - updateConfiguration(createIncremental(null, - null, - ImmutableMap.copyOf(configuration))); - } else { - LOGGER.error("action: {} is invalid.", action.name()); - return; - } - LOGGER.warn("Config value cache changed: action:{}; item:{}", action.name(), configuration.keySet()); - } - } -} diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/ConfigurationAction.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/ConfigurationAction.java deleted file mode 100644 index 3defe34f076..00000000000 --- a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/ConfigurationAction.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.config.nacos.client; - -public enum ConfigurationAction { - CREATE, - SET, - DELETE -} diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java deleted file mode 100644 index 290f922c106..00000000000 --- a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosClient.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.config.nacos.client; - -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.CREATE; -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.DELETE; -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.SET; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executor; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.config.nacos.archaius.sources.NacosConfigurationSourceImpl.UpdateHandler; -import org.apache.servicecomb.config.parser.Parser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.alibaba.nacos.api.NacosFactory; -import com.alibaba.nacos.api.config.ConfigService; -import com.alibaba.nacos.api.config.listener.Listener; - -public class NacosClient { - - private static final Logger LOGGER = LoggerFactory.getLogger(NacosClient.class); - - private static final Map originalConfigMap = new ConcurrentHashMap<>(); - - private final UpdateHandler updateHandler; - - public NacosClient(UpdateHandler updateHandler) { - this.updateHandler = updateHandler; - } - - public void refreshNacosConfig() { - new ConfigRefresh().refreshConfig(); - } - - class ConfigRefresh { - Parser contentParser = Parser.findParser(NacosConfig.INSTANCE.getContentType()); - - String keyPrefix = NacosConfig.INSTANCE.getGroup() + "." + - NacosConfig.INSTANCE.getDataId(); - - ConfigRefresh() { - } - - @SuppressWarnings("unchecked") - void refreshConfig() { - Properties properties = new Properties(); - properties.put("serverAddr", NacosConfig.INSTANCE.getServerAddr()); - properties.put("namespace", NacosConfig.INSTANCE.getNameSpace()); - - try { - ConfigService configService = NacosFactory.createConfigService(properties); - String content = configService.getConfig(NacosConfig.INSTANCE.getDataId(), - NacosConfig.INSTANCE.getGroup(), 5000); - processContent(content); - configService.addListener(NacosConfig.INSTANCE.getDataId(), - NacosConfig.INSTANCE.getGroup(), new Listener() { - @Override - public void receiveConfigInfo(String configInfo) { - LOGGER.info("receive from nacos:" + configInfo); - processContent(configInfo); - } - - @Override - public Executor getExecutor() { - return null; - } - }); - } catch (Exception e) { - LOGGER.error("Receive nacos config error: ", e); - } - } - - private void processContent(String content) { - if (StringUtils.isEmpty(content)) { - return; - } - - refreshConfigItems(contentParser.parse(content, keyPrefix, NacosConfig.INSTANCE.getAddPrefix())); - } - - private void refreshConfigItems(Map map) { - compareChangedConfig(originalConfigMap, map); - originalConfigMap.clear(); - originalConfigMap.putAll(map); - } - - void compareChangedConfig(Map before, Map after) { - Map itemsCreated = new HashMap<>(); - Map itemsDeleted = new HashMap<>(); - Map itemsModified = new HashMap<>(); - if (before == null || before.isEmpty()) { - updateHandler.handle(CREATE, after); - return; - } - if (after == null || after.isEmpty()) { - updateHandler.handle(DELETE, before); - return; - } - after.entrySet().forEach(stringObjectEntry -> { - String itemKey = stringObjectEntry.getKey(); - Object itemValue = stringObjectEntry.getValue(); - if (!before.containsKey(itemKey)) { - itemsCreated.put(itemKey, itemValue); - } else if (!itemValue.equals(before.get(itemKey))) { - itemsModified.put(itemKey, itemValue); - } - }); - for (String itemKey : before.keySet()) { - if (!after.containsKey(itemKey)) { - itemsDeleted.put(itemKey, ""); - } - } - updateHandler.handle(CREATE, itemsCreated); - updateHandler.handle(SET, itemsModified); - updateHandler.handle(DELETE, itemsDeleted); - } - } -} - diff --git a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java b/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java deleted file mode 100644 index 4fb31111ca6..00000000000 --- a/dynamic-config/config-nacos/src/main/java/org/apache/servicecomb/config/nacos/client/NacosConfig.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.config.nacos.client; - -import org.apache.commons.configuration.Configuration; - -public class NacosConfig { - public static final NacosConfig INSTANCE = new NacosConfig(); - - private static Configuration finalConfig; - - public static final String DATA_ID = "servicecomb.nacos.dataId"; - - public static final String SERVER_ADDR = "servicecomb.nacos.serverAddr"; - - public static final String GROUP = "servicecomb.nacos.group"; - - public static final String ADD_PREFIX = "servicecomb.nacos.addPrefix"; - - public static final String NAME_SPACE = "servicecomb.nacos.namespace"; - - public static final String CONTENT_TYPE = "servicecomb.nacos.contentType"; - - private NacosConfig() { - } - - public static void setConcurrentCompositeConfiguration(Configuration config) { - finalConfig = config; - } - - public String getServerAddr() { - return finalConfig.getString(SERVER_ADDR); - } - - public String getDataId() { - return finalConfig.getString(DATA_ID); - } - - public String getGroup() { - return finalConfig.getString(GROUP); - } - - public String getNameSpace() { - return finalConfig.getString(NAME_SPACE, "public"); - } - - public String getContentType() { - return finalConfig.getString(CONTENT_TYPE, "yaml"); - } - - public boolean getAddPrefix() { - return finalConfig.getBoolean(ADD_PREFIX, true); - } -} diff --git a/dynamic-config/config-nacos/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-nacos/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..f7b7e102457 --- /dev/null +++ b/dynamic-config/config-nacos/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.nacos.NacosDynamicPropertiesSource diff --git a/dynamic-config/config-nacos/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/dynamic-config/config-nacos/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource deleted file mode 100644 index 94965f14785..00000000000 --- a/dynamic-config/config-nacos/src/main/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.config.nacos.archaius.sources.NacosConfigurationSourceImpl diff --git a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImplTest.java b/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImplTest.java deleted file mode 100644 index 1faf1d15964..00000000000 --- a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/archaius/sources/NacosConfigurationSourceImplTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.config.nacos.archaius.sources; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.config.nacos.archaius.sources.NacosConfigurationSourceImpl.UpdateHandler; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.config.WatchedUpdateListener; - -import mockit.Deencapsulation; - -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.*; -import static org.apache.servicecomb.config.nacos.client.ConfigurationAction.CREATE; - -public class NacosConfigurationSourceImplTest { - @Test - public void testCreate() throws Exception { - NacosConfigurationSourceImpl nacosConfigurationSource = new NacosConfigurationSourceImpl(); - nacosConfigurationSource.addUpdateListener(result -> Assert.assertTrue(!result.getAdded().isEmpty())); - UpdateHandler udateHandler = Deencapsulation.getField(nacosConfigurationSource, UpdateHandler.class); - Map createItems = new HashMap<>(); - createItems.put("nacosTestKey", "testValue"); - udateHandler.handle(CREATE, createItems); - } - - @Test - public void testUpdate() throws Exception { - NacosConfigurationSourceImpl nacosConfigurationSource = new NacosConfigurationSourceImpl(); - nacosConfigurationSource.addUpdateListener(result -> Assert.assertTrue(!result.getChanged().isEmpty())); - UpdateHandler udateHandler = Deencapsulation.getField(nacosConfigurationSource, UpdateHandler.class); - Map updateItems = new HashMap<>(); - updateItems.put("nacosTestKey", "testValue"); - udateHandler.handle(SET, updateItems); - - } - - @Test - public void testDelete() throws Exception { - NacosConfigurationSourceImpl nacosConfigurationSource = new NacosConfigurationSourceImpl(); - nacosConfigurationSource.addUpdateListener(result -> Assert.assertTrue(!result.getDeleted().isEmpty())); - UpdateHandler udateHandler = Deencapsulation.getField(nacosConfigurationSource, UpdateHandler.class); - Map deleteItems = new HashMap<>(); - deleteItems.put("nacosTestKey", "testValue"); - - nacosConfigurationSource.getCurrentData().put("nacosTestKey", "testValue"); - udateHandler.handle(DELETE, deleteItems); - Assert.assertTrue(nacosConfigurationSource.getCurrentData().isEmpty()); - } - - @Test - public void testRemoveUpdateListener() { - NacosConfigurationSourceImpl nacosConfigurationSource = new NacosConfigurationSourceImpl(); - WatchedUpdateListener watchedUpdateListener = Mockito.mock(WatchedUpdateListener.class); - nacosConfigurationSource.addUpdateListener(watchedUpdateListener); - nacosConfigurationSource.removeUpdateListener(watchedUpdateListener); - Assert.assertTrue(nacosConfigurationSource.getCurrentListeners().isEmpty()); - } -} diff --git a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java b/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java deleted file mode 100644 index 9484517873d..00000000000 --- a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosClientTest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.config.nacos.client; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.config.nacos.archaius.sources.NacosConfigurationSourceImpl; -import org.apache.servicecomb.config.nacos.archaius.sources.NacosConfigurationSourceImpl.UpdateHandler; -import org.apache.servicecomb.config.nacos.client.NacosClient; -import org.apache.servicecomb.config.nacos.client.NacosConfig; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import mockit.Deencapsulation; - -public class NacosClientTest { - @BeforeClass - public static void setUpClass() { - NacosConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig()); - } - - @Test - public void refreshNacosConfig() { - - NacosConfigurationSourceImpl impl = new NacosConfigurationSourceImpl(); - UpdateHandler updateHandler = impl.new UpdateHandler(); - NacosClient nacosClient = new NacosClient(updateHandler); - //before open this code,you need to start nacos-console first - //and make sure the address is 127.0.0.1:8848 - //nacosClient.refreshNacosConfig(); - Map originMap = Deencapsulation.getField(nacosClient, "originalConfigMap"); - originMap.put("nacos","12345"); - Assert.assertEquals(1, originMap.size()); - } - - @Test - public void testCompareChangedConfig() { - boolean status = true; - Map before = new HashMap<>(); - Map after = new HashMap<>(); - - NacosConfigurationSourceImpl impl = new NacosConfigurationSourceImpl(); - UpdateHandler updateHandler = impl.new UpdateHandler(); - NacosClient nacosClient = new NacosClient(updateHandler); - - NacosClient.ConfigRefresh cr = nacosClient.new ConfigRefresh(); - - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - - status = true; - before.put("test", "testValue"); - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - - status = true; - after.put("test", "testValue2"); - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - - status = true; - try { - Deencapsulation.invoke(cr, "compareChangedConfig", before, after); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - } -} diff --git a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosConfigTest.java b/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosConfigTest.java deleted file mode 100644 index 89c44e7154b..00000000000 --- a/dynamic-config/config-nacos/src/test/java/org/apache/servicecomb/config/nacos/client/NacosConfigTest.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.config.nacos.client; - -import org.apache.servicecomb.config.ConfigUtil; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -public class NacosConfigTest { - @BeforeClass - public static void setUpClass() { - NacosConfig.setConcurrentCompositeConfiguration(ConfigUtil.createLocalConfig()); - } - - @Test - public void getServiceName() { - NacosConfig instance = NacosConfig.INSTANCE; - Assert.assertEquals("DEFAULT_GROUP", instance.getGroup()); - Assert.assertEquals("127.0.0.1:8848", instance.getServerAddr()); - Assert.assertEquals("example", instance.getDataId()); - } -} diff --git a/dynamic-config/config-nacos/src/test/resources/microservice.yaml b/dynamic-config/config-nacos/src/test/resources/microservice.yaml index 49501846276..1b9666a84d4 100644 --- a/dynamic-config/config-nacos/src/test/resources/microservice.yaml +++ b/dynamic-config/config-nacos/src/test/resources/microservice.yaml @@ -33,12 +33,3 @@ servicecomb: address: 0.0.0.0:8080 highway: address: 0.0.0.0:7070 - handler: - chain: - Provider: - default: bizkeeper-provider - #executors: - #default: test - #Provider: - #server: test - #server.wrapParam: test \ No newline at end of file diff --git a/dynamic-config/config-zookeeper/pom.xml b/dynamic-config/config-zookeeper/pom.xml new file mode 100644 index 00000000000..35fabec9591 --- /dev/null +++ b/dynamic-config/config-zookeeper/pom.xml @@ -0,0 +1,49 @@ + + + + + + + dynamic-config + org.apache.servicecomb + 3.4.0-SNAPSHOT + + 4.0.0 + config-zookeeper + Java Chassis::Dynamic Config::Zookeeper + + + org.apache.servicecomb + foundation-config + + + org.apache.servicecomb + foundation-vertx + + + + org.apache.curator + curator-framework + + + org.apache.curator + curator-recipes + + + diff --git a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java new file mode 100644 index 00000000000..407c577d4e5 --- /dev/null +++ b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperClient.java @@ -0,0 +1,281 @@ +/* + * 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.config.zookeeper; + +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.security.auth.login.AppConfigurationEntry; +import javax.security.auth.login.Configuration; + +import org.apache.commons.lang3.StringUtils; +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.framework.recipes.cache.CuratorCache; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.zookeeper.ZookeeperDynamicPropertiesSource.UpdateHandler; +import org.apache.zookeeper.server.auth.DigestLoginModule; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ByteArrayResource; + +public class ZookeeperClient { + static class ZookeeperSASLConfig extends Configuration { + AppConfigurationEntry entry; + + public ZookeeperSASLConfig(String username, + String password) { + Map options = new HashMap<>(); + options.put("username", username); + options.put("password", password); + this.entry = new AppConfigurationEntry( + DigestLoginModule.class.getName(), + AppConfigurationEntry.LoginModuleControlFlag.REQUIRED, + options + ); + } + + @Override + public AppConfigurationEntry[] getAppConfigurationEntry(String name) { + AppConfigurationEntry[] array = new AppConfigurationEntry[1]; + array[0] = entry; + return array; + } + } + + private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperClient.class); + + public static final String PATH_ENVIRONMENT = "/servicecomb/config/environment/%s"; + + public static final String PATH_APPLICATION = "/servicecomb/config/application/%s/%s"; + + public static final String PATH_SERVICE = "/servicecomb/config/service/%s/%s/%s"; + + public static final String PATH_VERSION = "/servicecomb/config/version/%s/%s/%s/%s"; + + public static final String PATH_TAG = "/servicecomb/config/tag/%s/%s/%s/%s/%s"; + + private final UpdateHandler updateHandler; + + private final ZookeeperConfig zookeeperConfig; + + private final Environment environment; + + private final Object lock = new Object(); + + private Map environmentData = new HashMap<>(); + + private Map applicationData = new HashMap<>(); + + private Map serviceData = new HashMap<>(); + + private Map versionData = new HashMap<>(); + + private Map tagData = new HashMap<>(); + + private Map allLast = new HashMap<>(); + + + public ZookeeperClient(UpdateHandler updateHandler, Environment environment) { + this.updateHandler = updateHandler; + this.zookeeperConfig = new ZookeeperConfig(environment); + this.environment = environment; + } + + public void refreshZookeeperConfig() throws Exception { + CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder() + .connectString(zookeeperConfig.getConnectString()) + .sessionTimeoutMs(zookeeperConfig.getSessionTimeoutMillis()) + .retryPolicy(new ExponentialBackoffRetry(1000, 3)); + String authSchema = zookeeperConfig.getAuthSchema(); + if (StringUtils.isNotEmpty(authSchema)) { + if (!"digest".equals(authSchema)) { + throw new IllegalStateException("Not supported schema now. " + authSchema); + } + if (zookeeperConfig.getAuthInfo() == null) { + throw new IllegalStateException("Auth info can not be empty. "); + } + + String[] authInfo = zookeeperConfig.getAuthInfo().split(":"); + Configuration.setConfiguration(new ZookeeperSASLConfig(authInfo[0], authInfo[1])); + } + CuratorFramework client = builder.build(); + client.start(); + + String env = BootStrapProperties.readServiceEnvironment(environment); + if (StringUtils.isEmpty(env)) { + env = ZookeeperConfig.ZOOKEEPER_DEFAULT_ENVIRONMENT; + } + addEnvironmentConfig(env, client); + addApplicationConfig(env, client); + addServiceConfig(env, client); + addVersionConfig(env, client); + addTagConfig(env, client); + + refreshConfigItems(); + } + + private void addTagConfig(String env, CuratorFramework client) throws Exception { + if (StringUtils.isEmpty(zookeeperConfig.getInstanceTag())) { + return; + } + String path = String.format(PATH_TAG, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment), + zookeeperConfig.getInstanceTag()); + CuratorCache cache = CuratorCache.builder(client, path).build(); + cache.listenable().addListener((type, oldData, newData) -> { + try { + this.tagData = parseData(client, path); + refreshConfigItems(); + } catch (Exception e) { + LOGGER.error("process event failed", e); + } + }); + cache.start(); + this.tagData = parseData(client, path); + } + + private void addVersionConfig(String env, CuratorFramework client) throws Exception { + String path = String.format(PATH_VERSION, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment), + BootStrapProperties.readServiceVersion(environment)); + CuratorCache cache = CuratorCache.builder(client, path).build(); + cache.listenable().addListener((type, oldData, newData) -> { + try { + this.versionData = parseData(client, path); + refreshConfigItems(); + } catch (Exception e) { + LOGGER.error("process event failed", e); + } + }); + cache.start(); + this.versionData = parseData(client, path); + } + + private void addServiceConfig(String env, CuratorFramework client) throws Exception { + String path = String.format(PATH_SERVICE, env, + BootStrapProperties.readApplication(environment), + BootStrapProperties.readServiceName(environment)); + CuratorCache cache = CuratorCache.builder(client, path).build(); + cache.listenable().addListener((type, oldData, newData) -> { + try { + this.serviceData = parseData(client, path); + refreshConfigItems(); + } catch (Exception e) { + LOGGER.error("process event failed", e); + } + }); + cache.start(); + this.serviceData = parseData(client, path); + } + + private void addApplicationConfig(String env, CuratorFramework client) throws Exception { + String path = String.format(PATH_APPLICATION, env, BootStrapProperties.readApplication(environment)); + CuratorCache cache = CuratorCache.builder(client, path).build(); + cache.listenable().addListener((type, oldData, newData) -> { + try { + this.applicationData = parseData(client, path); + refreshConfigItems(); + } catch (Exception e) { + LOGGER.error("process event failed", e); + } + }); + cache.start(); + this.applicationData = parseData(client, path); + } + + private void addEnvironmentConfig(String env, CuratorFramework client) throws Exception { + String path = String.format(PATH_ENVIRONMENT, env); + CuratorCache cache = CuratorCache.builder(client, path).build(); + cache.listenable().addListener((type, oldData, newData) -> { + try { + this.environmentData = parseData(client, path); + refreshConfigItems(); + } catch (Exception e) { + LOGGER.error("process event failed", e); + } + }); + cache.start(); + this.environmentData = parseData(client, path); + } + + private Map parseData(CuratorFramework client, String path) throws Exception { + Map values = new HashMap<>(); + + if (client.checkExists().forPath(path) != null) { + client.getChildren().forPath(path).stream().sorted().forEach(item -> { + try { + byte[] data = client.getData().forPath(path + "/" + item); + if (item.endsWith(".yaml") || item.endsWith(".yml")) { + YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean(); + yamlFactory.setResources(new ByteArrayResource(data)); + values.putAll(toMap(yamlFactory.getObject())); + } else if (item.endsWith(".properties")) { + Properties properties = new Properties(); + properties.load(new StringReader(new String(data, StandardCharsets.UTF_8))); + values.putAll(toMap(properties)); + } else { + values.put(item, new String(data, StandardCharsets.UTF_8)); + } + } catch (Exception e) { + LOGGER.error("", e); + } + }); + } + + return values; + } + + private void refreshConfigItems() { + synchronized (lock) { + Map all = new HashMap<>(); + all.putAll(environmentData); + all.putAll(applicationData); + all.putAll(serviceData); + all.putAll(versionData); + all.putAll(tagData); + updateHandler.handle(all, allLast); + this.allLast = all; + } + } + + @SuppressWarnings("unchecked") + private Map toMap(Properties properties) { + if (properties == null) { + return Collections.emptyMap(); + } + Map result = new HashMap<>(); + Enumeration keys = (Enumeration) properties.propertyNames(); + while (keys.hasMoreElements()) { + String key = keys.nextElement(); + Object value = properties.getProperty(key); + result.put(key, value); + } + return result; + } +} diff --git a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java new file mode 100644 index 00000000000..307ef7f0d55 --- /dev/null +++ b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperConfig.java @@ -0,0 +1,65 @@ +/* + * 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.config.zookeeper; + +import org.springframework.core.env.Environment; + +public class ZookeeperConfig { + public static final String ZOOKEEPER_DEFAULT_ENVIRONMENT = "production"; + + public static final String PROPERTY_CONNECT_STRING = "servicecomb.config.zk.connect-string"; + + public static final String PROPERTY_SESSION_TIMEOUT = "servicecomb.config.zk.session-timeout-millis"; + + public static final String PROPERTY_CONNECTION_TIMEOUT = "servicecomb.config.zk.connection-timeout-mills"; + + public static final String PROPERTY_AUTH_SCHEMA = "servicecomb.config.zk.authentication-schema"; + + public static final String PROPERTY_AUTH_INFO = "servicecomb.config.zk.authentication-info"; + + public static final String PROPERTY_INSTANCE_TAG = "servicecomb.config.zk.instance-tag"; + + private final Environment environment; + + public ZookeeperConfig(Environment environment) { + this.environment = environment; + } + + public String getConnectString() { + return environment.getProperty(PROPERTY_CONNECT_STRING, "127.0.0.1:2181"); + } + + public int getSessionTimeoutMillis() { + return environment.getProperty(PROPERTY_SESSION_TIMEOUT, int.class, 60000); + } + + public int getConnectionTimeoutMillis() { + return environment.getProperty(PROPERTY_CONNECTION_TIMEOUT, int.class, 1000); + } + + public String getAuthSchema() { + return environment.getProperty(PROPERTY_AUTH_SCHEMA); + } + + public String getAuthInfo() { + return environment.getProperty(PROPERTY_AUTH_INFO); + } + + public String getInstanceTag() { + return environment.getProperty(PROPERTY_INSTANCE_TAG); + } +} diff --git a/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperDynamicPropertiesSource.java b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperDynamicPropertiesSource.java new file mode 100644 index 00000000000..a971ea5845f --- /dev/null +++ b/dynamic-config/config-zookeeper/src/main/java/org/apache/servicecomb/config/zookeeper/ZookeeperDynamicPropertiesSource.java @@ -0,0 +1,73 @@ +/* + * 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.config.zookeeper; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.DynamicPropertiesSource; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +public class ZookeeperDynamicPropertiesSource implements DynamicPropertiesSource { + public static final String SOURCE_NAME = "zookeeper"; + + private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperDynamicPropertiesSource.class); + + private final Map valueCache = new ConcurrentHashMap<>(); + + public ZookeeperDynamicPropertiesSource() { + } + + private final UpdateHandler updateHandler = new UpdateHandler(); + + private void init(Environment environment) { + ZookeeperClient zookeeperClient = new ZookeeperClient(updateHandler, environment); + try { + zookeeperClient.refreshZookeeperConfig(); + } catch (Exception e) { + throw new IllegalStateException("Set up zookeeper config failed.", e); + } + } + + public class UpdateHandler { + public void handle(Map current, Map last) { + ConfigurationChangedEvent event = ConfigurationChangedEvent.createIncremental(current, last); + LOGGER.info("Dynamic configuration changed: {}", event.getChanged()); + valueCache.putAll(event.getAdded()); + valueCache.putAll(event.getUpdated()); + event.getDeleted().forEach((k, v) -> valueCache.remove(k)); + EventManager.post(event); + } + } + + @Override + public PropertySource create(Environment environment) { + init(environment); + return new MapPropertySource(SOURCE_NAME, valueCache); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/dynamic-config/config-zookeeper/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/dynamic-config/config-zookeeper/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..7b3b32c721d --- /dev/null +++ b/dynamic-config/config-zookeeper/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.zookeeper.ZookeeperDynamicPropertiesSource diff --git a/dynamic-config/pom.xml b/dynamic-config/pom.xml index 859224c81a1..d5777cd654c 100644 --- a/dynamic-config/pom.xml +++ b/dynamic-config/pom.xml @@ -23,7 +23,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default 4.0.0 @@ -36,6 +36,9 @@ config-cc config-nacos config-kie + config-zookeeper + config-etcd + config-consul diff --git a/edge/edge-core/pom.xml b/edge/edge-core/pom.xml index 75c46bfb365..0a75f8e33c6 100644 --- a/edge/edge-core/pom.xml +++ b/edge/edge-core/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb edge - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT edge-core Java Chassis::Edge::Core @@ -42,13 +42,13 @@ - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test @@ -61,5 +61,10 @@ swagger-generator-jaxrs test + + org.mockito + mockito-inline + test + diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java index 7cdc43ea038..c29c066b800 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/AbstractEdgeDispatcher.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.edge.core; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.Response.Status; import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; @@ -34,10 +34,6 @@ public abstract class AbstractEdgeDispatcher extends AbstractVertxHttpDispatcher { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractEdgeDispatcher.class); - protected EdgeInvocation createEdgeInvocation() { - return new EdgeInvocation(); - } - protected void onFailure(RoutingContext context) { LOGGER.error("edge server failed.", context.failure()); HttpServerResponse response = context.response(); diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CommonHttpEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CommonHttpEdgeDispatcher.java index c3e02f7daa9..0f7e59bb0d2 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CommonHttpEdgeDispatcher.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CommonHttpEdgeDispatcher.java @@ -20,27 +20,33 @@ import java.util.HashMap; import java.util.Map; +import org.apache.servicecomb.common.rest.route.URLMappedConfigurationItem; +import org.apache.servicecomb.common.rest.route.URLMappedConfigurationLoader; +import org.apache.servicecomb.common.rest.route.Utils; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.config.ConfigurationChangedEvent; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.cache.VersionedCache; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; +import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; import org.apache.servicecomb.loadbalance.ExtensionsManager; +import org.apache.servicecomb.loadbalance.LoadBalanceFilter; import org.apache.servicecomb.loadbalance.LoadBalancer; -import org.apache.servicecomb.loadbalance.LoadbalanceHandler; import org.apache.servicecomb.loadbalance.RuleExt; import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter; -import org.apache.servicecomb.registry.RegistrationManager; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTree; import org.apache.servicecomb.transport.rest.client.Http2TransportHttpClientOptionsSPI; import org.apache.servicecomb.transport.rest.client.HttpTransportHttpClientOptionsSPI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicPropertyFactory; +import com.google.common.eventbus.Subscribe; import io.vertx.core.Future; import io.vertx.core.Handler; @@ -74,42 +80,64 @@ public class CommonHttpEdgeDispatcher extends AbstractEdgeDispatcher { private Map configurations = new HashMap<>(); - private DiscoveryTree discoveryTree; + private Environment environment; public CommonHttpEdgeDispatcher() { + + } + + // though this is an SPI, but add as beans. + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; if (this.enabled()) { loadConfigurations(); - discoveryTree = new DiscoveryTree(); - discoveryTree.addFilter(new ServerDiscoveryFilter()); } } + // Maybe future change to beans + protected DiscoveryTree getDiscoveryTree() { + return BeanUtils.getBean(DiscoveryTree.class); + } + + // Maybe future change to beans + protected Environment getEnvironment() { + return BeanUtils.getBean(Environment.class); + } + + // Maybe future change to beans + protected ExtensionsManager getExtensionsManager() { + return BeanUtils.getBean(ExtensionsManager.class); + } + @Override public int getOrder() { - return DynamicPropertyFactory.getInstance().getIntProperty(KEY_ORDER, 40_000).get(); + return LegacyPropertyFactory.getIntProperty(KEY_ORDER, 40_000); } @Override public boolean enabled() { - return DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, false).get(); + return environment.getProperty(KEY_ENABLED, boolean.class, false); } @Override public void init(Router router) { - String pattern = DynamicPropertyFactory.getInstance().getStringProperty(KEY_PATTERN, PATTERN_ANY).get(); + String pattern = environment.getProperty(KEY_PATTERN, PATTERN_ANY); router.routeWithRegex(pattern).failureHandler(this::onFailure).handler(this::onRequest); } private void loadConfigurations() { - ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory - .getBackingConfigurationSource(); - configurations = URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREFIX); - config.addConfigurationListener(event -> { - if (event.getPropertyName().startsWith(KEY_MAPPING_PREFIX)) { - LOG.info("Map rule have been changed. Reload configurations. Event=" + event.getType()); - configurations = URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREFIX); + configurations = URLMappedConfigurationLoader.loadConfigurations(environment, KEY_MAPPING_PREFIX); + } + + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + for (String changed : event.getChanged()) { + if (changed.startsWith(KEY_MAPPING_PREFIX)) { + loadConfigurations(); + break; } - }); + } } protected void onRequest(RoutingContext context) { @@ -133,8 +161,8 @@ public String getMicroserviceName() { } }; - LoadBalancer loadBalancer = getOrCreateLoadBalancer(invocation, configurationItem.getMicroserviceName(), - configurationItem.getVersionRule()); + LoadBalancer loadBalancer = getOrCreateLoadBalancer(invocation, configurationItem.getMicroserviceName() + ); ServiceCombServer server = loadBalancer.chooseServer(invocation); if (server == null) { LOG.warn("no available server for service {}", configurationItem.getMicroserviceName()); @@ -162,24 +190,26 @@ public String getMicroserviceName() { httpClient .request(requestOptions).compose(httpClientRequest -> { - context.request().headers().forEach((header) -> httpClientRequest.headers().set(header.getKey(), header.getValue())); - - context.request().resume(); - context.request().handler(httpClientRequest::write); - context.request().endHandler((v) -> httpClientRequest.end()); - - return httpClientRequest.response().compose(httpClientResponse -> { - context.response().setStatusCode(httpClientResponse.statusCode()); - httpClientResponse.headers().forEach((header) -> context.response().headers().set(header.getKey(), header.getValue())); - httpClientResponse.handler(this.responseHandler(context)); - httpClientResponse.endHandler((v) -> context.response().end()); - return Future.succeededFuture(); - }); - }).onFailure(failure -> { - LOG.warn("send request to target {}:{} failed, cause {}", endpointObject.getHostOrIp(), endpointObject.getPort(), - failure.getMessage()); - serverNotReadyResponse(context); - }); + context.request().headers() + .forEach((header) -> httpClientRequest.headers().set(header.getKey(), header.getValue())); + + context.request().resume(); + context.request().handler(httpClientRequest::write); + context.request().endHandler((v) -> httpClientRequest.end()); + + return httpClientRequest.response().compose(httpClientResponse -> { + context.response().setStatusCode(httpClientResponse.statusCode()); + httpClientResponse.headers() + .forEach((header) -> context.response().headers().set(header.getKey(), header.getValue())); + httpClientResponse.handler(this.responseHandler(context)); + httpClientResponse.endHandler((v) -> context.response().end()); + return Future.succeededFuture(); + }); + }).onFailure(failure -> { + LOG.warn("send request to target {}:{} failed, cause {}", endpointObject.getHostOrIp(), endpointObject.getPort(), + failure.getMessage()); + serverNotReadyResponse(context); + }); } private void serverNotReadyResponse(RoutingContext context) { @@ -192,20 +222,19 @@ protected Handler responseHandler(RoutingContext routingContext) { return data -> routingContext.response().write(data); } - protected LoadBalancer getOrCreateLoadBalancer(Invocation invocation, String microserviceName, String versionRule) { + protected LoadBalancer getOrCreateLoadBalancer(Invocation invocation, String microserviceName) { DiscoveryContext context = new DiscoveryContext(); context.setInputParameters(invocation); - VersionedCache serversVersionedCache = discoveryTree.discovery(context, - RegistrationManager.INSTANCE.getMicroservice().getAppId(), - microserviceName, - versionRule); - invocation.addLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST, serversVersionedCache.data()); + VersionedCache serversVersionedCache = getDiscoveryTree().discovery(context, + BootStrapProperties.readApplication(environment), + microserviceName); + invocation.addLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST, serversVersionedCache.data()); return loadBalancerMap .computeIfAbsent(microserviceName, name -> createLoadBalancer(microserviceName)); } private LoadBalancer createLoadBalancer(String microserviceName) { - RuleExt rule = ExtensionsManager.createLoadBalancerRule(microserviceName); + RuleExt rule = getExtensionsManager().createLoadBalancerRule(microserviceName); return new LoadBalancer(rule, microserviceName); } diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java deleted file mode 100644 index cb92aec8854..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/CompatiblePathVersionMapper.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.edge.core; - -import java.util.Map; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.registry.version.VersionRule; -import org.apache.servicecomb.registry.version.VersionRuleUtils; -import org.springframework.util.StringUtils; - -public class CompatiblePathVersionMapper { - // v1 -> 1.0.0-2.0.0 - // v2 -> 2.0.0-3.0.0 - private Map mapper = new ConcurrentHashMapEx<>(); - - public VersionRule getOrCreate(String pathVersion) { - return mapper.computeIfAbsent(pathVersion, this::createVersionRule); - } - - // v + number - protected VersionRule createVersionRule(String pathVersion) { - if (StringUtils.isEmpty(pathVersion) || Character.toUpperCase(pathVersion.charAt(0)) != 'V') { - throw new ServiceCombException( - String.format("pathVersion \"%s\" is invalid, format must be v+number or V+number.", pathVersion)); - } - - int number = 0; - try { - number = Integer.parseInt(pathVersion.substring(1)); - } catch (NumberFormatException e) { - throw new ServiceCombException( - String.format("pathVersion \"%s\" is invalid, format must be v+number or V+number.", pathVersion), e); - } - - if (number < 0 || number > Short.MAX_VALUE) { - throw new ServiceCombException( - String.format("pathVersion \"%s\" is invalid, version range is [0, %d].", pathVersion, Short.MAX_VALUE)); - } - - if (number == Short.MAX_VALUE) { - return VersionRuleUtils.getOrCreate(String.format("%d.0.0+", number)); - } - - return VersionRuleUtils.getOrCreate(String.format("%d.0.0-%d.0.0", number, number + 1)); - } -} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java index e85fb289cb6..56108a8cf1a 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java @@ -18,16 +18,17 @@ package org.apache.servicecomb.edge.core; import org.apache.servicecomb.common.rest.RestProducerInvocationFlow; -import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.common.rest.route.Utils; import org.apache.servicecomb.core.invocation.InvocationCreator; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; import org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse; -import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; import com.google.common.annotations.VisibleForTesting; -import com.netflix.config.DynamicPropertyFactory; import io.vertx.codegen.annotations.Nullable; import io.vertx.ext.web.Router; @@ -44,38 +45,36 @@ public class DefaultEdgeDispatcher extends AbstractEdgeDispatcher { private static final String KEY_PREFIX = "servicecomb.http.dispatcher.edge.default.prefix"; - private static final String KEY_WITH_VERSION = "servicecomb.http.dispatcher.edge.default.withVersion"; - private static final String KEY_PREFIX_SEGMENT_COUNT = "servicecomb.http.dispatcher.edge.default.prefixSegmentCount"; public static final String MICROSERVICE_NAME = "param0"; - public static final String VERSION = "param1"; - - private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper(); - - private String prefix; + private int prefixSegmentCount; - private boolean withVersion; + private Environment environment; - private int prefixSegmentCount; + // though this is an SPI, but add as beans. + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } @Override public int getOrder() { - return DynamicPropertyFactory.getInstance().getIntProperty(KEY_ORDER, 20_000).get(); + // can not use environment, add as beans is later than instantiate SPI + return LegacyPropertyFactory.getIntProperty(KEY_ORDER, 20_000); } @Override public boolean enabled() { - return DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, false).get(); + return environment.getProperty(KEY_ENABLED, boolean.class, false); } @Override public void init(Router router) { - prefix = DynamicPropertyFactory.getInstance().getStringProperty(KEY_PREFIX, "api").get(); - withVersion = DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_WITH_VERSION, true).get(); - prefixSegmentCount = DynamicPropertyFactory.getInstance().getIntProperty(KEY_PREFIX_SEGMENT_COUNT, 1).get(); - String regex = generateRouteRegex(prefix, withVersion); + String prefix = environment.getProperty(KEY_PREFIX, "api"); + prefixSegmentCount = environment.getProperty(KEY_PREFIX_SEGMENT_COUNT, int.class, 1); + String regex = generateRouteRegex(prefix, false); // cookies handler are enabled by default start from 3.8.3 router.routeWithRegex(regex).handler(createBodyHandler()); @@ -90,19 +89,9 @@ String generateRouteRegex(String prefix, boolean withVersion) { protected void onRequest(RoutingContext context) { String microserviceName = extractMicroserviceName(context); - String versionRule = extractVersionRule(context); String path = Utils.findActualPath(context.request().path(), prefixSegmentCount); - if (isFilterChainEnabled()) { - requestByFilter(context, microserviceName, versionRule, path); - return; - } - - requestByHandler(context, microserviceName, versionRule, path); - } - - protected boolean isFilterChainEnabled() { - return SCBEngine.getInstance().isFilterChainEnabled(); + requestByFilter(context, microserviceName, path); } @Nullable @@ -110,28 +99,12 @@ private String extractMicroserviceName(RoutingContext context) { return context.pathParam(MICROSERVICE_NAME); } - private String extractVersionRule(RoutingContext context) { - if (withVersion) { - String pathVersion = context.pathParam(VERSION); - return versionMapper.getOrCreate(pathVersion).getVersionRule(); - } - - return DefinitionConst.VERSION_RULE_ALL; - } - - protected void requestByFilter(RoutingContext context, String microserviceName, String versionRule, String path) { + protected void requestByFilter(RoutingContext context, String microserviceName, String path) { HttpServletRequestEx requestEx = new VertxServerRequestToHttpServletRequest(context); HttpServletResponseEx responseEx = new VertxServerResponseToHttpServletResponse(context.response()); InvocationCreator creator = new EdgeInvocationCreator(context, requestEx, responseEx, - microserviceName, versionRule, path); + microserviceName, path); new RestProducerInvocationFlow(creator, requestEx, responseEx) .run(); } - - private void requestByHandler(RoutingContext context, String microserviceName, String versionRule, String path) { - EdgeInvocation edgeInvocation = createEdgeInvocation(); - edgeInvocation.setVersionRule(versionRule); - edgeInvocation.init(microserviceName, context, path, httpServerFilters); - edgeInvocation.edgeInvoke(); - } } diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java deleted file mode 100644 index 95b67ddc3e2..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderClientFilter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.edge.core; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.function.BiConsumer; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.common.rest.filter.HttpClientFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.ConfigurationManager; -import com.netflix.config.DynamicPropertyFactory; - -public class EdgeAddHeaderClientFilter implements HttpClientFilter { - private static final Logger LOGGER = LoggerFactory.getLogger(EdgeAddHeaderClientFilter.class); - - private static final String PREFIX = "servicecomb.edge.filter.addHeader"; - - private static final String KEY_ENABLED = PREFIX + ".enabled"; - - private static final String KEY_HEADERS = PREFIX + ".allowedHeaders"; - - private List publicHeaders = new ArrayList<>(); - - private boolean enabled = false; - - public EdgeAddHeaderClientFilter() { - init(); - ConfigurationManager.getConfigInstance() - .addConfigurationListener(event -> { - if (StringUtils.startsWith(event.getPropertyName(), PREFIX)) { - LOGGER.info("Public headers config have been changed. Event=" + event.getType()); - init(); - } - }); - } - - private void init() { - enabled = DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, false).get(); - String publicHeaderStr = DynamicPropertyFactory.getInstance().getStringProperty(KEY_HEADERS, "").get(); - String[] split = publicHeaderStr.split(","); - if (split.length > 0) { - publicHeaders = Arrays.asList(split); - } - } - - @Override - public int getOrder() { - return 0; - } - - @Override - public boolean enabled() { - return enabled; - } - - @Override - public void beforeSendRequest(Invocation invocation, HttpServletRequestEx requestEx) { - addHeaders(invocation, requestEx::addHeader); - } - - public void addHeaders(Invocation invocation, BiConsumer headerAdder) { - if (!invocation.isEdge()) { - return; - } - - HttpServletRequestEx oldRequest = invocation.getRequestEx(); - publicHeaders.forEach(key -> { - String value = oldRequest.getHeader(key); - if (StringUtils.isNotEmpty(value)) { - headerAdder.accept(key, value); - } - }); - } - - @Override - public Response afterReceiveResponse(Invocation invocation, HttpServletResponseEx responseEx) { - return null; - } -} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java index 0ea56584a4f..92594e6157a 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java @@ -16,39 +16,93 @@ */ package org.apache.servicecomb.edge.core; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.CompletableFuture; -import javax.annotation.Nonnull; - +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.swagger.invocation.Response; import org.apache.servicecomb.transport.rest.client.RestClientTransportContext; -import org.springframework.stereotype.Component; +import org.springframework.core.env.Environment; + +import com.google.common.eventbus.Subscribe; -@Component -public class EdgeAddHeaderFilter implements ConsumerFilter { +public class EdgeAddHeaderFilter extends AbstractFilter implements EdgeFilter { public static final String NAME = "edge-add-headers"; - private EdgeAddHeaderClientFilter filter = new EdgeAddHeaderClientFilter(); + private static final String PREFIX = "servicecomb.edge.filter.addHeader"; + + private static final String KEY_HEADERS = PREFIX + ".allowedHeaders"; + + private final Environment environment; + + private List publicHeaders = new ArrayList<>(); + + public EdgeAddHeaderFilter(Environment environment) { + this.environment = environment; + init(); + EventManager.register(this); + } + + @Subscribe + @SuppressWarnings("unused") + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + for (String changed : event.getChanged()) { + if (changed.startsWith(PREFIX)) { + init(); + break; + } + } + } + + private void init() { + String publicHeaderStr = environment.getProperty(KEY_HEADERS); + if (StringUtils.isEmpty(publicHeaderStr)) { + return; + } + publicHeaders = Arrays.asList(publicHeaderStr.split(",")); + } - @Nonnull @Override public String getName() { return NAME; } @Override - public boolean isEnabled() { - return filter.enabled(); + public boolean enabledForTransport(String transport) { + return CoreConst.RESTFUL.equals(transport); + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1995; } @Override public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (publicHeaders.isEmpty()) { + return nextNode.onFilter(invocation); + } + RestClientTransportContext transportContext = invocation.getTransportContext(); - return CompletableFuture.completedFuture(null) - .thenAccept(v -> filter.addHeaders(invocation, transportContext.getHttpClientRequest()::putHeader)) - .thenCompose(v -> nextNode.onFilter(invocation)); + HttpServletRequestEx oldRequest = invocation.getRequestEx(); + publicHeaders.forEach(key -> { + String value = oldRequest.getHeader(key); + if (StringUtils.isNotEmpty(value)) { + transportContext.getHttpClientRequest().putHeader(key, value); + } + }); + + return nextNode.onFilter(invocation); } } diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeBootListener.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeBootListener.java index 55ee39261ad..144dc2c6224 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeBootListener.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeBootListener.java @@ -17,41 +17,18 @@ package org.apache.servicecomb.edge.core; -import org.apache.commons.configuration.Configuration; import org.apache.servicecomb.core.BootListener; import org.apache.servicecomb.core.executor.ExecutorManager; -import org.apache.servicecomb.transport.rest.client.TransportClientConfig; import org.apache.servicecomb.transport.rest.vertx.TransportConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; -import com.netflix.config.DynamicPropertyFactory; - -@Component public class EdgeBootListener implements BootListener { - private static final Logger LOGGER = LoggerFactory.getLogger(EdgeBootListener.class); - @Override public void onBootEvent(BootEvent event) { if (!EventType.BEFORE_PRODUCER_PROVIDER.equals(event.getEventType())) { return; } - TransportClientConfig.setRestTransportClientCls(EdgeRestTransportClient.class); TransportConfig.setRestServerVerticle(EdgeRestServerVerticle.class); - - String defaultExecutor = DynamicPropertyFactory.getInstance() - .getStringProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, null) - .get(); - if (defaultExecutor != null) { - LOGGER.info("Edge service default executor is {}.", defaultExecutor); - return; - } - - // change default to reactive mode - Configuration configuration = (Configuration) DynamicPropertyFactory.getBackingConfigurationSource(); - configuration.setProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, ExecutorManager.EXECUTOR_REACTIVE); - LOGGER.info("Set ReactiveExecutor to be edge service default executor."); + ExecutorManager.setExecutorDefault(ExecutorManager.EXECUTOR_REACTIVE); } } diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeCoreConfiguration.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeCoreConfiguration.java new file mode 100644 index 00000000000..6fa0457c7fc --- /dev/null +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeCoreConfiguration.java @@ -0,0 +1,34 @@ +/* + * 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.edge.core; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class EdgeCoreConfiguration { + @Bean + public EdgeBootListener scbEdgeBootListener() { + return new EdgeBootListener(); + } + + @Bean + public EdgeAddHeaderFilter scbEdgeAddHeaderFilter(Environment environment) { + return new EdgeAddHeaderFilter(environment); + } +} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocation.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocation.java deleted file mode 100644 index 9c502fb0115..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocation.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.edge.core; - -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.common.rest.AbstractRestInvocation; -import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.common.rest.locator.OperationLocator; -import org.apache.servicecomb.common.rest.locator.ServicePathManager; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.invocation.InvocationFactory; -import org.apache.servicecomb.core.provider.consumer.MicroserviceReferenceConfig; -import org.apache.servicecomb.core.provider.consumer.ReactiveResponseExecutor; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.foundation.vertx.executor.VertxContextExecutor; -import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; -import org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse; - -import io.vertx.core.Vertx; -import io.vertx.ext.web.RoutingContext; - -public class EdgeInvocation extends AbstractRestInvocation { - public static final String EDGE_INVOCATION_CONTEXT = "edgeInvocationContext"; - - protected String microserviceName; - - protected MicroserviceReferenceConfig microserviceReferenceConfig; - - protected ReferenceConfig referenceConfig; - - protected String versionRule = null;//DefinitionConst.VERSION_RULE_ALL; - - protected RoutingContext routingContext; - - public void init(String microserviceName, RoutingContext context, String path, - List httpServerFilters) { - this.microserviceName = microserviceName; - this.requestEx = new VertxServerRequestToHttpServletRequest(context, path); - this.responseEx = new VertxServerResponseToHttpServletResponse(context.response()); - this.routingContext = context; - this.httpServerFilters = httpServerFilters; - requestEx.setAttribute(RestConst.REST_REQUEST, requestEx); - } - - public void edgeInvoke() { - findMicroserviceVersionMeta().whenCompleteAsync((r, e) -> { - if (e != null) { - sendFailResponse(e); - } else { - try { - microserviceReferenceConfig = r; - findRestOperation(microserviceReferenceConfig.getLatestMicroserviceMeta()); - scheduleInvocation(); - } catch (Throwable error) { - sendFailResponse(error); - } - } - }, VertxContextExecutor.create(Vertx.currentContext())); - } - - protected CompletableFuture findMicroserviceVersionMeta() { - return SCBEngine.getInstance() - .createMicroserviceReferenceConfigAsync(microserviceName, chooseVersionRule()); - } - - public void setVersionRule(String versionRule) { - this.versionRule = versionRule; - } - - // another possible rule: - // path is: /msName/version/..... - // version in path is v1 or v2 and so on - // map version to VersionRule: - // v1->1.0.0-2.0.0 - // v2->2.0.0-3.0.0 - // that means if a(1.x.x) bigger then b(1.y.y), then a compatible to b - // but a(2.x.x) not compatible to b - protected String chooseVersionRule() { - // this will use all instance of the microservice - // and this required all new version compatible to old version - return versionRule; - } - - @Override - protected OperationLocator locateOperation(ServicePathManager servicePathManager) { - return servicePathManager.consumerLocateOperation(requestEx.getRequestURI(), requestEx.getMethod()); - } - - @Override - protected void createInvocation() { - ReferenceConfig referenceConfig = microserviceReferenceConfig - .createReferenceConfig(restOperationMeta.getOperationMeta()); - - this.invocation = InvocationFactory.forConsumer(referenceConfig, - restOperationMeta.getOperationMeta(), - restOperationMeta.getOperationMeta().buildBaseConsumerRuntimeType(), - null); - this.invocation.setSync(false); - this.invocation.setEdge(true); - this.invocation.getHandlerContext().put(EDGE_INVOCATION_CONTEXT, Vertx.currentContext()); - this.invocation.setResponseExecutor(new ReactiveResponseExecutor()); - this.routingContext.put(RestConst.REST_INVOCATION_CONTEXT, invocation); - } - - @Override - protected void setContext() throws Exception { - // do not read InvocationContext from HTTP header, for security reason - } -} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java index 17d67a647f0..309548a5b38 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeInvocationCreator.java @@ -16,13 +16,12 @@ */ package org.apache.servicecomb.edge.core; -import static org.apache.servicecomb.edge.core.EdgeInvocation.EDGE_INVOCATION_CONTEXT; - import java.util.concurrent.CompletableFuture; import org.apache.servicecomb.common.rest.RestVertxProducerInvocationCreator; import org.apache.servicecomb.common.rest.locator.OperationLocator; import org.apache.servicecomb.common.rest.locator.ServicePathManager; +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.invocation.InvocationFactory; @@ -35,9 +34,9 @@ import io.vertx.ext.web.RoutingContext; public class EdgeInvocationCreator extends RestVertxProducerInvocationCreator { - protected final String microserviceName; + public static final String EDGE_INVOCATION_CONTEXT = "edgeInvocationContext"; - protected final String versionRule; + protected final String microserviceName; protected final String path; @@ -45,11 +44,13 @@ public class EdgeInvocationCreator extends RestVertxProducerInvocationCreator { public EdgeInvocationCreator(RoutingContext routingContext, HttpServletRequestEx requestEx, HttpServletResponseEx responseEx, - String microserviceName, String versionRule, String path) { - super(routingContext, null, null, requestEx, responseEx); + String microserviceName, String path) { + // Set endpoint before load balance because edge service will use RESTFUL transport filters. + super(routingContext, null, + SCBEngine.getInstance().getTransportManager().findTransport(CoreConst.RESTFUL).getEndpoint(), + requestEx, responseEx); this.microserviceName = microserviceName; - this.versionRule = versionRule; this.path = path; } @@ -61,10 +62,10 @@ public CompletableFuture createAsync() { protected CompletableFuture createMicroserviceReferenceConfig() { return SCBEngine.getInstance() - .createMicroserviceReferenceConfigAsync(microserviceName, versionRule) + .getOrCreateReferenceConfigAsync(microserviceName) .thenAccept(mrc -> { this.microserviceReferenceConfig = mrc; - this.microserviceMeta = mrc.getLatestMicroserviceMeta(); + this.microserviceMeta = mrc.getMicroserviceMeta(); }); } @@ -73,11 +74,6 @@ protected OperationLocator locateOperation(ServicePathManager servicePathManager return servicePathManager.consumerLocateOperation(path, requestEx.getMethod()); } - @Override - protected void initInvocationContext(Invocation invocation) { - // do not read InvocationContext from HTTP header, for security reason - } - @Override protected Invocation createInstance() { ReferenceConfig referenceConfig = microserviceReferenceConfig @@ -88,7 +84,8 @@ protected Invocation createInstance() { restOperationMeta.getOperationMeta().buildBaseConsumerRuntimeType(), null); invocation.setSync(false); - invocation.setEdge(true); + invocation.setEdge(); + invocation.setEndpoint(endpoint); // ensure transport name is correct invocation.addLocalContext(EDGE_INVOCATION_CONTEXT, Vertx.currentContext()); return invocation; diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java deleted file mode 100644 index f8229e085f1..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeRestTransportClient.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.edge.core; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClients; -import org.apache.servicecomb.transport.rest.client.Http2TransportHttpClientOptionsSPI; -import org.apache.servicecomb.transport.rest.client.HttpTransportHttpClientOptionsSPI; -import org.apache.servicecomb.transport.rest.client.RestTransportClient; - -import io.vertx.core.Context; - -public class EdgeRestTransportClient extends RestTransportClient { - @Override - protected HttpClientWithContext findHttpClientPool(Invocation invocation) { - Context invocationContext = (Context) invocation.getHandlerContext().get(EdgeInvocation.EDGE_INVOCATION_CONTEXT); - - URIEndpointObject endpoint = (URIEndpointObject) invocation.getEndpoint().getAddress(); - String clientName = endpoint.isHttp2Enabled() ? - Http2TransportHttpClientOptionsSPI.CLIENT_NAME : - HttpTransportHttpClientOptionsSPI.CLIENT_NAME; - return HttpClients.getClient(clientName, invocation.isSync(), invocationContext); - } -} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java deleted file mode 100644 index 71968af9c36..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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.edge.core; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.swagger.invocation.InvocationType; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.context.TransportContext; -import org.springframework.stereotype.Component; - -@Component -public class EdgeServerCodecFilter extends RestServerCodecFilter { - public static final String NAME = "edge-server-codec"; - - @Nonnull - @Override - public String getName() { - return NAME; - } - - @Nonnull - @Override - public List getInvocationTypes() { - return Collections.singletonList(InvocationType.CONSUMER); - } - - @Override - public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { - if (invocation.getRequestEx() == null) { - // to support normal consumer invocation in edge process - return nextNode.onFilter(invocation); - } - - return super.onFilter(invocation, nextNode); - } - - // save and restore transportContext to support edge invocation - @Override - protected CompletableFuture invokeNext(Invocation invocation, FilterNode nextNode) { - TransportContext transportContext = invocation.getTransportContext(); - return nextNode.onFilter(invocation) - .whenComplete((r, e) -> invocation.setTransportContext(transportContext)); - } -} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationLoader.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationLoader.java deleted file mode 100644 index a6f7522fd79..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationLoader.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.edge.core; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.regex.Pattern; - -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicPropertyFactory; - -public class URLMappedConfigurationLoader { - private static final Logger LOG = LoggerFactory.getLogger(URLMappedConfigurationLoader.class); - - private static final String KEY_MAPPING_PATH = ".path"; - - private static final String KEY_MAPPING_SERVICE_NAME = "%s.%s.microserviceName"; - - private static final String KEY_MAPPING_VERSION_RULE = "%s.%s.versionRule"; - - private static final String KEY_MAPPING_PREFIX_SEGMENT_COUNT = "%s.%s.prefixSegmentCount"; - - public static Map loadConfigurations( - ConcurrentCompositeConfiguration config, String configPrefix) { - Map configurations = new HashMap<>(); - Iterator configsItems = config.getKeys(configPrefix); - while (configsItems.hasNext()) { - String pathKey = configsItems.next(); - if (pathKey.endsWith(KEY_MAPPING_PATH)) { - URLMappedConfigurationItem configurationItem = new URLMappedConfigurationItem(); - String pattern = DynamicPropertyFactory.getInstance() - .getStringProperty(pathKey, null).get(); - if (StringUtils.isEmpty(pattern)) { - continue; - } - configurationItem.setPattern(Pattern.compile(pattern)); - configurationItem.setStringPattern(pattern); - String pathKeyItem = pathKey - .substring(configPrefix.length() + 1, pathKey.length() - KEY_MAPPING_PATH.length()); - configurationItem.setMicroserviceName(DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(KEY_MAPPING_SERVICE_NAME, configPrefix, pathKeyItem), null).get()); - if (StringUtils.isEmpty(configurationItem.getMicroserviceName())) { - continue; - } - configurationItem.setPrefixSegmentCount(DynamicPropertyFactory.getInstance() - .getIntProperty(String.format(KEY_MAPPING_PREFIX_SEGMENT_COUNT, configPrefix, pathKeyItem), 0).get()); - configurationItem.setVersionRule(DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(KEY_MAPPING_VERSION_RULE, configPrefix, pathKeyItem), "0.0.0+").get()); - configurations.put(pathKeyItem, configurationItem); - } - } - logConfigurations(configurations); - return configurations; - } - - private static void logConfigurations(Map configurations) { - configurations.entrySet().forEach(stringConfigurationItemEntry -> { - URLMappedConfigurationItem item = stringConfigurationItemEntry.getValue(); - LOG.info("config item: key=" + stringConfigurationItemEntry.getKey() + ";pattern=" + item.getStringPattern() - + ";service=" + item.getMicroserviceName() + ";versionRule=" + item.getVersionRule()); - }); - } -} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java index 014c1e9ef4d..d4e456c098f 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java @@ -20,22 +20,33 @@ import java.util.HashMap; import java.util.Map; +import org.apache.servicecomb.common.rest.RestProducerInvocationFlow; +import org.apache.servicecomb.common.rest.route.URLMappedConfigurationItem; +import org.apache.servicecomb.common.rest.route.URLMappedConfigurationLoader; +import org.apache.servicecomb.common.rest.route.Utils; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.core.invocation.InvocationCreator; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; +import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; +import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; +import org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse; import org.apache.servicecomb.transport.rest.vertx.RestBodyHandler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicPropertyFactory; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.eventbus.Subscribe; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.PlatformHandler; /** * Provide a URL mapping based dispatcher. Users configure witch URL patterns dispatch to a target service. */ public class URLMappedEdgeDispatcher extends AbstractEdgeDispatcher { - private static final Logger LOG = LoggerFactory.getLogger(URLMappedEdgeDispatcher.class); - public static final String CONFIGURATION_ITEM = "URLMappedConfigurationItem"; private static final String PATTERN_ANY = "/(.*)"; @@ -50,42 +61,58 @@ public class URLMappedEdgeDispatcher extends AbstractEdgeDispatcher { private Map configurations = new HashMap<>(); + private Environment environment; + public URLMappedEdgeDispatcher() { + EventManager.register(this); + } + + // though this is an SPI, but add as beans. + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; if (this.enabled()) { loadConfigurations(); } } + @VisibleForTesting + public Map getConfigurations() { + return configurations; + } + @Override public int getOrder() { - return DynamicPropertyFactory.getInstance().getIntProperty(KEY_ORDER, 30_000).get(); + return LegacyPropertyFactory.getIntProperty(KEY_ORDER, 30_000); } @Override public boolean enabled() { - return DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, false).get(); + return environment.getProperty(KEY_ENABLED, boolean.class, false); } @Override public void init(Router router) { // cookies handler are enabled by default start from 3.8.3 - String pattern = DynamicPropertyFactory.getInstance().getStringProperty(KEY_PATTERN, PATTERN_ANY).get(); + String pattern = environment.getProperty(KEY_PATTERN, PATTERN_ANY); router.routeWithRegex(pattern).failureHandler(this::onFailure) - .handler(this::preCheck) + .handler((PlatformHandler) URLMappedEdgeDispatcher.this::preCheck) .handler(createBodyHandler()) .handler(this::onRequest); } private void loadConfigurations() { - ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory - .getBackingConfigurationSource(); - configurations = URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREFIX); - config.addConfigurationListener(event -> { - if (event.getPropertyName().startsWith(KEY_MAPPING_PREFIX)) { - LOG.info("Map rule have been changed. Reload configurations. Event=" + event.getType()); - configurations = URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREFIX); + configurations = URLMappedConfigurationLoader.loadConfigurations(environment, KEY_MAPPING_PREFIX); + } + + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + for (String changed : event.getChanged()) { + if (changed.startsWith(KEY_MAPPING_PREFIX)) { + loadConfigurations(); + break; } - }); + } } protected void preCheck(RoutingContext context) { @@ -113,12 +140,16 @@ protected void onRequest(RoutingContext context) { String path = Utils.findActualPath(context.request().path(), configurationItem.getPrefixSegmentCount()); - EdgeInvocation edgeInvocation = createEdgeInvocation(); - if (configurationItem.getVersionRule() != null) { - edgeInvocation.setVersionRule(configurationItem.getVersionRule()); - } - edgeInvocation.init(configurationItem.getMicroserviceName(), context, path, httpServerFilters); - edgeInvocation.edgeInvoke(); + requestByFilter(context, configurationItem, path); + } + + protected void requestByFilter(RoutingContext context, URLMappedConfigurationItem configurationItem, String path) { + HttpServletRequestEx requestEx = new VertxServerRequestToHttpServletRequest(context); + HttpServletResponseEx responseEx = new VertxServerResponseToHttpServletResponse(context.response()); + InvocationCreator creator = new EdgeInvocationCreator(context, requestEx, responseEx, + configurationItem.getMicroserviceName(), path); + new RestProducerInvocationFlow(creator, requestEx, responseEx) + .run(); } private URLMappedConfigurationItem findConfigurationItem(String path) { diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/Utils.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/Utils.java deleted file mode 100644 index 9bbefb9f0d1..00000000000 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/Utils.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.edge.core; - -/** - * Commonly used methods in this package. - */ -public final class Utils { - private Utils() { - - } - - /** - * Get the actual path without prefix - * @param path full path - * @param pathIndex the index of / that after prefix - * @return actual path - */ - public static String findActualPath(String path, int pathIndex) { - if (pathIndex <= 0) { - return path; - } - - int fromIndex = 0; - int counter = pathIndex; - char[] chars = path.toCharArray(); - for (int i = 0; i < chars.length; i++) { - if (chars[i] == '/') { - if (--counter < 0) { - fromIndex = i; - break; - } - } - } - return fromIndex > 0 ? path.substring(fromIndex) : ""; - } -} diff --git a/edge/edge-core/src/main/resources/META-INF/microservice.yaml b/edge/edge-core/src/main/resources/META-INF/microservice.yaml new file mode 100644 index 00000000000..a456c2868b2 --- /dev/null +++ b/edge/edge-core/src/main/resources/META-INF/microservice.yaml @@ -0,0 +1,23 @@ +## --------------------------------------------------------------------------- +## 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-config-order: -500 + +servicecomb: + context: + # do not decode invocation context for edge service by default + decodeInvocationContext: false diff --git a/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter deleted file mode 100644 index c07a4b7621f..00000000000 --- a/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.edge.core.EdgeAddHeaderClientFilter diff --git a/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher index 0f1d5d6dea7..6a672cefffd 100644 --- a/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher +++ b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher @@ -17,4 +17,4 @@ org.apache.servicecomb.edge.core.DefaultEdgeDispatcher org.apache.servicecomb.edge.core.URLMappedEdgeDispatcher -org.apache.servicecomb.edge.core.CommonHttpEdgeDispatcher \ No newline at end of file +org.apache.servicecomb.edge.core.CommonHttpEdgeDispatcher diff --git a/edge/edge-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/edge/edge-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..aa087dba015 --- /dev/null +++ b/edge/edge-core/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.servicecomb.edge.core.EdgeCoreConfiguration diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestAbstractEdgeDispatcher.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestAbstractEdgeDispatcher.java index 09973cb4260..bbeceff2292 100644 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestAbstractEdgeDispatcher.java +++ b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestAbstractEdgeDispatcher.java @@ -17,24 +17,17 @@ package org.apache.servicecomb.edge.core; -import java.util.HashMap; -import java.util.Map; - import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.Test; import io.vertx.core.http.HttpServerResponse; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestAbstractEdgeDispatcher { - class AbstractEdgeDispatcherForTest extends AbstractEdgeDispatcher { + static class AbstractEdgeDispatcherForTest extends AbstractEdgeDispatcher { @Override public int getOrder() { return 0; @@ -46,51 +39,25 @@ public void init(Router router) { } @Test - public void onFailure(@Mocked RoutingContext context) { - Map map = new HashMap<>(); - HttpServerResponse response = new MockUp() { - @Mock - HttpServerResponse setStatusCode(int statusCode) { - map.put("code", statusCode); - return null; - } + public void onFailure() { + RoutingContext context = Mockito.mock(RoutingContext.class); - @Mock - HttpServerResponse setStatusMessage(String statusMessage) { - map.put("msg", statusMessage); - return null; - } - }.getMockInstance(); + HttpServerResponse response = Mockito.mock(HttpServerResponse.class); - new Expectations() { - { - context.failure(); - returns(new RuntimeExceptionWithoutStackTrace("failed"), null); - context.response(); - result = response; - } - }; + Mockito.when(context.response()).thenReturn(response); + Mockito.when(context.failure()).thenReturn(new RuntimeExceptionWithoutStackTrace("failed")); AbstractEdgeDispatcherForTest dispatcher = new AbstractEdgeDispatcherForTest(); dispatcher.onFailure(context); - Assert.assertEquals(502, map.get("code")); - Assert.assertEquals("Bad Gateway", map.get("msg")); + Mockito.verify(response).setStatusMessage("Bad Gateway"); + Mockito.verify(response).setStatusCode(502); - new Expectations() { - { - context.failure(); - returns(new InvocationException(401, "unauthorized", "unauthorized"), - new InvocationException(401, "unauthorized", "unauthorized")); - context.response(); - result = response; - } - }; + Mockito.when(context.failure()).thenReturn(new InvocationException(401, "unauthorized", "unauthorized")); dispatcher = new AbstractEdgeDispatcherForTest(); dispatcher.onFailure(context); - - Assert.assertEquals(401, map.get("code")); - Assert.assertEquals("unauthorized", map.get("msg")); + Mockito.verify(response).setStatusMessage("unauthorized"); + Mockito.verify(response).setStatusCode(401); } } diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestCompatiblePathVersionMapper.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestCompatiblePathVersionMapper.java deleted file mode 100644 index 2bfe7b03721..00000000000 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestCompatiblePathVersionMapper.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.edge.core; - -import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.registry.version.VersionRule; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestCompatiblePathVersionMapper { - CompatiblePathVersionMapper mapper = new CompatiblePathVersionMapper(); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void getOrCreate() { - VersionRule versionRule = mapper.getOrCreate("v1"); - - Assert.assertEquals("1.0.0.0-2.0.0.0", versionRule.getVersionRule()); - } - - @Test - public void createVersionRule_empty() { - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage(Matchers.is("pathVersion \"\" is invalid, format must be v+number or V+number.")); - - mapper.getOrCreate(""); - } - - @Test - public void createVersionRule_invalidFormat() { - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage(Matchers.is("pathVersion \"a1\" is invalid, format must be v+number or V+number.")); - - mapper.getOrCreate("a1"); - } - - @Test - public void createVersionRule_invalidNumber() { - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage(Matchers.is("pathVersion \"va\" is invalid, format must be v+number or V+number.")); - - mapper.getOrCreate("va"); - } - - @Test - public void createVersionRule_tooSmall() { - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage(Matchers.is("pathVersion \"v-1\" is invalid, version range is [0, 32767].")); - - mapper.getOrCreate("v-1"); - } - - @Test - public void createVersionRule_tooBig() { - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage(Matchers.is("pathVersion \"v32768\" is invalid, version range is [0, 32767].")); - - mapper.getOrCreate("v32768"); - } - - @Test - public void createVersionRule_32767() { - VersionRule versionRule = mapper.getOrCreate("v32767"); - - Assert.assertEquals("32767.0.0.0+", versionRule.getVersionRule()); - } -} diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java deleted file mode 100644 index 639eb0286e9..00000000000 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestDefaultEdgeDispatcher.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.edge.core; - -import static org.apache.servicecomb.edge.core.DefaultEdgeDispatcher.MICROSERVICE_NAME; -import static org.apache.servicecomb.edge.core.DefaultEdgeDispatcher.VERSION; - -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import io.vertx.core.Handler; -import io.vertx.core.http.HttpServerRequest; -import io.vertx.ext.web.Route; -import io.vertx.ext.web.Router; -import io.vertx.ext.web.RoutingContext; -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mocked; - -public class TestDefaultEdgeDispatcher { - @Before - public void setUp() { - - } - - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - - @Test - @SuppressWarnings("unchecked") - public void testOnRequest(@Mocked Router router, @Mocked Route route - , @Mocked RoutingContext context - , @Mocked HttpServerRequest requst - , @Mocked EdgeInvocation invocation) { - DefaultEdgeDispatcher dispatcher = new DefaultEdgeDispatcher() { - @Override - protected boolean isFilterChainEnabled() { - return false; - } - }; - - new Expectations(SCBEngine.class) { - { - router.routeWithRegex(dispatcher.generateRouteRegex("api", true)); - result = route; - route.handler((Handler) any); - result = route; - route.failureHandler((Handler) any); - result = route; - context.pathParam(MICROSERVICE_NAME); - result = "testService"; - context.pathParam(VERSION); - result = "v1"; - context.request(); - result = requst; - requst.path(); - result = "/api/testService/v1/hello"; - invocation.setVersionRule("1.0.0.0-2.0.0.0"); - invocation.init("testService", context, "/testService/v1/hello", - Deencapsulation.getField(dispatcher, "httpServerFilters")); - invocation.edgeInvoke(); - } - }; - dispatcher.init(router); - Assert.assertEquals(dispatcher.enabled(), false); - Assert.assertEquals(Utils.findActualPath("/api/test", 1), "/test"); - Assert.assertEquals(dispatcher.getOrder(), 20000); - - dispatcher.onRequest(context); - // assert done in expectations. - } -} diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestEdgeBootListener.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestEdgeBootListener.java deleted file mode 100644 index 992aad06c70..00000000000 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestEdgeBootListener.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.edge.core; - -import org.apache.servicecomb.core.BootListener.BootEvent; -import org.apache.servicecomb.core.BootListener.EventType; -import org.apache.servicecomb.core.executor.ExecutorManager; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.netflix.config.DynamicPropertyFactory; - -public class TestEdgeBootListener { - EdgeBootListener listener = new EdgeBootListener(); - - BootEvent bootEvent = new BootEvent(); - - @Before - public void setup() { - ArchaiusUtils.resetConfig(); - } - - @After - public void teardown() { - ArchaiusUtils.resetConfig(); - System.clearProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT); - } - - @Test - public void onBootEvent_ignore() { - System.setProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, ExecutorManager.EXECUTOR_DEFAULT); - - bootEvent.setEventType(EventType.AFTER_CONSUMER_PROVIDER); - listener.onBootEvent(bootEvent); - - Assert.assertEquals(ExecutorManager.EXECUTOR_DEFAULT, - DynamicPropertyFactory.getInstance().getStringProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, null).get()); - } - - @Test - public void onBootEvent_accept_notChange() { - System.setProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, ExecutorManager.EXECUTOR_DEFAULT); - - bootEvent.setEventType(EventType.BEFORE_PRODUCER_PROVIDER); - listener.onBootEvent(bootEvent); - - Assert.assertEquals(ExecutorManager.EXECUTOR_DEFAULT, - DynamicPropertyFactory.getInstance().getStringProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, null).get()); - } - - @Test - public void onBootEvent_change() { - bootEvent.setEventType(EventType.BEFORE_PRODUCER_PROVIDER); - listener.onBootEvent(bootEvent); - - Assert.assertEquals(ExecutorManager.EXECUTOR_REACTIVE, - DynamicPropertyFactory.getInstance().getStringProperty(ExecutorManager.KEY_EXECUTORS_DEFAULT, null).get()); - } -} diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java index a209a408e6b..046adfaa3a2 100644 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java +++ b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java @@ -17,91 +17,104 @@ package org.apache.servicecomb.edge.core; +import java.util.HashMap; import java.util.Map; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.common.rest.route.URLMappedConfigurationItem; +import org.apache.servicecomb.config.ConfigurationChangedEvent; import org.apache.servicecomb.transport.rest.vertx.RestBodyHandler; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; -import io.vertx.core.http.HttpServerRequest; import io.vertx.ext.web.RoutingContext; -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mocked; public class TestURLMappedEdgeDispatcher { - @Before + ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class); + + @BeforeEach public void setUp() throws Exception { } - @After + @AfterEach public void tearDown() { - ArchaiusUtils.resetConfig(); } @Test - public void testConfigurations(@Mocked RoutingContext context - , @Mocked HttpServerRequest requst - , @Mocked EdgeInvocation invocation) { - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.enabled", true); - + public void testConfigurations() { + EnumerablePropertySource propertySource = Mockito.mock(EnumerablePropertySource.class); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + }); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.enabled", boolean.class, false)) + .thenReturn(true); URLMappedEdgeDispatcher dispatcher = new URLMappedEdgeDispatcher(); - Map items = Deencapsulation - .getField(dispatcher, "configurations"); - Assert.assertEquals(items.size(), 0); + dispatcher.setEnvironment(environment); + Map items = dispatcher.getConfigurations(); + Assertions.assertEquals(items.size(), 0); - new Expectations() { - { - context.get(RestBodyHandler.BYPASS_BODY_HANDLER); - result = Boolean.TRUE; - context.next(); - } - }; + RoutingContext context = Mockito.mock(RoutingContext.class); + Mockito.when(context.get(RestBodyHandler.BYPASS_BODY_HANDLER)).thenReturn(Boolean.TRUE); dispatcher.onRequest(context); - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.path", "/a/b/c/.*"); - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.microserviceName", "serviceName"); - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.prefixSegmentCount", 2); - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.versionRule", "2.0.0+"); - items = Deencapsulation.getField(dispatcher, "configurations"); - Assert.assertEquals(items.size(), 1); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.http.dispatcher.edge.url.mappings.service1.path", + "servicecomb.http.dispatcher.edge.url.mappings.service1.microserviceName", + "servicecomb.http.dispatcher.edge.url.mappings.service1.prefixSegmentCount", + "servicecomb.http.dispatcher.edge.url.mappings.service1.versionRule" + }); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.path")) + .thenReturn("/a/b/c/.*"); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.microserviceName")) + .thenReturn("serviceName"); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.prefixSegmentCount", + int.class, 0)) + .thenReturn(2); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.versionRule", + "0.0.0+")) + .thenReturn("2.0.0+"); + Map latest = new HashMap<>(); + latest.put("servicecomb.http.dispatcher.edge.url.mappings.service1.path", "/a/b/c/.*"); + dispatcher.onConfigurationChangedEvent(ConfigurationChangedEvent.createIncremental(latest, new HashMap<>())); + + items = dispatcher.getConfigurations(); + Assertions.assertEquals(items.size(), 1); URLMappedConfigurationItem item = items.get("service1"); - Assert.assertEquals(item.getMicroserviceName(), "serviceName"); - Assert.assertEquals(item.getPrefixSegmentCount(), 2); - Assert.assertEquals(item.getStringPattern(), "/a/b/c/.*"); - Assert.assertEquals(item.getVersionRule(), "2.0.0+"); + Assertions.assertEquals(item.getMicroserviceName(), "serviceName"); + Assertions.assertEquals(item.getPrefixSegmentCount(), 2); + Assertions.assertEquals(item.getStringPattern(), "/a/b/c/.*"); + Assertions.assertEquals(item.getVersionRule(), "2.0.0+"); - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service2.versionRule", "2.0.0+"); - ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service3.path", "/b/c/d/.*"); - items = Deencapsulation.getField(dispatcher, "configurations"); - Assert.assertEquals(items.size(), 1); - item = items.get("service1"); - Assert.assertEquals(item.getMicroserviceName(), "serviceName"); - Assert.assertEquals(item.getPrefixSegmentCount(), 2); - Assert.assertEquals(item.getStringPattern(), "/a/b/c/.*"); - Assert.assertEquals(item.getVersionRule(), "2.0.0+"); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.http.dispatcher.edge.url.mappings.service1.path", + "servicecomb.http.dispatcher.edge.url.mappings.service1.microserviceName", + "servicecomb.http.dispatcher.edge.url.mappings.service1.prefixSegmentCount", + "servicecomb.http.dispatcher.edge.url.mappings.service1.versionRule", + "servicecomb.http.dispatcher.edge.url.mappings.service2.versionRule", + "servicecomb.http.dispatcher.edge.url.mappings.service3.path" + }); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.mappings.service2.versionRule")) + .thenReturn("2.0.0+"); + Mockito.when(environment.getProperty("servicecomb.http.dispatcher.edge.url.mappings.service3.path")) + .thenReturn("/b/c/d/.*"); - URLMappedConfigurationItem finalItem = item; - new Expectations() { - { - context.get(RestBodyHandler.BYPASS_BODY_HANDLER); - result = Boolean.FALSE; - context.get(URLMappedEdgeDispatcher.CONFIGURATION_ITEM); - result = finalItem; + latest = new HashMap<>(); + latest.put("servicecomb.http.dispatcher.edge.url.mappings.service3.path", "/a/b/c/.*"); + dispatcher.onConfigurationChangedEvent(ConfigurationChangedEvent.createIncremental(latest, new HashMap<>())); - context.request(); - result = requst; - requst.path(); - result = "/a/b/c/d/e"; - invocation.setVersionRule("2.0.0+"); - invocation.init("serviceName", context, "/c/d/e", - Deencapsulation.getField(dispatcher, "httpServerFilters")); - invocation.edgeInvoke(); - } - }; - dispatcher.onRequest(context); + items = dispatcher.getConfigurations(); + Assertions.assertEquals(items.size(), 1); + item = items.get("service1"); + Assertions.assertEquals(item.getMicroserviceName(), "serviceName"); + Assertions.assertEquals(item.getPrefixSegmentCount(), 2); + Assertions.assertEquals(item.getStringPattern(), "/a/b/c/.*"); + Assertions.assertEquals(item.getVersionRule(), "2.0.0+"); } } diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestUtils.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestUtils.java index c92373fb35f..38e8fa837d5 100644 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestUtils.java +++ b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestUtils.java @@ -17,17 +17,18 @@ package org.apache.servicecomb.edge.core; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.common.rest.route.Utils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestUtils { @Test - public void testUtisl() { - Assert.assertEquals(Utils.findActualPath("/a/b/c", -1), "/a/b/c"); - Assert.assertEquals(Utils.findActualPath("/a/b/c", 0), "/a/b/c"); - Assert.assertEquals(Utils.findActualPath("/a/b/c", 1), "/b/c"); - Assert.assertEquals(Utils.findActualPath("/a/b/c", 2), "/c"); - Assert.assertEquals(Utils.findActualPath("/a/b/c", 3), ""); - Assert.assertEquals(Utils.findActualPath("/a/b/c", 100), ""); + public void testUtils() { + Assertions.assertEquals("/a/b/c", Utils.findActualPath("/a/b/c", -1)); + Assertions.assertEquals("/a/b/c", Utils.findActualPath("/a/b/c", 0)); + Assertions.assertEquals("/b/c", Utils.findActualPath("/a/b/c", 1)); + Assertions.assertEquals("/c", Utils.findActualPath("/a/b/c", 2)); + Assertions.assertEquals("", Utils.findActualPath("/a/b/c", 3)); + Assertions.assertEquals("", Utils.findActualPath("/a/b/c", 100)); } } diff --git a/edge/pom.xml b/edge/pom.xml index 144e16ea390..e11f4e088b6 100644 --- a/edge/pom.xml +++ b/edge/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default edge diff --git a/etc/checkstyle-eclipse.xml b/etc/checkstyle-eclipse.xml deleted file mode 100644 index 956816ecd20..00000000000 --- a/etc/checkstyle-eclipse.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/etc/checkstyle-suppressions.xml b/etc/checkstyle-suppressions.xml deleted file mode 100644 index 802285ff829..00000000000 --- a/etc/checkstyle-suppressions.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - diff --git a/etc/checkstyle.xml b/etc/checkstyle.xml deleted file mode 100644 index 546932fe309..00000000000 --- a/etc/checkstyle.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/etc/findbugs-exclude.xml b/etc/findbugs-exclude.xml deleted file mode 100644 index 8bacf38dc84..00000000000 --- a/etc/findbugs-exclude.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/foundations/foundation-common/pom.xml b/foundations/foundation-common/pom.xml index 3c40ac72048..2f5a18878b4 100644 --- a/foundations/foundation-common/pom.xml +++ b/foundations/foundation-common/pom.xml @@ -20,7 +20,7 @@ 4.0.0 org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT foundations foundation-common @@ -54,10 +54,16 @@ org.apache.httpcomponents httpclient + + + commons-logging + commons-logging + + - javax.ws.rs - javax.ws.rs-api + jakarta.ws.rs + jakarta.ws.rs-api commons-io @@ -100,34 +106,20 @@ vertx-core - - log4j - log4j - provided - true - - - org.slf4j - slf4j-log4j12 - provided - true + org.apache.logging.log4j + log4j-slf4j-impl + test - - org.apache.logging.log4j - log4j-slf4j-impl - provided - true + log4j-core + test - - - ch.qos.logback - logback-classic - provided - true + org.jmockit + jmockit + test diff --git a/foundations/foundation-common/src/main/java/com/fasterxml/jackson/databind/ObjectMapperUtils.java b/foundations/foundation-common/src/main/java/com/fasterxml/jackson/databind/ObjectMapperUtils.java deleted file mode 100644 index 5be6d73c710..00000000000 --- a/foundations/foundation-common/src/main/java/com/fasterxml/jackson/databind/ObjectMapperUtils.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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 com.fasterxml.jackson.databind; - -import com.fasterxml.jackson.core.JsonParser; - -public final class ObjectMapperUtils { - private ObjectMapperUtils() { - } - - public static DeserializationContext createDeserializationContext(ObjectMapper mapper, JsonParser jp) { - return mapper.createDeserializationContext(jp, mapper.getDeserializationConfig()); - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/FoundationCommonAuthConfiguration.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/FoundationCommonAuthConfiguration.java new file mode 100644 index 00000000000..7faea74a3b5 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/FoundationCommonAuthConfiguration.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.foundation.auth; + +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FoundationCommonAuthConfiguration { + public ShaAKSKCipher scbShaAKSKCipher() { + return new ShaAKSKCipher(); + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/ShaAKSKCipher.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/ShaAKSKCipher.java index e7449745e9c..ee857e64464 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/ShaAKSKCipher.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/auth/ShaAKSKCipher.java @@ -17,9 +17,6 @@ package org.apache.servicecomb.foundation.auth; -import org.springframework.stereotype.Component; - -@Component public class ShaAKSKCipher implements Cipher { public static final String CIPHER_NAME = "ShaAKSKCipher"; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Holder.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Holder.java index ebc92a34ebd..9e9752c6a30 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Holder.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/Holder.java @@ -16,7 +16,7 @@ */ package org.apache.servicecomb.foundation.common; -// do not use javax.xml.ws.Holder, use this one. Because JDK 11 above do not have javax.ws.Holder +// do not use javax.xml.ws.Holder, use this one. Because JDK 11 above do not have jakarta.ws.Holder public final class Holder { /** diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/LegacyPropertyFactory.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/LegacyPropertyFactory.java new file mode 100644 index 00000000000..ada58bdf3e7 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/LegacyPropertyFactory.java @@ -0,0 +1,72 @@ +/* + * 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.foundation.common; + +import org.springframework.core.env.Environment; + +import com.google.common.annotations.VisibleForTesting; + +/** + * Provider a convenient way to get property value in static context. + * + * NOTE: This way is not commented and only for legacy code without too much refactoring. + * And make sure to use this class when spring bean context is already initialized. + */ +public class LegacyPropertyFactory { + private static Environment environment; + + public LegacyPropertyFactory(Environment environment) { + LegacyPropertyFactory.environment = environment; + } + + @VisibleForTesting + public static void setEnvironment(Environment environment) { + LegacyPropertyFactory.environment = environment; + } + + public static T getProperty(String key, Class targetType) { + return environment.getProperty(key, targetType); + } + + public static T getProperty(String key, Class targetType, T defaultValue) { + return environment.getProperty(key, targetType, defaultValue); + } + + public static boolean getBooleanProperty(String key, boolean defaultValue) { + return environment.getProperty(key, boolean.class, defaultValue); + } + + public static int getIntProperty(String key, int defaultValue) { + return environment.getProperty(key, int.class, defaultValue); + } + + public static long getLongProperty(String key, long defaultValue) { + return environment.getProperty(key, long.class, defaultValue); + } + + public static String getStringProperty(String key) { + return environment.getProperty(key); + } + + public static String getStringProperty(String key, String defaultValue) { + return environment.getProperty(key, defaultValue); + } + + public static Environment getEnvironment() { + return environment; + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/NamedThreadFactory.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/NamedThreadFactory.java index c6be9c1e0db..3b79c9c8e1a 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/NamedThreadFactory.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/NamedThreadFactory.java @@ -43,7 +43,9 @@ public NamedThreadFactory(String prefix) { */ @Override public Thread newThread(Runnable r) { - return new Thread(r, prefix + "-" + threadNumber.getAndIncrement()); + Thread thread = new Thread(r, prefix + "-" + threadNumber.getAndIncrement()); + thread.setDaemon(true); + return thread; } public String getPrefix() { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/ParameterizedTypeUtil.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/ParameterizedTypeUtil.java new file mode 100644 index 00000000000..025c08acbf3 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/ParameterizedTypeUtil.java @@ -0,0 +1,96 @@ +/* + * 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.foundation.common; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * Utility class for creating ParameterizedType. + */ +public class ParameterizedTypeUtil implements ParameterizedType { + private final Type[] actualTypeArguments; + + private final Class rawType; + + private ParameterizedTypeUtil(Class rawType, Type[] actualTypeArguments) { + this.actualTypeArguments = actualTypeArguments; + this.rawType = rawType; + } + + public static ParameterizedType make(Class rawType, Type... actualTypeArguments) { + return new ParameterizedTypeUtil(rawType, actualTypeArguments); + } + + @Override + public Type[] getActualTypeArguments() { + return this.actualTypeArguments; + } + + @Override + public Type getRawType() { + return rawType; + } + + @Override + public Type getOwnerType() { + return null; + } + + @Override + public boolean equals(Object o) { + if (o instanceof ParameterizedType that) { + + if (this == that) { + return true; + } + + Type thatRawType = that.getRawType(); + + return Objects.equals(rawType, thatRawType) && + Arrays.equals(actualTypeArguments, that.getActualTypeArguments()); + } else { + return false; + } + } + + @Override + public int hashCode() { + return Arrays.hashCode(actualTypeArguments) ^ + Objects.hashCode(rawType); + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(rawType.getName()); + + if (actualTypeArguments != null) { + StringJoiner sj = new StringJoiner(", ", "<", ">"); + sj.setEmptyValue(""); + for (Type t : actualTypeArguments) { + sj.add(t.getTypeName()); + } + sb.append(sj); + } + + return sb.toString(); + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/RegisterManager.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/RegisterManager.java index 5fa4b8c9f7e..80cf768a22d 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/RegisterManager.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/RegisterManager.java @@ -27,13 +27,13 @@ public class RegisterManager { private static final Logger LOGGER = LoggerFactory.getLogger(RegisterManager.class); - private String name; + private final String name; private String registerErrorFmt = "Not allow register repeat data, name=%s, key=%s"; - private Map objMap = new ConcurrentHashMap<>(); + private final Map objMap = new ConcurrentHashMap<>(); - private Object lockObj = new Object(); + private final Object lockObj = new Object(); protected Map getObjMap() { return objMap; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/VendorExtensions.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/VendorExtensions.java index bd938807572..270a883d0f0 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/VendorExtensions.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/VendorExtensions.java @@ -22,7 +22,7 @@ import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; public class VendorExtensions { - private Map store = new ConcurrentHashMapEx<>(); + private final Map store = new ConcurrentHashMapEx<>(); public Map getStore() { return store; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/DynamicEnum.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/DynamicEnum.java index 6629db5f9f2..982e913fefe 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/DynamicEnum.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/DynamicEnum.java @@ -22,7 +22,7 @@ import com.fasterxml.jackson.annotation.JsonValue; public abstract class DynamicEnum { - private T value; + private final T value; @JsonIgnore private boolean dynamic = false; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/EnumUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/EnumUtils.java index e845bc3ea45..b25bcfa1504 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/EnumUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/EnumUtils.java @@ -18,6 +18,7 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; +import java.lang.reflect.Type; import java.util.Arrays; import java.util.stream.Stream; @@ -40,7 +41,7 @@ static Stream findEnumFields(Class cls) { .filter(field -> isEnumField(cls, field)); } - static boolean isDynamicEnum(Class cls) { - return DynamicEnum.class.isAssignableFrom(cls); + static boolean isDynamicEnum(Type cls) { + return cls instanceof DynamicEnum; } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/ServiceCombConstants.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/ServiceCombConstants.java index 73a0e558116..aedae7c1a86 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/ServiceCombConstants.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/base/ServiceCombConstants.java @@ -30,11 +30,7 @@ public interface ServiceCombConstants { String DEFAULT_TRACING_COLLECTOR_ADDRESS = "http://127.0.0.1:9411"; - String CONFIG_SERVICECOMB_PREFIX = "servicecomb."; - - String CONFIG_CSE_PREFIX = "cse."; - - String CONFIG_KEY_SPLITER = "_"; + String CONFIG_KEY_SPLITTER = "_"; String CONFIG_FRAMEWORK_DEFAULT_NAME = "servicecomb-java-chassis"; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/cache/VersionedCache.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/cache/VersionedCache.java index 6580174861e..b30e13862b4 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/cache/VersionedCache.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/cache/VersionedCache.java @@ -30,7 +30,7 @@ interface IsEmpty { boolean isEmpty(); } - protected int cacheVersion; + protected volatile int cacheVersion; // an optional name protected String name; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/PaaSResourceUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/PaaSResourceUtils.java index f3103661d05..fe11a3fe763 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/PaaSResourceUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/PaaSResourceUtils.java @@ -20,22 +20,20 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Comparator; import java.util.List; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.foundation.common.config.impl.PropertiesLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.util.StringUtils; + public class PaaSResourceUtils extends org.springframework.util.ResourceUtils { public static final String PROPERTIES_SUFFIX = ".properties"; - public static final String XML_SUFFIX = ".xml"; - - private static ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + private static final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); /** * 失败,则返回空数组 @@ -71,34 +69,31 @@ public static List getResources(String... locationPatterns) { * 此时,还分多个,是不合适的 */ public static void sortResources(List resList, String suffix) { - resList.sort(new Comparator() { - @Override - public int compare(Resource o1, Resource o2) { - try { - // jar的优先级比较低 - if (isJarURL(o1.getURL()) && isFileURL(o2.getURL())) { - return -1; - } - - // 干掉后缀,再排序 - String name1 = o1.getFilename(); - String name2 = o2.getFilename(); - - //Resource.getFilename接口会返回null,当路径的文件名不存在时 - //配置文件一定存在,并且Resource有合法的文件名,name1和name2不可能为空, - //这里做判断是为了处理CodeDEX报的null引用 - if (StringUtils.isEmpty(name1) || StringUtils.isEmpty(name2)) { - throw new IOException( - String.format("Resource %s or %s is not a file", o1.getURI(), o2.getURI())); - } - - name1 = name1.substring(0, name1.length() - suffix.length()); - name2 = name2.substring(0, name2.length() - suffix.length()); - - return name1.compareTo(name2); - } catch (IOException e) { - throw new RuntimeException(e); + resList.sort((o1, o2) -> { + try { + // jar的优先级比较低 + if (isJarURL(o1.getURL()) && isFileURL(o2.getURL())) { + return -1; + } + + // 干掉后缀,再排序 + String name1 = o1.getFilename(); + String name2 = o2.getFilename(); + + //Resource.getFilename接口会返回null,当路径的文件名不存在时 + //配置文件一定存在,并且Resource有合法的文件名,name1和name2不可能为空, + //这里做判断是为了处理CodeDEX报的null引用 + if (StringUtils.isEmpty(name1) || StringUtils.isEmpty(name2)) { + throw new IOException( + String.format("Resource %s or %s is not a file", o1.getURI(), o2.getURI())); } + + name1 = name1.substring(0, name1.length() - suffix.length()); + name2 = name2.substring(0, name2.length() - suffix.length()); + + return name1.compareTo(name2); + } catch (IOException e) { + throw new RuntimeException(e); } }); } @@ -107,10 +102,6 @@ public static void sortProperties(List resList) { sortResources(resList, PROPERTIES_SUFFIX); } - public static void sortXmls(List resList) { - sortResources(resList, XML_SUFFIX); - } - public static List getSortedResources(String locationPattern, String suffix) { if (StringUtils.isEmpty(locationPattern)) { throw new RuntimeException("Resource path must not be null or empty"); @@ -127,7 +118,7 @@ public static List getSortedResources(String locationPattern, String s return resList; } - public static List getSortedPorperties(String locationPattern) { + public static List getSortedProperties(String locationPattern) { return getSortedResources(locationPattern, PROPERTIES_SUFFIX); } @@ -135,8 +126,4 @@ public static Properties loadMergedProperties(String locationPattern) throws Exc PropertiesLoader loader = new PropertiesLoader(Arrays.asList(locationPattern)); return loader.load(); } - - public static List getSortedXmls(String locationPattern) { - return getSortedResources(locationPattern, XML_SUFFIX); - } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PaaSPropertiesLoaderUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PaaSPropertiesLoaderUtils.java index b31901bd12a..a12eca5ae3a 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PaaSPropertiesLoaderUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PaaSPropertiesLoaderUtils.java @@ -21,9 +21,10 @@ import java.util.List; import java.util.Properties; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.foundation.common.config.PaaSResourceUtils; import org.springframework.core.io.Resource; -import org.springframework.util.StringUtils; + public class PaaSPropertiesLoaderUtils extends org.springframework.core.io.support.PropertiesLoaderUtils { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PropertiesLoader.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PropertiesLoader.java index 1590ba143bf..ae4500e8aef 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PropertiesLoader.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/PropertiesLoader.java @@ -25,7 +25,7 @@ import org.springframework.core.io.Resource; public class PropertiesLoader extends AbstractLoader { - private List foundResList = new ArrayList<>(); + private final List foundResList = new ArrayList<>(); public PropertiesLoader(List locationPatternList) { super(locationPatternList); @@ -40,7 +40,7 @@ public List getFoundResList() { public T load() throws Exception { Properties props = new Properties(); for (String locationPattern : locationPatternList) { - List resList = PaaSResourceUtils.getSortedPorperties(locationPattern); + List resList = PaaSResourceUtils.getSortedProperties(locationPattern); foundResList.addAll(resList); PaaSPropertiesLoaderUtils.fillAllProperties(props, resList); } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoader.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoader.java deleted file mode 100644 index 254b1eda3d0..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoader.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.foundation.common.config.impl; - -import java.util.List; - -import org.apache.servicecomb.foundation.common.config.PaaSResourceUtils; -import org.springframework.core.io.Resource; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * 无逻辑append xml - */ -public class XmlLoader extends AbstractLoader { - - private String suffix; - - public XmlLoader(List locationPatternList) { - this(locationPatternList, PaaSResourceUtils.XML_SUFFIX); - } - - public XmlLoader(List locationPatternList, String suffix) { - super(locationPatternList); - this.suffix = suffix; - } - - @SuppressWarnings("unchecked") - @Override - public T load() throws Exception { - Document doc = XmlLoaderUtils.newDoc(); - Element root = null; - for (String locationPattern : locationPatternList) { - List resList = PaaSResourceUtils.getSortedResources(locationPattern, suffix); - for (Resource res : resList) { - Document tmpDoc = XmlLoaderUtils.load(res); - Element tmpRoot = tmpDoc.getDocumentElement(); - - if (root == null) { - root = (Element) doc.importNode(tmpRoot, false); - doc.appendChild(root); - } - - NodeList nodeList = tmpRoot.getChildNodes(); - for (int idx = 0; idx < nodeList.getLength(); idx++) { - Node child = nodeList.item(idx); - - if (!Element.class.isInstance(child)) { - continue; - } - - Element clone = (Element) doc.importNode(child, true); - Element exist = findAndSetExist(clone); - if (exist == null) { - root.appendChild(clone); - continue; - } - - // merge attr and children - XmlLoaderUtils.mergeElement(clone, exist); - } - } - } - return (T) doc; - } - - protected Element findAndSetExist(Element ele) { - return null; - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoaderUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoaderUtils.java index af0393409e4..8d2a4b98c1e 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoaderUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/config/impl/XmlLoaderUtils.java @@ -38,7 +38,7 @@ public final class XmlLoaderUtils { private XmlLoaderUtils() { } - private static ObjectMapper xmlMapper = new XmlMapper(); + private static final ObjectMapper xmlMapper = new XmlMapper(); @SuppressWarnings("unchecked") public static T load(Resource res, Class cls) throws Exception { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java index 1f100c14849..3539764406d 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/AlarmEvent.java @@ -31,5 +31,5 @@ public Type getType() { public enum Type { OPEN, CLOSE - }; + } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java index aad5e69fbdf..50b474050d9 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/EventManager.java @@ -56,7 +56,7 @@ public static void unregister(Object listener) { } @Bean - public EventBus eventBus() { + public EventBus scbEventBus() { return eventBus; } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java index 561974c44e5..990ca304dcf 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java @@ -29,13 +29,13 @@ public class SimpleSubscriber { private static final Logger LOGGER = LoggerFactory.getLogger(SimpleSubscriber.class); - private Object instance; + private final Object instance; - private Method method; + private final Method method; private int order; - private boolean enableExceptionPropagation; + private final boolean enableExceptionPropagation; // generated from method private Consumer lambda; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatus.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatus.java index 15489ba95a9..45806dcc53f 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatus.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatus.java @@ -16,9 +16,9 @@ */ package org.apache.servicecomb.foundation.common.http; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.Status.Family; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status.Family; +import jakarta.ws.rs.core.Response.StatusType; public class HttpStatus implements StatusType { public static boolean isSuccess(int code) { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusManager.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusManager.java index b2ec5a75472..8a995f74389 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusManager.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusManager.java @@ -19,13 +19,13 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.StatusType; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; public class HttpStatusManager { - private Map statusMap = new ConcurrentHashMap<>(); + private final Map statusMap = new ConcurrentHashMap<>(); public HttpStatusManager() { for (Status status : Status.values()) { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusUtils.java index 4dac0e4259b..3c4693c9eab 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpStatusUtils.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.foundation.common.http; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.Response.StatusType; public final class HttpStatusUtils { private static final HttpStatusManager MGR = new HttpStatusManager(); diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java index 2e32bc15eb5..626cb136030 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/http/HttpUtils.java @@ -19,9 +19,10 @@ import java.io.File; import java.net.URI; import java.net.URISyntaxException; -import org.springframework.util.StringUtils; + import com.google.common.net.UrlEscapers; +import org.apache.commons.lang3.StringUtils; public final class HttpUtils { private HttpUtils() { @@ -42,9 +43,8 @@ public static String parseParamFromHeaderValue(String headerValue, String paramN if (idx == -1) { continue; } - - if (paramName.equalsIgnoreCase(value.substring(0, idx))) { - return value.substring(idx + 1); + if (paramName.equalsIgnoreCase(value.substring(0, idx).trim())) { + return value.substring(idx + 1).replaceAll("\"", "").trim(); } } return null; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/log/AbstractMarker.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/log/AbstractMarker.java index d3a22755747..15128c19bce 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/log/AbstractMarker.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/log/AbstractMarker.java @@ -65,4 +65,4 @@ public boolean contains(String name) { public String toString() { return getName(); } -} \ No newline at end of file +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/IpPort.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/IpPort.java index d8515eea13a..66aae3ebca7 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/IpPort.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/IpPort.java @@ -22,9 +22,9 @@ import com.google.common.base.Objects; public class IpPort { - private String hostOrIp; + private volatile String hostOrIp; - private int port; + private volatile int port; private volatile InetSocketAddress socketAddress; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/NetUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/NetUtils.java index 90d6301de7a..fd8cc1f7a29 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/NetUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/NetUtils.java @@ -262,7 +262,7 @@ public static IpPort parseIpPort(String scheme, String authority) { /** * 对于配置为0.0.0.0的地址,let it go * schema, e.g. http - * adddress, e.g 0.0.0.0:8080 + * address, e.g 0.0.0.0:8080 * return 实际监听的地址 */ public static String getRealListenAddress(String schema, String address) { @@ -340,7 +340,7 @@ public static String humanReadableBytes(long bytes) { return String.valueOf(bytes); } int exp = (int) (Math.log(bytes) / Math.log(unit)); - char pre = "KMGTPE" .charAt(exp - 1); + char pre = "KMGTPE".charAt(exp - 1); return String.format("%.3f%c", bytes / Math.pow(unit, exp), pre); } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java index 517a25fdfc4..78b633c1183 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java @@ -35,24 +35,32 @@ public class URIEndpointObject extends IpPort { private static final String PROTOCOL_KEY = "protocol"; + private static final String WEBSOCKET_ENABLED_KEY = "websocketEnabled"; + private static final String HTTP2 = "http2"; - private boolean sslEnabled; + private final boolean sslEnabled; private boolean http2Enabled; - private Map> querys; + private boolean websocketEnabled; + + private final Map> queries; + + private final String schema; public URIEndpointObject(String endpoint) { URI uri = URI.create(endpoint); + schema = uri.getScheme(); setHostOrIp(uri.getHost()); if (uri.getPort() < 0) { // do not use default port throw new IllegalArgumentException("port not specified."); } setPort(uri.getPort()); - querys = splitQuery(uri); + queries = splitQuery(uri); sslEnabled = Boolean.parseBoolean(getFirst(SSL_ENABLED_KEY)); + websocketEnabled = Boolean.parseBoolean(getFirst(WEBSOCKET_ENABLED_KEY)); String httpVersion = getFirst(PROTOCOL_KEY); if (HTTP2.equals(httpVersion)) { http2Enabled = true; @@ -73,16 +81,24 @@ public boolean isSslEnabled() { return sslEnabled; } + public boolean isWebsocketEnabled() { + return websocketEnabled; + } + public boolean isHttp2Enabled() { return http2Enabled; } + public String getSchema() { + return this.schema; + } + public List getQuery(String key) { - return querys.get(key); + return queries.get(key); } public String getFirst(String key) { - List values = querys.get(key); + List values = queries.get(key); // it's impossible that values is not null and size is 0 if (values == null) { return null; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/AbstractPart.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/AbstractPart.java index 653d0f909e3..0c849a5d83a 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/AbstractPart.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/AbstractPart.java @@ -22,11 +22,12 @@ import java.util.Collection; import javax.activation.MimetypesFileTypeMap; -import javax.servlet.http.Part; -import javax.ws.rs.core.MediaType; + +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.MediaType; public class AbstractPart implements Part { - private static MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); + private static final MimetypesFileTypeMap mimetypesFileTypeMap = new MimetypesFileTypeMap(); protected String name; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePart.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePart.java index ef290479760..1bd9ddfd952 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePart.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePart.java @@ -18,14 +18,14 @@ package org.apache.servicecomb.foundation.common.part; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import org.apache.commons.io.FileUtils; public class FilePart extends AbstractPart implements FilePartForSend { - private File file; + private final File file; private boolean deleteAfterFinished; @@ -41,7 +41,7 @@ public FilePart(String name, File file) { @Override public InputStream getInputStream() throws IOException { - return new FileInputStream(file); + return Files.newInputStream(file.toPath()); } @Override diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePartForSend.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePartForSend.java index f86e696a66e..b2252361997 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePartForSend.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/FilePartForSend.java @@ -16,7 +16,7 @@ */ package org.apache.servicecomb.foundation.common.part; -import javax.servlet.http.Part; +import jakarta.servlet.http.Part; public interface FilePartForSend extends Part { boolean isDeleteAfterFinished(); diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/ResourcePart.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/ResourcePart.java index ff07e896ac8..cb00e5dd00c 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/ResourcePart.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/part/ResourcePart.java @@ -23,7 +23,7 @@ import org.springframework.core.io.Resource; public class ResourcePart extends AbstractPart { - private Resource resource; + private final Resource resource; public ResourcePart(String name, Resource resource) { this.name = name; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/spring/PaasNamespaceHandler.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/spring/PaasNamespaceHandler.java index 5b65bf7edcd..f434818df84 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/spring/PaasNamespaceHandler.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/spring/PaasNamespaceHandler.java @@ -50,10 +50,10 @@ public void init() { String className = entry.getValue().toString(); try { Class clazz = Class.forName(className); - Object instance = clazz.newInstance(); + Object instance = clazz.getDeclaredConstructor().newInstance(); registerBeanDefinitionParser(entry.getKey().toString(), (BeanDefinitionParser) instance); - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + } catch (ReflectiveOperationException e) { // 类找不到,说明没部署相应的jar包,这不一定是错误 // 可能是业务就选择不部署相应的jar包 // 所以只是打印个info日志 diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AbstractRestObjectMapper.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AbstractRestObjectMapper.java index 0a246962c58..5069e6a3986 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AbstractRestObjectMapper.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AbstractRestObjectMapper.java @@ -22,5 +22,13 @@ public abstract class AbstractRestObjectMapper extends ObjectMapper { private static final long serialVersionUID = 189026839992490564L; - abstract public String convertToString(Object value) throws Exception; + public AbstractRestObjectMapper() { + super(); + } + + public AbstractRestObjectMapper(RestObjectMapper src) { + super(src); + } + + public abstract String convertToString(Object value) throws Exception; } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AsyncUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AsyncUtils.java index 8f4780eda56..25219038097 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AsyncUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/AsyncUtils.java @@ -17,8 +17,11 @@ package org.apache.servicecomb.foundation.common.utils; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.function.Supplier; +import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; + public final class AsyncUtils { private AsyncUtils() { } @@ -47,30 +50,24 @@ public static CompletableFuture completeExceptionally(Throwable throwable } /** - * throws {@code exception} as unchecked exception, without wrapping exception. + * throws {@code exception} as RuntimeException. * * @param exception exception which will be rethrow - * @throws T {@code exception} as unchecked exception */ - @SuppressWarnings("unchecked") - public static void rethrow(Throwable exception) throws T { - throw (T) exception; + public static RuntimeException rethrow(Throwable exception) { + if (exception instanceof RuntimeException) { + return (RuntimeException) exception; + } + return new ServiceCombException("Not declared exception", exception); } public static T toSync(CompletableFuture future) { try { return future.get(); + } catch (ExecutionException executionException) { + throw rethrow(executionException.getCause()); } catch (Throwable e) { - rethrow(e.getCause()); - return null; - } - } - - public static void waitQuietly(CompletableFuture future) { - try { - future.get(); - } catch (Exception e) { - // just eat the exception + throw rethrow(e); } } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java index 77abe7231d4..bc6a648b361 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/BeanUtils.java @@ -17,107 +17,21 @@ package org.apache.servicecomb.foundation.common.utils; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.aop.framework.AopProxyUtils; import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; public final class BeanUtils { - private static final Logger LOGGER = LoggerFactory.getLogger(BeanUtils.class); - - public static final String DEFAULT_BEAN_CORE_RESOURCE = "classpath*:META-INF/spring/scb-core-bean.xml"; - - public static final String DEFAULT_BEAN_NORMAL_RESOURCE = "classpath*:META-INF/spring/*.bean.xml"; - - public static final String[] DEFAULT_BEAN_RESOURCE = new String[] {DEFAULT_BEAN_CORE_RESOURCE - , DEFAULT_BEAN_NORMAL_RESOURCE}; - - public static final String SCB_SCAN_PACKAGE = "scb-scan-package"; - - private static final String SCB_PACKAGE = "org.apache.servicecomb"; - private static ApplicationContext context; private BeanUtils() { } - public static void init() { - init(DEFAULT_BEAN_RESOURCE); - } - - public static void init(String... configLocations) { - prepareServiceCombScanPackage(); - - Set locationSet = new LinkedHashSet<>(); - addBeanLocation(locationSet, DEFAULT_BEAN_RESOURCE); - addBeanLocation(locationSet, configLocations); - context = new ClassPathXmlApplicationContext(locationSet.toArray(new String[locationSet.size()])); - } - - public static void addBeanLocation(Set locationSet, String... location) { - Arrays.stream(location).forEach(loc -> addBeanLocation(locationSet, loc)); - } - - public static void addBeanLocation(Set locationSet, String location) { - if (location == null) { - return; - } - - location = location.trim(); - if (StringUtils.isNotEmpty(location)) { - locationSet.add(location); - } - } - - private static void addItem(Set set, String item) { - for (String it : set) { - if (item.startsWith(it)) { - return; - } - } - set.add(item); - } - - public static void prepareServiceCombScanPackage() { - Set scanPackags = new LinkedHashSet<>(); - // add exists settings - String exists = System.getProperty(SCB_SCAN_PACKAGE); - if (exists != null) { - for (String exist : exists.trim().split(",")) { - if (!exist.isEmpty()) { - addItem(scanPackags, exist.trim()); - } - } - } - - // ensure servicecomb package exist - addItem(scanPackags, SCB_PACKAGE); - - // add main class package - for (Class mainClass : new Class[] {JvmUtils.findMainClass(), JvmUtils.findMainClassByStackTrace()}) { - if (mainClass != null && mainClass.getPackage() != null) { - String pkg = mainClass.getPackage().getName(); - addItem(scanPackags, pkg); - } - } - - // finish - String scbScanPackages = StringUtils.join(scanPackags, ","); - System.setProperty(SCB_SCAN_PACKAGE, scbScanPackages); - LOGGER.info("Scb scan package list: " + scbScanPackages); - } - public static ApplicationContext getContext() { return context; } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ConditionWaiter.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ConditionWaiter.java new file mode 100644 index 00000000000..4641ca3d233 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ConditionWaiter.java @@ -0,0 +1,80 @@ +/* + * 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.foundation.common.utils; + +import java.util.concurrent.Callable; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +public class ConditionWaiter { + private final AtomicReference dataReference; + + private final AtomicBoolean isComplete; + + private final long sleepDuration; + + private final TimeUnit timeUnit; + + private final ExecutorService executorService; + + public ConditionWaiter(T initialData, long sleepDuration, TimeUnit timeUnit) { + this.dataReference = new AtomicReference<>(initialData); + this.isComplete = new AtomicBoolean(false); + this.sleepDuration = sleepDuration; + this.timeUnit = timeUnit; + this.executorService = Executors.newSingleThreadExecutor(); + } + + public T waitForCompletion() { + while (!isComplete.get()) { + SleepUtil.sleep(sleepDuration, timeUnit); + } + return dataReference.get(); + } + + public void setData(T newData) { + dataReference.set(newData); + } + + public void executeTaskAsync(Callable task) { + CompletableFuture.supplyAsync(() -> { + try { + return task.call(); + } catch (Exception e) { + throw new RuntimeException("Task execution failed", e); + } + }, executorService).thenAccept(result -> { + setData(result); + isComplete.set(true); + }); + } + + public static class SleepUtil { + public static void sleep(long duration, TimeUnit timeUnit) { + try { + timeUnit.sleep(duration); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + System.out.println("Thread was interrupted during sleep!"); + } + } + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FilePerm.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FilePerm.java index 7ffaa173aac..979841f1523 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FilePerm.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FilePerm.java @@ -84,7 +84,7 @@ private FilePerm() { */ public static final int FILE_PERM_MASK = 511; - private static AclEntryPermission[] permList = new AclEntryPermission[] { + private static final AclEntryPermission[] permList = new AclEntryPermission[] { AclEntryPermission.READ_DATA, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.READ_NAMED_ATTRS, diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FortifyUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FortifyUtils.java index c88415ad754..63234af5ab4 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FortifyUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/FortifyUtils.java @@ -36,9 +36,9 @@ */ public final class FortifyUtils { - private static Method getMessageMethod; + private static final Method getMessageMethod; - private static Method printStackTraceMethod; + private static final Method printStackTraceMethod; static { try { @@ -83,7 +83,7 @@ public static String getErrorInfo(Throwable e) { } public static String getErrorInfo(Throwable e, boolean isPrintMsg) { - StringBuffer error = new StringBuffer(System.lineSeparator()); + StringBuilder error = new StringBuilder(System.lineSeparator()); error.append("Exception: ").append(e.getClass().getName()).append("; "); if (isPrintMsg) { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/GenericsUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/GenericsUtils.java index 0429b82da70..d872236082e 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/GenericsUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/GenericsUtils.java @@ -24,14 +24,14 @@ public final class GenericsUtils { /** * check if XXX.class is generic type. see TestGenericsUtils for details meaning. * This method is provided for API compatibility for RestTemplate. Following code: - * - * + *

+ *{@code * List>> response = consumers.getSCBRestTemplate() * postForObject("/testListObjectParam", request, List.class); - * + * } * * should work for versions of 1.*. This is because java-chassis can read type info from swaggers. - * + *

* Start from 2.x, the best practise to write this code is to use ParameterizedTypeReference provided by RestTemplate * exchange method. */ diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java index ed1d1ad12cd..07269d6830f 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JsonUtils.java @@ -22,14 +22,19 @@ import java.io.OutputStream; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.json.JsonWriteFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; public final class JsonUtils { public static final ObjectMapper OBJ_MAPPER; + private static final ObjectMapper UNICODE_OBJ_MAPPER; static { OBJ_MAPPER = new RestObjectMapper(); + + UNICODE_OBJ_MAPPER = OBJ_MAPPER.copy(); + UNICODE_OBJ_MAPPER.enable(JsonWriteFeature.ESCAPE_NON_ASCII.mappedFeature()); } private JsonUtils() { @@ -55,6 +60,10 @@ public static String writeValueAsString(Object value) throws JsonProcessingExcep return OBJ_MAPPER.writeValueAsString(value); } + public static String writeUnicodeValueAsString(Object value) throws JsonProcessingException { + return UNICODE_OBJ_MAPPER.writeValueAsString(value); + } + public static T convertValue(Object fromValue, Class toValueType) { return OBJ_MAPPER.convertValue(fromValue, toValueType); } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java index 04196d303ff..6ed60ff0afc 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/JvmUtils.java @@ -54,7 +54,7 @@ public static Class findMainClassByStackTrace() { } } } - if(StringUtils.isEmpty(mainClass)){ + if (StringUtils.isEmpty(mainClass)) { LOGGER.info("Can't found main class by stackTrace."); return null; } @@ -85,7 +85,7 @@ public static Class findMainClass() { String mainClassOrJar = command.trim().split(" ")[0]; mainClass = readFromJar(mainClassOrJar); } - if(StringUtils.isEmpty(mainClass)){ + if (StringUtils.isEmpty(mainClass)) { LOGGER.info("Can't found main class by manifest."); return null; } @@ -139,4 +139,4 @@ public static ClassLoader correctClassLoader(ClassLoader classLoader) { public static ClassLoader findClassLoader() { return correctClassLoader(null); } -} \ No newline at end of file +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/KeyPairEntry.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/KeyPairEntry.java new file mode 100644 index 00000000000..be31df199a4 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/KeyPairEntry.java @@ -0,0 +1,47 @@ +/* + * 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.foundation.common.utils; + +import java.security.PrivateKey; +import java.security.PublicKey; + +public final class KeyPairEntry { + + private final PrivateKey privateKey; + + private final PublicKey publicKey; + + private final String publicKeyEncoded; + + public KeyPairEntry(PrivateKey privateKey, PublicKey publicKey, String publicKeyEncoded) { + this.privateKey = privateKey; + this.publicKey = publicKey; + this.publicKeyEncoded = publicKeyEncoded; + } + + public PrivateKey getPrivateKey() { + return privateKey; + } + + public PublicKey getPublicKey() { + return publicKey; + } + + public String getPublicKeyEncoded() { + return publicKeyEncoded; + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/KeyPairUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/KeyPairUtils.java new file mode 100644 index 00000000000..91fed2ce1c8 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/KeyPairUtils.java @@ -0,0 +1,117 @@ +/* + * 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.foundation.common.utils; + +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class KeyPairUtils { + + private static final Logger LOGGER = LoggerFactory.getLogger(KeyPairUtils.class); + + private static final String KEY_GENERATOR_ALGORITHM = LegacyPropertyFactory.getStringProperty( + "servicecomb.publicKey.accessControl.keyGeneratorAlgorithm", "RSA"); + + private static final String SIGN_ALG = LegacyPropertyFactory.getStringProperty( + "servicecomb.publicKey.accessControl.signAlgorithm", "SHA256withRSA"); + + private static final int KEY_SIZE = LegacyPropertyFactory.getIntProperty( + "servicecomb.publicKey.accessControl.keySize", 2048); + + private static final Base64.Encoder encoder = Base64.getEncoder(); + + private static final Base64.Decoder decoder = Base64.getDecoder(); + + private static KeyFactory kf = null; + + static { + + try { + kf = KeyFactory.getInstance(KEY_GENERATOR_ALGORITHM); + } catch (NoSuchAlgorithmException e) { + LOGGER.error("init keyfactory error"); + } + } + + public static KeyPairEntry generateALGKeyPair() { + try { + KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(KEY_GENERATOR_ALGORITHM); + keyGenerator.initialize(KEY_SIZE, new SecureRandom()); + KeyPair keyPair = keyGenerator.generateKeyPair(); + PublicKey pubKey = keyPair.getPublic(); + PrivateKey privKey = keyPair.getPrivate(); + return new KeyPairEntry(privKey, pubKey, encoder.encodeToString(pubKey.getEncoded())); + } catch (NoSuchAlgorithmException e) { + LOGGER.error("generate rsa keypair failed"); + throw new IllegalStateException("perhaps error occurred on jre"); + } + } + + /** + * if has performance problem ,change Signature to ThreadLocal instance + */ + public static String sign(String content, PrivateKey privateKey) + throws NoSuchAlgorithmException, SignatureException, InvalidKeyException { + Signature signature = Signature.getInstance(SIGN_ALG); + signature.initSign(privateKey); + signature.update(content.getBytes(StandardCharsets.UTF_8)); + byte[] signByte = signature.sign(); + return encoder.encodeToString(signByte); + } + + /** + * + * if has performance problem ,change Signature to ThreadLocal instance + * @param publicKey public key after base64 encode + * @param sign 签名 + * @param content original content + * @return verify result + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + * @throws InvalidKeyException + * @throws SignatureException + */ + public static boolean verify(String publicKey, String sign, String content) + throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { + if (null == kf) { + throw new NoSuchAlgorithmException(KEY_GENERATOR_ALGORITHM + " KeyFactory not available"); + } + byte[] bytes = decoder.decode(publicKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); + PublicKey pubKey = kf.generatePublic(keySpec); + Signature signature = Signature.getInstance(SIGN_ALG); + signature.initVerify(pubKey); + signature.update(content.getBytes(StandardCharsets.UTF_8)); + return signature.verify(decoder.decode(sign)); + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaMetafactoryUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaMetafactoryUtils.java index a63a9abaa76..32ba59014e0 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaMetafactoryUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaMetafactoryUtils.java @@ -83,7 +83,7 @@ private static void initGetterSetterMap() { private LambdaMetafactoryUtils() { } - protected static Method findAbstractMethod(Class functionalInterface) { + private static Method findAbstractMethod(Class functionalInterface) { for (Method method : functionalInterface.getMethods()) { if ((method.getModifiers() & Modifier.ABSTRACT) != 0) { return method; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaUtils.java new file mode 100644 index 00000000000..09265d57e2e --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/LambdaUtils.java @@ -0,0 +1,31 @@ +/* + * 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.foundation.common.utils; + +import java.util.function.Consumer; + +public class LambdaUtils { + + public static Consumer ignoreException(Consumer consumer) { + return item -> { + try { + consumer.accept(item); + } catch (Throwable e) { + } + }; + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/Log4jUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/Log4jUtils.java deleted file mode 100644 index 46dbd7814b1..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/Log4jUtils.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.foundation.common.utils; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.stream.Collectors; - -import org.apache.commons.io.FileUtils; -import org.apache.log4j.PropertyConfigurator; -import org.apache.servicecomb.foundation.common.config.impl.PropertiesLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.io.Resource; - -public final class Log4jUtils { - - private static final String MERGED_FILE = "merged.log4j.properties"; - - public static final String OUTPUT_CONFIG_ENABLED = "log4j.logger.outputConfig.enabled"; - - public static final String OUTPUT_CONFIG_ENABLED_TRUE = "true"; - - // spring boot的包装中会重复调用init,需要规避一下 - private static boolean inited = false; - - private static final Object LOCK = new Object(); - - private Log4jUtils() { - } - - public static void init() throws Exception { - init(Arrays.asList("classpath*:config/base/log4j.properties", "classpath*:config/log4j.properties")); - } - - public static void init(String locationPattern) throws Exception { - init(Arrays.asList(locationPattern)); - } - - public static void init(List locationPatterns) throws Exception { - if (inited) { - return; - } - - synchronized (LOCK) { - if (inited) { - return; - } - - PropertiesLoader loader = new PropertiesLoader(locationPatterns); - Properties properties = loader.load(); - if (properties.isEmpty()) { - throw new Exception("can not find resource " + locationPatterns); - } - - PropertyConfigurator.configure(properties); - inited = true; - - if (OUTPUT_CONFIG_ENABLED_TRUE.equals( - properties.getProperty(OUTPUT_CONFIG_ENABLED, OUTPUT_CONFIG_ENABLED_TRUE))) { - // If the property file with the highest priority is on a hard disk(not in a jar package) - // and we have write access, output the merged property file for the purpose of debugging - outputFile(loader.getFoundResList(), properties); - } - } - } - - private static void outputFile(List resList, - Properties properties) throws IOException { - //不可以作为class的变量初始化,因为在outputFile前一句log机制才初始化完成的 - //must create org.slf4j.impl.Log4jLoggerAdapter by LoggerExtFactory - //in order to redefine Log4jLoggerAdapter before other class load Log4jLoggerAdapter - Logger log = LoggerFactory.getLogger(Log4jUtils.class); - - String content = genFileContext(resList, properties); - //不打印配置信息,有密钥等敏感信息 - //log.info("Merged log4j:\n{}", content); - - Resource res = resList.get(resList.size() - 1); - // 不能直接使用res.getFile,因为jar里面的资源,getFile会抛异常 - File file = new File(res.getURL().getPath()); - if (!file.getParentFile().canWrite()) { - log.error("Can not output {},because can not write to directory of file {}", - MERGED_FILE, - res.getURL().getPath()); - return; - } - - File mergedfile = new File(res.getFile().getParentFile(), MERGED_FILE); - FileUtils.writeStringToFile(mergedfile, content, StandardCharsets.UTF_8, false); - log.info("Write merged log4j config file to {}", IOUtils.anonymousPath(mergedfile.getAbsolutePath())); - } - - private static String genFileContext(List resList, Properties properties) throws IOException { - List> entryList = properties.entrySet() - .stream() - .sorted(new Comparator>() { - @Override - public int compare(Entry o1, Entry o2) { - return o1.getKey().toString().compareTo(o2.getKey().toString()); - } - }) - .collect(Collectors.toList()); - - StringBuilder sb = new StringBuilder(); - for (Resource res : resList) { - sb.append("#").append(res.getURL().getPath()).append("\n"); - } - for (Entry entry : entryList) { - sb.append(entry.getKey()).append("=").append(entry.getValue()).append("\n"); - } - return sb.toString(); - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MimeTypesUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MimeTypesUtils.java index f96851a8758..25bf4cb4610 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MimeTypesUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MimeTypesUtils.java @@ -36,45 +36,38 @@ public class MimeTypesUtils { private static final Pattern EQUAL_SPLITTER = Pattern.compile(" *= *"); - private static final Comparator ACCEPT_X_COMPARATOR = new Comparator() { - float getQuality(String s) { - if (s == null) { - return 0; - } + private static final Comparator ACCEPT_X_COMPARATOR = (o1, o2) -> Float.compare(getQuality(o2), getQuality(o1)); - String[] params = SEMICOLON_SPLITTER.split(s); - for (int i = 1; i < params.length; i++) { - String[] q = EQUAL_SPLITTER.split(params[1]); - if ("q".equals(q[0])) { - return Float.parseFloat(q[1]); - } - } - return 1; + private static float getQuality(String s) { + if (s == null) { + return 0; } - @Override - public int compare(String o1, String o2) { - float f1 = getQuality(o1); - float f2 = getQuality(o2); - return Float.compare(f2, f1); + String[] params = SEMICOLON_SPLITTER.split(s); + for (int i = 1; i < params.length; i++) { + String[] q = EQUAL_SPLITTER.split(params[1]); + if ("q".equals(q[0])) { + return Float.parseFloat(q[1]); + } } - }; + return 1; + } public static List getSortedAcceptableMimeTypes(String acceptHeader) { - // accept anything when accept is not present + // accept anything when accept is not present if (acceptHeader == null) { return Collections.emptyList(); } - // parse + // parse String[] items = COMMA_SPLITTER.split(acceptHeader); - // sort on quality + // sort on quality Arrays.sort(items, ACCEPT_X_COMPARATOR); List list = new ArrayList<>(items.length); for (String item : items) { - // find any ; e.g.: "application/json;q=0.8" + // find any ; e.g.: "application/json;q=0.8" int space = item.indexOf(';'); if (space != -1) { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MuteExceptionUtil.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MuteExceptionUtil.java new file mode 100644 index 00000000000..334ae13808f --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/MuteExceptionUtil.java @@ -0,0 +1,93 @@ +/* + * 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.foundation.common.utils; + +import java.util.concurrent.CompletableFuture; +import java.util.function.Supplier; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MuteExceptionUtil { + + public interface FunctionWithException { + R apply(T t) throws Exception; + } + + public interface FunctionWithDoubleParam { + R apply(T1 t1, T2 t2) throws Exception; + } + + private static final Logger LOGGER = LoggerFactory.getLogger(MuteExceptionUtil.class); + + public static class MuteExceptionUtilBuilder { + + private String logMessage; + + private Object[] customMessageParams; + + public MuteExceptionUtilBuilder withLog(String message, Object... params) { + this.logMessage = message; + this.customMessageParams = params; + return this; + } + + private String getLogMessage(String defaultMessage) { + return logMessage != null ? logMessage : defaultMessage; + } + + public R executeFunction(FunctionWithException function, T t) { + try { + return function.apply(t); + } catch (Exception e) { + LOGGER.error(getLogMessage("execute Function failure..."), customMessageParams, e); + return null; + } + } + + public T executeSupplier(Supplier supplier) { + try { + return supplier.get(); + } catch (Exception e) { + LOGGER.error(getLogMessage("execute Supplier failure..."), customMessageParams, e); + return null; + } + } + + public T executeCompletableFuture(CompletableFuture completableFuture) { + try { + return completableFuture.get(); + } catch (Exception e) { + LOGGER.error(getLogMessage("execute CompletableFuture failure..."), customMessageParams, e); + return null; + } + } + + public R executeFunctionWithDoubleParam(FunctionWithDoubleParam function, T1 t1, T2 t2) { + try { + return function.apply(t1, t2); + } catch (Exception e) { + LOGGER.error(getLogMessage("execute FunctionWithDoubleParam failure..."), customMessageParams, e); + return null; + } + } + } + + public static MuteExceptionUtilBuilder builder() { + return new MuteExceptionUtilBuilder(); + } +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/PartUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/PartUtils.java index cb9b23393be..61bbf442e11 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/PartUtils.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/PartUtils.java @@ -19,14 +19,14 @@ import java.io.File; import java.io.InputStream; -import javax.servlet.http.Part; - import org.apache.servicecomb.foundation.common.part.FilePart; import org.apache.servicecomb.foundation.common.part.InputStreamPart; import org.apache.servicecomb.foundation.common.part.ResourcePart; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; +import jakarta.servlet.http.Part; + public final class PartUtils { private PartUtils() { } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RSAKeyPairEntry.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RSAKeyPairEntry.java deleted file mode 100644 index dd1b442a100..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RSAKeyPairEntry.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.foundation.common.utils; - -import java.security.PrivateKey; -import java.security.PublicKey; - -public final class RSAKeyPairEntry { - - private PrivateKey privateKey; - - private PublicKey publicKey; - - private String publicKeyEncoded; - - public RSAKeyPairEntry(PrivateKey privateKey, PublicKey publicKey, String publicKeyEncoded) { - this.privateKey = privateKey; - this.publicKey = publicKey; - this.publicKeyEncoded = publicKeyEncoded; - } - - public PrivateKey getPrivateKey() { - return privateKey; - } - - public PublicKey getPublicKey() { - return publicKey; - } - - public String getPublicKeyEncoded() { - return publicKeyEncoded; - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RSAUtils.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RSAUtils.java deleted file mode 100644 index 0cded9129c4..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RSAUtils.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.foundation.common.utils; - -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.X509EncodedKeySpec; -import java.util.Base64; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RSAUtils { - - private final static Logger LOGGER = LoggerFactory.getLogger(RSAUtils.class); - - private final static String RSA_ALG = "RSA"; - - private final static String SIGN_ALG = "SHA256withRSA"; - - private final static int KEY_SIZE = 2048; - - private static Base64.Encoder encoder = Base64.getEncoder(); - - private static Base64.Decoder decoder = Base64.getDecoder(); - - private static KeyFactory kf = null; - - static { - - try { - kf = KeyFactory.getInstance(RSA_ALG); - } catch (NoSuchAlgorithmException e) { - LOGGER.error("init keyfactory error"); - } - } - - public static RSAKeyPairEntry generateRSAKeyPair() { - try { - KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance(RSA_ALG); - keyGenerator.initialize(KEY_SIZE, new SecureRandom()); - KeyPair keyPair = keyGenerator.generateKeyPair(); - PublicKey pubKey = keyPair.getPublic(); - PrivateKey privKey = keyPair.getPrivate(); - return new RSAKeyPairEntry(privKey, pubKey, encoder.encodeToString(pubKey.getEncoded())); - } catch (NoSuchAlgorithmException e) { - LOGGER.error("generate rsa keypair faild"); - throw new IllegalStateException("perhaps error occurred on jre"); - } - } - - /** - * if has performance problem ,change Signature to ThreadLocal instance - */ - public static String sign(String content, PrivateKey privateKey) - throws NoSuchAlgorithmException, InvalidKeySpecException, SignatureException, InvalidKeyException { - Signature signature = Signature.getInstance(SIGN_ALG); - signature.initSign(privateKey); - signature.update(content.getBytes()); - byte[] signByte = signature.sign(); - return encoder.encodeToString(signByte); - } - - /** - * - * if has performance problem ,change Signature to ThreadLocal instance - * @param publicKey public key after base64 encode - * @param sign 签名 - * @param content original content - * @return verify result - * @throws NoSuchAlgorithmException - * @throws InvalidKeySpecException - * @throws InvalidKeyException - * @throws SignatureException - */ - public static boolean verify(String publicKey, String sign, String content) - throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { - if (null == kf) { - throw new NoSuchAlgorithmException(RSA_ALG + " KeyFactory not available"); - } - byte[] bytes = decoder.decode(publicKey); - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes); - PublicKey pubKey = kf.generatePublic(keySpec); - Signature signature = Signature.getInstance(SIGN_ALG); - signature.initVerify(pubKey); - signature.update(content.getBytes()); - return signature.verify(decoder.decode(sign)); - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ResourceUtil.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ResourceUtil.java index 4aa7e33bedf..037900d9a7a 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ResourceUtil.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/ResourceUtil.java @@ -68,8 +68,7 @@ public static List findResources(String resourceLocation, Predicate f Enumeration dirURLs = JvmUtils.findClassLoader().getResources(resourceLocation); while (dirURLs.hasMoreElements()) { URL dirURL = dirURLs.nextElement(); - - if (dirURL.getProtocol().equals("file")) { + if ("file".equals(dirURL.getProtocol())) { Path dirPath = Paths.get(dirURL.toURI()); collectResourcesFromPath(dirPath, filter, result); continue; @@ -77,7 +76,16 @@ public static List findResources(String resourceLocation, Predicate f try (FileSystem fileSystem = FileSystems.newFileSystem(dirURL.toURI(), Collections.emptyMap())) { Path dirPath = fileSystem.getPath(resourceLocation); - collectResourcesFromPath(dirPath, filter, result); + if (Files.exists(dirPath)) { + // normal jar files like : xxx.jar!/resourceLocation + collectResourcesFromPath(dirPath, filter, result); + } else { + // spring boot fat jar files like : xxx.jar!/BOOT-INF/!classes/resourceLocation + dirPath = fileSystem.getPath("BOOT-INF", "classes", resourceLocation); + if (Files.exists(dirPath)) { + collectResourcesFromPath(dirPath, filter, result); + } + } } } diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java index 4fd41fcb94f..edc6095878f 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RestObjectMapper.java @@ -47,13 +47,15 @@ public void serialize(JsonObject value, JsonGenerator jgen, SerializerProvider p private static final JavaType STRING_JAVA_TYPE = TypeFactory.defaultInstance().constructType(String.class); public RestObjectMapper() { + super(); getFactory().disable(Feature.AUTO_CLOSE_SOURCE); // Enable features that can tolerance errors and not enable those make more constraints for compatible reasons. // Developers can use validation api to do more checks. disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // no view annotations shouldn't be included in JSON - disable(MapperFeature.DEFAULT_VIEW_INCLUSION); + this._deserializationConfig = this._deserializationConfig.without(MapperFeature.DEFAULT_VIEW_INCLUSION); + this._serializationConfig = this._serializationConfig.without(MapperFeature.DEFAULT_VIEW_INCLUSION); disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); enable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); @@ -65,6 +67,15 @@ public RestObjectMapper() { registerModule(new JavaTimeModule()); } + public RestObjectMapper(RestObjectMapper src) { + super(src); + } + @Override + public RestObjectMapper copy() { + this._checkInvalidCopy(RestObjectMapper.class); + return new RestObjectMapper(this); + } + @Override public String convertToString(Object value) throws Exception { return convertValue(value, STRING_JAVA_TYPE); diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RollingFileAppenderExt.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RollingFileAppenderExt.java deleted file mode 100644 index 70dd285f62c..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/RollingFileAppenderExt.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.foundation.common.utils; - -import java.io.File; -import java.io.IOException; - -import org.apache.log4j.RollingFileAppender; -import org.apache.log4j.helpers.LogLog; -import org.apache.log4j.spi.LoggingEvent; - -/** - * 扩展增加2个功能:1. 设置文件权限;2. 文件删除后重建。 - */ -public class RollingFileAppenderExt extends RollingFileAppender { - private File currentFile; - - private boolean append; - - private String logPermission; - - public String getLogPermission() { - return logPermission; - } - - public void setLogPermission(String logPermission) { - this.logPermission = logPermission; - } - - @Override - public void setFile(String file) { - super.setFile(file); - } - - @Override - public void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException { - this.append = append; - currentFile = new File(fileName); - createCurrentFile(); - super.setFile(fileName, append, bufferedIO, bufferSize); - } - - @Override - protected void subAppend(LoggingEvent event) { - // create a new file when file deleted - if (!currentFile.exists()) { - try { - setFile(fileName, append, bufferedIO, bufferSize); - } catch (IOException e) { - LogLog.error("", e); - } - } - super.subAppend(event); - } - - protected void createCurrentFile() throws IOException { - if (!currentFile.exists()) { - File parent = currentFile.getParentFile(); - if (parent != null && !parent.exists()) { - parent.mkdirs(); - } - currentFile.createNewFile(); - } - FilePerm.setFilePerm(currentFile, logPermission); - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapGetter.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapGetter.java index 04d71048ebb..84039d3595a 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapGetter.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapGetter.java @@ -19,7 +19,7 @@ import java.util.Map; public class MapGetter implements Getter, V> { - private K key; + private final K key; public MapGetter(K key) { this.key = key; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapSetter.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapSetter.java index 4ed23951a2b..872d00a63a4 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapSetter.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/bean/MapSetter.java @@ -19,7 +19,7 @@ import java.util.Map; public class MapSetter implements Setter, V> { - private K key; + private final K key; public MapSetter(K key) { this.key = key; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java index 98b489f9c12..5b4f80b9ddb 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartDeserializer.java @@ -19,12 +19,12 @@ import java.io.IOException; -import javax.servlet.http.Part; - import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; +import jakarta.servlet.http.Part; + public class JavaxServletPartDeserializer extends JsonDeserializer { @Override public Part deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java index eca1db08a88..c964241b42c 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/JavaxServletPartSerializer.java @@ -19,14 +19,14 @@ import java.io.IOException; -import javax.servlet.http.Part; - import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.util.TokenBuffer; +import jakarta.servlet.http.Part; + // 什么情况下用? public class JavaxServletPartSerializer extends StdSerializer { private static final long serialVersionUID = 348443113789878443L; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/PartModule.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/PartModule.java index 7749a9534d2..5c3b8a53bd6 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/PartModule.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/utils/json/PartModule.java @@ -16,12 +16,12 @@ */ package org.apache.servicecomb.foundation.common.utils.json; -import javax.servlet.http.Part; - import org.apache.servicecomb.foundation.common.utils.SPIOrder; import com.fasterxml.jackson.databind.module.SimpleModule; +import jakarta.servlet.http.Part; + public class PartModule extends SimpleModule implements SPIOrder { private static final long serialVersionUID = 4201325332650814739L; diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/logback/MarkerFilter.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/logback/MarkerFilter.java deleted file mode 100644 index 8bb39c776b9..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/logback/MarkerFilter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.foundation.logback; - -import org.slf4j.Marker; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.filter.AbstractMatcherFilter; -import ch.qos.logback.core.spi.FilterReply; - -/** - * Create a marker filter for logback usage. lockback 1.2.3 do not provide any marker filter. But higher - * versions provide one. If you are using a more higher version, you can use the native one. - * - * see: https://github.com/qos-ch/logback/pull/407/files - */ -public class MarkerFilter extends AbstractMatcherFilter { - private String marker; - - public MarkerFilter() { - setOnMatch(FilterReply.ACCEPT); - setOnMismatch(FilterReply.DENY); - } - - @Override - public FilterReply decide(ILoggingEvent event) { - if (!isStarted()) { - return FilterReply.NEUTRAL; - } - - Marker currentMarker = event.getMarker(); - - if (currentMarker == null || !marker.equals(currentMarker.getName())) { - return onMismatch; - } else { - return onMatch; - } - } - - public void setMarker(String marker) { - this.marker = marker; - } - - @Override - public void start() { - if (this.marker != null) { - super.start(); - } - } -} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/token/Keypair4Auth.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/token/Keypair4Auth.java new file mode 100644 index 00000000000..a3172419465 --- /dev/null +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/token/Keypair4Auth.java @@ -0,0 +1,69 @@ +/* + * 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.foundation.token; + +import java.security.PrivateKey; +import java.security.PublicKey; + +/** + * 进程级别公私钥对 + * + */ +public class Keypair4Auth { + + private Keypair4Auth() { + } + + private PrivateKey privateKey; + + private PublicKey publicKey; + + private String publicKeyEncoded; + + + public PrivateKey getPrivateKey() { + return privateKey; + } + + + public void setPrivateKey(PrivateKey privateKey) { + this.privateKey = privateKey; + } + + + public PublicKey getPublicKey() { + return publicKey; + } + + + public void setPublicKey(PublicKey publicKey) { + this.publicKey = publicKey; + } + + + public String getPublicKeyEncoded() { + return publicKeyEncoded; + } + + + public void setPublicKeyEncoded(String publicKeyEncoded) { + this.publicKeyEncoded = publicKeyEncoded; + } + + public static Keypair4Auth INSTANCE = new Keypair4Auth(); +} diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/token/RSAKeypair4Auth.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/token/RSAKeypair4Auth.java deleted file mode 100644 index b95cbf32a3e..00000000000 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/token/RSAKeypair4Auth.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.foundation.token; - -import java.security.PrivateKey; -import java.security.PublicKey; - -/** - * 进程级别公私钥对 - * - */ -public class RSAKeypair4Auth { - - private RSAKeypair4Auth() { - } - - private PrivateKey privateKey; - - private PublicKey publicKey; - - private String publicKeyEncoded; - - - public PrivateKey getPrivateKey() { - return privateKey; - } - - - public void setPrivateKey(PrivateKey privateKey) { - this.privateKey = privateKey; - } - - - public PublicKey getPublicKey() { - return publicKey; - } - - - public void setPublicKey(PublicKey publicKey) { - this.publicKey = publicKey; - } - - - public String getPublicKeyEncoded() { - return publicKeyEncoded; - } - - - public void setPublicKeyEncoded(String publicKeyEncoded) { - this.publicKeyEncoded = publicKeyEncoded; - } - - public static RSAKeypair4Auth INSTANCE = new RSAKeypair4Auth(); -} diff --git a/foundations/foundation-common/src/main/resources/META-INF/mime.types b/foundations/foundation-common/src/main/resources/META-INF/mime.types index 3e85536f857..eec38ecd549 100644 --- a/foundations/foundation-common/src/main/resources/META-INF/mime.types +++ b/foundations/foundation-common/src/main/resources/META-INF/mime.types @@ -154,4 +154,3 @@ application/x-x509-ca-cert cacert application/x-x509-server-cert scert application/x-x509-user-cert ucert application/x-x509-email-cert ecert - diff --git a/foundations/foundation-common/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.encrypt.Encryption b/foundations/foundation-common/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.encrypt.Encryption index 0e40feb3d0f..f954930aa71 100644 --- a/foundations/foundation-common/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.encrypt.Encryption +++ b/foundations/foundation-common/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.common.encrypt.Encryption @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.foundation.common.encrypt.NoEncryption \ No newline at end of file +org.apache.servicecomb.foundation.common.encrypt.NoEncryption diff --git a/foundations/foundation-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/foundations/foundation-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..de62f3b7eb0 --- /dev/null +++ b/foundations/foundation-common/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -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.apache.servicecomb.foundation.auth.FoundationCommonAuthConfiguration +org.apache.servicecomb.foundation.common.event.EventManager diff --git a/foundations/foundation-common/src/main/resources/config/base/log4j.properties b/foundations/foundation-common/src/main/resources/config/base/log4j.properties deleted file mode 100644 index 83de4e47594..00000000000 --- a/foundations/foundation-common/src/main/resources/config/base/log4j.properties +++ /dev/null @@ -1,39 +0,0 @@ -# -# 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. -# - -##log4j DEBUG < INFO < WARN < ERROR < FATAL -log4j.rootLogger=INFO,paas,stdout -paas.logs.dir=./ -paas.logs.file=cse.log - -#if not set runLogger level ,log4Utils.init will meet a null point error -log4j.logger.runLogger=INFO - -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%p] %m %l%n - -log4j.appender.paas=org.apache.servicecomb.foundation.common.utils.RollingFileAppenderExt -log4j.appender.paas.file=${paas.logs.dir}${paas.logs.file} -log4j.appender.paas.MaxFileSize=20MB -log4j.appender.paas.MaxBackupIndex=10 -log4j.appender.paas.layout=org.apache.log4j.PatternLayout -log4j.appender.paas.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS/zzz}][%t][%p]%m %l%n -log4j.appender.paas.logPermission=rw------- - -# do not print configuration content -log4j.logger.com.netflix.config.DynamicPropertyUpdater=OFF diff --git a/foundations/foundation-common/src/test/java/TestNoPackageMain.java b/foundations/foundation-common/src/test/java/TestNoPackageMain.java deleted file mode 100644 index 75fe8789362..00000000000 --- a/foundations/foundation-common/src/test/java/TestNoPackageMain.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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. - */ - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.JvmUtils; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; - -public class TestNoPackageMain { - @Test - public void prepareServiceCombScanPackage_mainNoPackage() { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - new Expectations(JvmUtils.class) { - { - JvmUtils.findMainClass(); - result = TestNoPackageMain.class; - JvmUtils.findMainClassByStackTrace(); - result = null; - } - }; - - BeanUtils.prepareServiceCombScanPackage(); - - Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); - } -} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/DynamicObjectTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/DynamicObjectTest.java index 25848c46ef4..6867124543b 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/DynamicObjectTest.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/DynamicObjectTest.java @@ -39,4 +39,4 @@ void should_support_json_encode_decode() { assertThat(dynamicObject.getDynamic()).isEqualTo(map); assertThat(Json.encode(dynamicObject)).isEqualTo("{\"k\":\"v\"}"); } -} \ No newline at end of file +} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/base/DynamicEnumTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/base/DynamicEnumTest.java index 665817287b0..836be565147 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/base/DynamicEnumTest.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/base/DynamicEnumTest.java @@ -98,4 +98,4 @@ void should_not_cache_unknown_value() { Color value2 = Json.decodeValue(UNKNOWN_COLOR, Color.class); assertThat(value1).isNotSameAs(value2); } -} \ No newline at end of file +} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/cache/TestVersionedCache.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/cache/TestVersionedCache.java index b2909374474..cdfe99f57b8 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/cache/TestVersionedCache.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/cache/TestVersionedCache.java @@ -20,28 +20,27 @@ import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Assert; -import org.junit.Test; - import mockit.Deencapsulation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestVersionedCache { - private static AtomicInteger VERSION = Deencapsulation.getField(VersionedCache.class, "VERSION"); + private static final AtomicInteger VERSION = Deencapsulation.getField(VersionedCache.class, "VERSION"); @Test public void construct() { VersionedCache cache = new VersionedCache(); - Assert.assertNull(cache.data()); - Assert.assertNull(cache.arrayData()); - Assert.assertTrue(cache.isEmpty()); + Assertions.assertNull(cache.data()); + Assertions.assertNull(cache.arrayData()); + Assertions.assertTrue(cache.isEmpty()); } @Test public void autoCacheVersion() { VersionedCache cache = new VersionedCache().autoCacheVersion(); - Assert.assertEquals(VERSION.get(), cache.cacheVersion()); + Assertions.assertEquals(VERSION.get(), cache.cacheVersion()); } @Test @@ -49,14 +48,14 @@ public void setCacheVersion() { VersionedCache parent = new VersionedCache().autoCacheVersion(); VersionedCache cache = new VersionedCache().cacheVersion(parent.cacheVersion()); - Assert.assertEquals(parent.cacheVersion(), cache.cacheVersion()); + Assertions.assertEquals(parent.cacheVersion(), cache.cacheVersion()); } @Test public void setName() { VersionedCache cache = new VersionedCache().name("n"); - Assert.assertEquals("n", cache.name()); + Assertions.assertEquals("n", cache.name()); } @Test @@ -64,31 +63,31 @@ public void setSubName() { VersionedCache parent = new VersionedCache().name("parent"); VersionedCache child = new VersionedCache().subName(parent, "child"); - Assert.assertEquals("parent/child", child.name()); + Assertions.assertEquals("parent/child", child.name()); } @Test public void setMapData() { VersionedCache cache = new VersionedCache().data(Collections.emptyMap()); - Assert.assertSame(Collections.emptyMap(), cache.data()); - Assert.assertSame(Collections.emptyMap(), cache.mapData()); - Assert.assertTrue(cache.isEmpty()); + Assertions.assertSame(Collections.emptyMap(), cache.data()); + Assertions.assertSame(Collections.emptyMap(), cache.mapData()); + Assertions.assertTrue(cache.isEmpty()); cache.data(Collections.singletonMap("k", "v")); - Assert.assertFalse(cache.isEmpty()); + Assertions.assertFalse(cache.isEmpty()); } @Test public void setCollectionData() { VersionedCache cache = new VersionedCache().data(Collections.emptyList()); - Assert.assertSame(Collections.emptyList(), cache.data()); - Assert.assertSame(Collections.emptyList(), cache.collectionData()); - Assert.assertTrue(cache.isEmpty()); + Assertions.assertSame(Collections.emptyList(), cache.data()); + Assertions.assertSame(Collections.emptyList(), cache.collectionData()); + Assertions.assertTrue(cache.isEmpty()); cache.data(Collections.singletonList("v")); - Assert.assertFalse(cache.isEmpty()); + Assertions.assertFalse(cache.isEmpty()); } @Test @@ -96,24 +95,24 @@ public void setArrayData() { Object[] array = Collections.emptyList().toArray(); VersionedCache cache = new VersionedCache().data(array); - Assert.assertSame(array, cache.data()); - Assert.assertSame(array, cache.arrayData()); - Assert.assertTrue(cache.isEmpty()); + Assertions.assertSame(array, cache.data()); + Assertions.assertSame(array, cache.arrayData()); + Assertions.assertTrue(cache.isEmpty()); cache.data(new String[] {"a", "b"}); - Assert.assertFalse(cache.isEmpty()); + Assertions.assertFalse(cache.isEmpty()); } @Test public void setCommonData() { VersionedCache cache = new VersionedCache().data(null); - Assert.assertNull(cache.data()); - Assert.assertNull(cache.arrayData()); - Assert.assertTrue(cache.isEmpty()); + Assertions.assertNull(cache.data()); + Assertions.assertNull(cache.arrayData()); + Assertions.assertTrue(cache.isEmpty()); cache.data("a"); - Assert.assertFalse(cache.isEmpty()); + Assertions.assertFalse(cache.isEmpty()); } @Test @@ -121,9 +120,9 @@ public void isExpired() { VersionedCache cacheOld = new VersionedCache().autoCacheVersion(); VersionedCache cacheNew = new VersionedCache().autoCacheVersion(); - Assert.assertTrue(cacheOld.isExpired(cacheNew)); - Assert.assertFalse(cacheOld.isExpired(cacheOld)); - Assert.assertFalse(cacheNew.isExpired(cacheOld)); + Assertions.assertTrue(cacheOld.isExpired(cacheNew)); + Assertions.assertFalse(cacheOld.isExpired(cacheOld)); + Assertions.assertFalse(cacheNew.isExpired(cacheOld)); } @Test @@ -132,7 +131,7 @@ public void isSameVersion() { VersionedCache cacheNew = new VersionedCache().autoCacheVersion(); VersionedCache cacheSame = new VersionedCache().cacheVersion(cacheNew.cacheVersion()); - Assert.assertFalse(cacheOld.isSameVersion(cacheNew)); - Assert.assertTrue(cacheSame.isSameVersion(cacheNew)); + Assertions.assertFalse(cacheOld.isSameVersion(cacheNew)); + Assertions.assertTrue(cacheSame.isSameVersion(cacheNew)); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/concurrency/RunnableWrapperTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/concurrency/RunnableWrapperTest.java index d9a7da588b7..79581ef3985 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/concurrency/RunnableWrapperTest.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/concurrency/RunnableWrapperTest.java @@ -17,13 +17,12 @@ package org.apache.servicecomb.foundation.common.concurrency; -import static org.junit.Assert.assertEquals; - import java.util.concurrent.CountDownLatch; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class RunnableWrapperTest { /** @@ -61,6 +60,6 @@ public void run() { scheduledThreadPoolExecutor.shutdownNow(); } - assertEquals(0, countDownLatch.getCount()); + Assertions.assertEquals(0, countDownLatch.getCount()); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/config/BeanProp.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/config/BeanProp.java new file mode 100644 index 00000000000..014be9283f1 --- /dev/null +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/config/BeanProp.java @@ -0,0 +1,35 @@ +/* + * 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.foundation.common.config; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class BeanProp { + @JsonProperty(value = "1.2") + private String test; + + public String getTest() { + return test; + } + + public void setTest(String test) { + this.test = test; + } +} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/encrypt/TestEncryptions.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/encrypt/TestEncryptions.java index 74bb90b760a..35090bad520 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/encrypt/TestEncryptions.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/encrypt/TestEncryptions.java @@ -17,11 +17,11 @@ package org.apache.servicecomb.foundation.common.encrypt; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestEncryptions { - class MyEncryption implements Encryption { + static class MyEncryption implements Encryption { @Override public char[] decode(char[] encrypted, String tags) { @@ -42,24 +42,24 @@ public char[] encode(char[] plain, String tags) { @Test public void testEncryptions() { - Assert.assertEquals(Encryptions.decode((String) null, ""), null); - Assert.assertEquals(Encryptions.decode("abcd", ""), "abcd"); - Assert.assertEquals(Encryptions.decode("abcd", null), "abcd"); - Assert.assertEquals(Encryptions.encode((String) null, ""), null); - Assert.assertEquals(Encryptions.encode("abcd", ""), "abcd"); - Assert.assertEquals(Encryptions.decode("abcd", null), "abcd"); + Assertions.assertNull(Encryptions.decode((String) null, "")); + Assertions.assertEquals(Encryptions.decode("abcd", ""), "abcd"); + Assertions.assertEquals(Encryptions.decode("abcd", null), "abcd"); + Assertions.assertNull(Encryptions.encode((String) null, "")); + Assertions.assertEquals(Encryptions.encode("abcd", ""), "abcd"); + Assertions.assertEquals(Encryptions.decode("abcd", null), "abcd"); } @Test public void testEncryptionsMy() { Encryption old = Encryptions.getEncryption(); Encryptions.setEncryption(new MyEncryption()); - Assert.assertEquals(Encryptions.decode((String) null, ""), null); - Assert.assertEquals(Encryptions.decode("abcd", ""), "abcd"); - Assert.assertEquals(Encryptions.decode("abcd", null), null); - Assert.assertEquals(Encryptions.encode((String) null, ""), null); - Assert.assertEquals(Encryptions.encode("abcd", ""), "abcd"); - Assert.assertEquals(Encryptions.encode("abcd", null), null); + Assertions.assertNull(Encryptions.decode((String) null, "")); + Assertions.assertEquals(Encryptions.decode("abcd", ""), "abcd"); + Assertions.assertNull(Encryptions.decode("abcd", null)); + Assertions.assertNull(Encryptions.encode((String) null, "")); + Assertions.assertEquals(Encryptions.encode("abcd", ""), "abcd"); + Assertions.assertNull(Encryptions.encode("abcd", null)); Encryptions.setEncryption(old); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java index 337efdaecc8..68cac748436 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventBus.java @@ -19,23 +19,23 @@ import java.util.ArrayList; import java.util.List; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; import com.google.common.eventbus.AllowConcurrentEvents; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; +import org.junit.jupiter.api.Test; public class TestEventBus { - private EventBus eventBus = new SimpleEventBus(); + private final EventBus eventBus = new SimpleEventBus(); - private List events = new ArrayList<>(); + private final List events = new ArrayList<>(); public static class SubscriberForTest { - private List events; + private final List events; - public SubscriberForTest( List events) { + public SubscriberForTest(List events) { this.events = events; } @Subscribe @@ -51,9 +51,9 @@ public void s2(String event) { } public static class SubscriberWithOrderForTest { - private List events; + private final List events; - public SubscriberWithOrderForTest( List events) { + public SubscriberWithOrderForTest(List events) { this.events = events; } @@ -75,7 +75,7 @@ public void order() { eventBus.register(new SubscriberWithOrderForTest(events)); eventBus.post("value"); - Assert.assertThat(events, Matchers.contains("s2:value", "s1:value")); + MatcherAssert.assertThat(events, Matchers.contains("s2:value", "s1:value")); } @Test @@ -95,7 +95,7 @@ public void oneSubscriber() { eventBus.post(0.1); eventBus.post(1); eventBus.post("str"); - Assert.assertThat(events, Matchers.contains(1, "str")); + MatcherAssert.assertThat(events, Matchers.contains(1, "str")); eventBus.unregister(obj); @@ -103,7 +103,7 @@ public void oneSubscriber() { eventBus.post(0.1); eventBus.post(1); eventBus.post("str"); - Assert.assertThat(events, Matchers.empty()); + MatcherAssert.assertThat(events, Matchers.empty()); } @Test @@ -117,13 +117,13 @@ public void twoSubscriber() { eventBus.post(0.1); eventBus.post(1); eventBus.post("str"); - Assert.assertThat(events, Matchers.contains(1, 1, "str", "str")); + MatcherAssert.assertThat(events, Matchers.contains(1, 1, "str", "str")); events.clear(); eventBus.unregister(obj1); eventBus.post(0.1); eventBus.post(1); eventBus.post("str"); - Assert.assertThat(events, Matchers.contains(1, "str")); + MatcherAssert.assertThat(events, Matchers.contains(1, "str")); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java index 77df59db2bf..736a933159b 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/event/TestEventManager.java @@ -18,10 +18,10 @@ package org.apache.servicecomb.foundation.common.event; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; -import org.junit.Assert; -import org.junit.Test; import com.google.common.eventbus.Subscribe; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestEventManager { private int objCount = 0; @@ -32,14 +32,14 @@ public void test(Object listener) { EventManager.register(listener); EventManager.post("a"); EventManager.post(1); - Assert.assertEquals(2, objCount); - Assert.assertEquals(1, iCount); + Assertions.assertEquals(2, objCount); + Assertions.assertEquals(1, iCount); EventManager.unregister(listener); EventManager.post("a"); EventManager.post(1); - Assert.assertEquals(2, objCount); - Assert.assertEquals(1, iCount); + Assertions.assertEquals(2, objCount); + Assertions.assertEquals(1, iCount); } @Test @@ -47,8 +47,8 @@ public void normalListener() { LogCollector collector = new LogCollector(); test(this); - Assert.assertTrue(collector.getEvents().isEmpty()); // ensure no warning logs - collector.teardown(); + Assertions.assertTrue(collector.getEvents().isEmpty()); // ensure no warning logs + collector.tearDown(); } @Test @@ -67,12 +67,12 @@ void onInt(Integer obj) { }; try { test(listener); - Assert.fail(); + Assertions.fail(); } catch (IllegalStateException e) { - Assert.assertTrue(true); + Assertions.assertTrue(true); } - collector.teardown(); + collector.tearDown(); } @Test @@ -91,14 +91,14 @@ public void onInt(Integer obj) { }; try { test(listener); - Assert.fail(); + Assertions.fail(); } catch (IllegalStateException e) { - Assert.assertTrue(true); + Assertions.assertTrue(true); } // ensure logs: "LOGGER.warn("Failed to create lambda for method: {}, fallback to reflect.", method, throwable);" - Assert.assertTrue(!collector.getEvents().isEmpty()); - collector.teardown(); + Assertions.assertFalse(collector.getEvents().isEmpty()); + collector.tearDown(); } @Subscribe @@ -111,4 +111,3 @@ public void onInt(Integer obj) { iCount++; } } - diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatus.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatus.java index 71e6eb46d59..b48ceeb4ee0 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatus.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatus.java @@ -17,41 +17,40 @@ package org.apache.servicecomb.foundation.common.http; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.Status.Family; - -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status.Family; public class TestHttpStatus { @Test public void testIsSuccessCode() { - Assert.assertTrue(HttpStatus.isSuccess(200)); - Assert.assertFalse(HttpStatus.isSuccess(300)); + Assertions.assertTrue(HttpStatus.isSuccess(200)); + Assertions.assertFalse(HttpStatus.isSuccess(300)); } @Test public void testIsSuccessType() { - Assert.assertTrue(HttpStatus.isSuccess(Status.OK)); - Assert.assertFalse(HttpStatus.isSuccess(Status.BAD_REQUEST)); + Assertions.assertTrue(HttpStatus.isSuccess(Status.OK)); + Assertions.assertFalse(HttpStatus.isSuccess(Status.BAD_REQUEST)); } @Test public void testGetStatusCode() { HttpStatus status = new HttpStatus(200, "ok"); - Assert.assertEquals(200, status.getStatusCode()); + Assertions.assertEquals(200, status.getStatusCode()); } @Test public void testGetFamily() { HttpStatus status = new HttpStatus(200, "ok"); - Assert.assertEquals(Family.familyOf(200), status.getFamily()); + Assertions.assertEquals(Family.familyOf(200), status.getFamily()); } @Test public void testGetReasonPhrase() { HttpStatus status = new HttpStatus(200, "ok"); - Assert.assertEquals("ok", status.getReasonPhrase()); + Assertions.assertEquals("ok", status.getReasonPhrase()); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatusUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatusUtils.java index ac546524109..87776b326ef 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatusUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpStatusUtils.java @@ -17,39 +17,32 @@ package org.apache.servicecomb.foundation.common.http; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.Response.StatusType; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestHttpStatusUtils { HttpStatusManager mgr = new HttpStatusManager(); StatusType st; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testStandard() { st = HttpStatusUtils.getOrCreateByStatusCode(200); - Assert.assertEquals(200, st.getStatusCode()); + Assertions.assertEquals(200, st.getStatusCode()); } @Test public void testNotStandard() { st = mgr.getOrCreateByStatusCode(250); - Assert.assertEquals(250, st.getStatusCode()); + Assertions.assertEquals(250, st.getStatusCode()); } @Test public void testAddRepeat() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("repeated status code: 200")); - - mgr.addStatusType(new HttpStatus(200, "ok")); + IllegalStateException illegalStateException = Assertions.assertThrows(IllegalStateException.class, + () -> mgr.addStatusType(new HttpStatus(200, "ok"))); + Assertions.assertEquals("repeated status code: 200", illegalStateException.getMessage()); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java index 43587fcfb4c..113df2905f1 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/http/TestHttpUtils.java @@ -18,94 +18,80 @@ import java.net.URISyntaxException; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestHttpUtils { - @Rule - public ExpectedException expectedException = ExpectedException.none(); @Test public void parseParamFromHeaderValue_normal() { - Assert.assertEquals("v", HttpUtils.parseParamFromHeaderValue("xx;k=v", "k")); - } - - @Test - public void parseParamFromHeaderValue_normal_ignoreCase() { - Assert.assertEquals("v", HttpUtils.parseParamFromHeaderValue("xx;K=v", "k")); + Assertions.assertEquals("a", HttpUtils.parseParamFromHeaderValue("key1=a;key2=b", "key1")); + Assertions.assertEquals("b", HttpUtils.parseParamFromHeaderValue("key1=a;key2= b", "key2")); + Assertions.assertEquals("b", HttpUtils.parseParamFromHeaderValue("key1=a; key2=b", "key2")); + Assertions.assertEquals("a", HttpUtils.parseParamFromHeaderValue("key1=\"a\";key2=\"b\"", "key1")); + Assertions.assertEquals("b", HttpUtils.parseParamFromHeaderValue("key1=\"a\";key2=\" b\"", "key2")); + Assertions.assertEquals("b", HttpUtils.parseParamFromHeaderValue("key1=\"a\"; key2=\"b\"", "key2")); + Assertions.assertEquals("b c.txt", HttpUtils.parseParamFromHeaderValue("key1=\"a\"; key2=\"b c.txt\"", "key2")); } @Test public void parseParamFromHeaderValue_null() { - Assert.assertNull(HttpUtils.parseParamFromHeaderValue(null, "k")); - } - - @Test - public void parseParamFromHeaderValue_noKv() { - Assert.assertNull(HttpUtils.parseParamFromHeaderValue("xx", "k")); + Assertions.assertNull(HttpUtils.parseParamFromHeaderValue(null, "key")); + Assertions.assertNull(HttpUtils.parseParamFromHeaderValue("key1=a; key2=b", "key")); } @Test - public void parseParamFromHeaderValue_noV() { - Assert.assertEquals("", HttpUtils.parseParamFromHeaderValue("xx;k=", "k")); - } - - @Test - public void parseParamFromHeaderValue_keyNotFound() { - Assert.assertNull(HttpUtils.parseParamFromHeaderValue("xx;k=", "kk")); + public void parseParamFromHeaderValue_emptyStr() { + Assertions.assertEquals("", HttpUtils.parseParamFromHeaderValue("key1=a; key2=", "key2")); } @Test public void uriEncode_null() { - Assert.assertEquals("", HttpUtils.uriEncodePath(null)); + Assertions.assertEquals("", HttpUtils.uriEncodePath(null)); } @Test public void uriDecode_null() { - Assert.assertNull(HttpUtils.uriDecodePath(null)); + Assertions.assertNull(HttpUtils.uriDecodePath(null)); } @Test public void uriEncode_chineseAndSpace() { String encoded = HttpUtils.uriEncodePath("测 试"); - Assert.assertEquals("%E6%B5%8B%20%E8%AF%95", encoded); - Assert.assertEquals("测 试", HttpUtils.uriDecodePath(encoded)); + Assertions.assertEquals("%E6%B5%8B%20%E8%AF%95", encoded); + Assertions.assertEquals("测 试", HttpUtils.uriDecodePath(encoded)); } @Test public void uriEncode_failed() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage(Matchers.is("uriEncode failed, path=\":\".")); - expectedException.expectCause(Matchers.instanceOf(URISyntaxException.class)); - - HttpUtils.uriEncodePath(":"); + IllegalArgumentException illegalArgumentException = Assertions.assertThrows(IllegalArgumentException.class, + () -> HttpUtils.uriEncodePath(":")); + Assertions.assertEquals("uriEncode failed, path=\":\".", illegalArgumentException.getMessage()); + Assertions.assertTrue(illegalArgumentException.getCause() instanceof URISyntaxException); } @Test public void uriEncode_plus() { String encoded = HttpUtils.uriEncodePath("a+b"); - Assert.assertEquals("a+b", encoded); - Assert.assertEquals("a+b", HttpUtils.uriDecodePath(encoded)); + Assertions.assertEquals("a+b", encoded); + Assertions.assertEquals("a+b", HttpUtils.uriDecodePath(encoded)); } @Test public void uriEncode_encodeEntirePath() { String encoded = HttpUtils.uriEncodePath("a%%'+b/def"); - Assert.assertEquals("a%25%25'+b/def", encoded); + Assertions.assertEquals("a%25%25'+b/def", encoded); } @Test public void pathParamEncode() { - Assert.assertEquals("a+b", HttpUtils.encodePathParam("a+b")); - Assert.assertEquals("a%25b", HttpUtils.encodePathParam("a%b")); - Assert.assertEquals("a%25%25b", HttpUtils.encodePathParam("a%%b")); - Assert.assertEquals("%3C%20%3E'%22%EF%BC%88)&%2F%20%20", HttpUtils.encodePathParam("< >'\"()&/ ")); - Assert.assertEquals("%E6%B5%8B%20%E8%AF%95", HttpUtils.encodePathParam("测 试")); + Assertions.assertEquals("a+b", HttpUtils.encodePathParam("a+b")); + Assertions.assertEquals("a%25b", HttpUtils.encodePathParam("a%b")); + Assertions.assertEquals("a%25%25b", HttpUtils.encodePathParam("a%%b")); + Assertions.assertEquals("%3C%20%3E'%22%EF%BC%88)&%2F%20%20", HttpUtils.encodePathParam("< >'\"()&/ ")); + Assertions.assertEquals("%E6%B5%8B%20%E8%AF%95", HttpUtils.encodePathParam("测 试")); } /** @@ -114,82 +100,80 @@ public void pathParamEncode() { */ @Test public void pathParamEncode_SafeChar() { - Assert.assertEquals("-._~!$'()*,;&=@:+", HttpUtils.encodePathParam("-._~!$'()*,;&=@:+")); + Assertions.assertEquals("-._~!$'()*,;&=@:+", HttpUtils.encodePathParam("-._~!$'()*,;&=@:+")); } @Test public void uriDecode_failed() { - expectedException.expect(IllegalArgumentException.class); - expectedException - .expectMessage(Matchers.is("uriDecode failed, path=\":\".")); - expectedException.expectCause(Matchers.instanceOf(URISyntaxException.class)); - - HttpUtils.uriDecodePath(":"); + IllegalArgumentException illegalArgumentException = Assertions.assertThrows(IllegalArgumentException.class, + () -> HttpUtils.uriDecodePath(":")); + Assertions.assertEquals("uriDecode failed, path=\":\".", illegalArgumentException.getMessage()); + Assertions.assertTrue(illegalArgumentException.getCause() instanceof URISyntaxException); } @Test public void parseFileNameFromHeaderValue() { String fileName = "测 试.txt"; String encoded = HttpUtils.uriEncodePath(fileName); - Assert.assertEquals(fileName, HttpUtils.parseFileNameFromHeaderValue("xx;filename=" + encoded)); + Assertions.assertEquals(fileName, HttpUtils.parseFileNameFromHeaderValue("xx;filename=" + encoded)); } @Test public void parseFileNameFromHeaderValue_defaultName() { - Assert.assertEquals("default", HttpUtils.parseFileNameFromHeaderValue("xx")); + Assertions.assertEquals("default", HttpUtils.parseFileNameFromHeaderValue("xx")); } @Test public void parseFileNameFromHeaderValue_ignorePath() { - Assert.assertEquals("a.txt", HttpUtils.parseFileNameFromHeaderValue("xx;filename=../../a.txt")); + Assertions.assertEquals("a.txt", HttpUtils.parseFileNameFromHeaderValue("xx;filename=../../a.txt")); } @Test public void getCharsetFromContentType_noContentType() { String character = HttpUtils.getCharsetFromContentType(null); - Assert.assertNull(character); + Assertions.assertNull(character); } @Test public void getCharsetFromContentType_noCharset() { String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON); - Assert.assertNull(character); + Assertions.assertNull(character); } @Test public void getCharsetFromContentType_noSemicolonEnd() { String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=utf-8"); - Assert.assertEquals("utf-8", character); + Assertions.assertEquals("utf-8", character); } @Test public void getCharsetFromContentType_semicolonEnd() { String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=utf-8;"); - Assert.assertEquals("utf-8", character); + Assertions.assertEquals("utf-8", character); } @Test public void getCharsetFromContentType_needTrim() { String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset= utf-8 ;"); - Assert.assertEquals("utf-8", character); + Assertions.assertEquals("utf-8", character); } @Test public void getCharsetFromContentType_quotationMarks() { String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=\"utf-8\";"); - Assert.assertEquals("utf-8", character); + Assertions.assertEquals("utf-8", character); } @Test public void getCharsetFromContentType_quotationMarks_needTrim() { String character = HttpUtils.getCharsetFromContentType(MediaType.APPLICATION_JSON + ";charset=\" utf-8 \";"); - Assert.assertEquals("utf-8", character); + Assertions.assertEquals("utf-8", character); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestIpPort.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestIpPort.java index fcd18bb8f6b..9194515cb28 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestIpPort.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestIpPort.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.foundation.common.net; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestIpPort { @Test @@ -27,12 +27,12 @@ public void testIpPort() { inst1.setHostOrIp("localhost"); inst1.setPort(3333); IpPort inst2 = new IpPort("localhost", 3333); - Assert.assertEquals(inst1.getHostOrIp(), inst2.getHostOrIp()); - Assert.assertEquals(inst1.getPort(), inst2.getPort()); - Assert.assertEquals(inst1.getSocketAddress().getHostName(), inst2.getSocketAddress().getHostName()); - Assert.assertEquals(inst1, inst1); - Assert.assertEquals(inst1, inst2); - Assert.assertEquals(inst1.toString(), "localhost:3333"); - Assert.assertNotEquals(inst1, new Object()); + Assertions.assertEquals(inst1.getHostOrIp(), inst2.getHostOrIp()); + Assertions.assertEquals(inst1.getPort(), inst2.getPort()); + Assertions.assertEquals(inst1.getSocketAddress().getHostName(), inst2.getSocketAddress().getHostName()); + Assertions.assertEquals(inst1, inst1); + Assertions.assertEquals(inst1, inst2); + Assertions.assertEquals(inst1.toString(), "localhost:3333"); + Assertions.assertNotEquals(inst1, new Object()); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestNetUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestNetUtils.java index 90bce85200d..dd13d96d4c6 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestNetUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestNetUtils.java @@ -17,8 +17,6 @@ package org.apache.servicecomb.foundation.common.net; -import static org.junit.Assert.fail; - import java.io.IOException; import java.net.InetAddress; import java.net.ServerSocket; @@ -26,8 +24,8 @@ import java.util.Map; import java.util.function.Consumer; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import mockit.Deencapsulation; @@ -38,52 +36,52 @@ public void testFindProperHostAddress() { NetUtils.resetHostName(); String result = NetUtils.getHostName(); System.out.println(result); - Assert.assertNotNull(result); + Assertions.assertNotNull(result); result = NetUtils.getHostAddress(); System.out.println(result); - Assert.assertNotNull(result); + Assertions.assertNotNull(result); result = NetUtils.getIpv6HostAddress(); System.out.println(result); if (result != null) { - Assert.assertFalse(result.contains("%")); + Assertions.assertFalse(result.contains("%")); } } @Test public void testIpPort() { IpPort oIPPort = new IpPort("10.145.154.45", 8080); - Assert.assertEquals("10.145.154.45", oIPPort.getHostOrIp()); - Assert.assertEquals(8080, oIPPort.getPort()); + Assertions.assertEquals("10.145.154.45", oIPPort.getHostOrIp()); + Assertions.assertEquals(8080, oIPPort.getPort()); oIPPort.setPort(9090); - Assert.assertEquals(9090, oIPPort.getPort()); - Assert.assertNotEquals(null, oIPPort.getSocketAddress()); + Assertions.assertEquals(9090, oIPPort.getPort()); + Assertions.assertNotEquals(null, oIPPort.getSocketAddress()); } @Test public void testNetUtils() { - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPort("127.0.0.1:8080").getHostOrIp()); - Assert.assertEquals(8080, NetUtils.parseIpPort("127.0.0.1:8080").getPort()); - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPort("127.0.0.1").getHostOrIp()); - Assert.assertEquals(-1, NetUtils.parseIpPort("127.0.0.1").getPort()); - Assert.assertEquals(null, NetUtils.parseIpPort((String) null)); - Assert.assertEquals(null, NetUtils.parseIpPortFromURI(null)); - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPortFromURI("rest://127.0.0.1:8080").getHostOrIp()); - Assert.assertEquals(8080, NetUtils.parseIpPortFromURI("http://127.0.0.1:8080").getPort()); - Assert.assertEquals(80, NetUtils.parseIpPortFromURI("http://127.0.0.1").getPort()); - Assert.assertEquals(8080, NetUtils.parseIpPortFromURI("https://127.0.0.1:8080").getPort()); - Assert.assertEquals(443, NetUtils.parseIpPortFromURI("https://127.0.0.1").getPort()); - - Assert.assertEquals(30000, NetUtils.parseIpPort("http", "127.0.0.1:30000").getPort()); - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPort("http", "127.0.0.1:30000").getHostOrIp()); - Assert.assertEquals(30000, NetUtils.parseIpPort("https", "127.0.0.1:30000").getPort()); - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPort("https", "127.0.0.1:30000").getHostOrIp()); - Assert.assertEquals(80, NetUtils.parseIpPort("http", "127.0.0.1").getPort()); - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPort("http", "127.0.0.1").getHostOrIp()); - Assert.assertEquals(443, NetUtils.parseIpPort("https", "127.0.0.1").getPort()); - Assert.assertEquals("127.0.0.1", NetUtils.parseIpPort("https", "127.0.0.1").getHostOrIp()); - Assert.assertNull(NetUtils.parseIpPort("http", null)); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPort("127.0.0.1:8080").getHostOrIp()); + Assertions.assertEquals(8080, NetUtils.parseIpPort("127.0.0.1:8080").getPort()); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPort("127.0.0.1").getHostOrIp()); + Assertions.assertEquals(-1, NetUtils.parseIpPort("127.0.0.1").getPort()); + Assertions.assertNull(NetUtils.parseIpPort((String) null)); + Assertions.assertNull(NetUtils.parseIpPortFromURI(null)); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPortFromURI("rest://127.0.0.1:8080").getHostOrIp()); + Assertions.assertEquals(8080, NetUtils.parseIpPortFromURI("http://127.0.0.1:8080").getPort()); + Assertions.assertEquals(80, NetUtils.parseIpPortFromURI("http://127.0.0.1").getPort()); + Assertions.assertEquals(8080, NetUtils.parseIpPortFromURI("https://127.0.0.1:8080").getPort()); + Assertions.assertEquals(443, NetUtils.parseIpPortFromURI("https://127.0.0.1").getPort()); + + Assertions.assertEquals(30000, NetUtils.parseIpPort("http", "127.0.0.1:30000").getPort()); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPort("http", "127.0.0.1:30000").getHostOrIp()); + Assertions.assertEquals(30000, NetUtils.parseIpPort("https", "127.0.0.1:30000").getPort()); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPort("https", "127.0.0.1:30000").getHostOrIp()); + Assertions.assertEquals(80, NetUtils.parseIpPort("http", "127.0.0.1").getPort()); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPort("http", "127.0.0.1").getHostOrIp()); + Assertions.assertEquals(443, NetUtils.parseIpPort("https", "127.0.0.1").getPort()); + Assertions.assertEquals("127.0.0.1", NetUtils.parseIpPort("https", "127.0.0.1").getHostOrIp()); + Assertions.assertNull(NetUtils.parseIpPort("http", null)); checkException(v -> NetUtils.parseIpPort("127.0.0.18080")); checkException(v -> NetUtils.parseIpPortFromURI("ss")); @@ -91,52 +89,52 @@ public void testNetUtils() { @Test public void testNetUtilsIPv6() { - Assert.assertEquals("[::1]", NetUtils.parseIpPort("[::1]:8080").getHostOrIp()); - Assert.assertEquals("[::]", NetUtils.parseIpPort("[::]:8080").getHostOrIp()); - Assert.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", + Assertions.assertEquals("[::1]", NetUtils.parseIpPort("[::1]:8080").getHostOrIp()); + Assertions.assertEquals("[::]", NetUtils.parseIpPort("[::]:8080").getHostOrIp()); + Assertions.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", NetUtils.parseIpPort("[fe80::f816:3eff:feda:38cd%eth0]:8080").getHostOrIp()); - Assert.assertEquals("[fe80::38f7:44b8:8ab1:468%16]", + Assertions.assertEquals("[fe80::38f7:44b8:8ab1:468%16]", NetUtils.parseIpPort("[fe80::38f7:44b8:8ab1:468%16]:8080").getHostOrIp()); - Assert.assertEquals(8080, NetUtils.parseIpPort("[::1]:8080").getPort()); - Assert.assertEquals(8080, NetUtils.parseIpPort("[::]:8080").getPort()); - Assert.assertEquals(8080, NetUtils.parseIpPort("[fe80::f816:3eff:feda:38cd%eth0]:8080").getPort()); - Assert.assertEquals(8080, NetUtils.parseIpPort("[fe80::38f7:44b8:8ab1:468%16]:8080").getPort()); - - Assert.assertEquals("[::1]", NetUtils.parseIpPortFromURI("rest://[::1]:8080").getHostOrIp()); - Assert.assertEquals("[::]", NetUtils.parseIpPortFromURI("rest://[::]:8080").getHostOrIp()); - Assert.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", + Assertions.assertEquals(8080, NetUtils.parseIpPort("[::1]:8080").getPort()); + Assertions.assertEquals(8080, NetUtils.parseIpPort("[::]:8080").getPort()); + Assertions.assertEquals(8080, NetUtils.parseIpPort("[fe80::f816:3eff:feda:38cd%eth0]:8080").getPort()); + Assertions.assertEquals(8080, NetUtils.parseIpPort("[fe80::38f7:44b8:8ab1:468%16]:8080").getPort()); + + Assertions.assertEquals("[::1]", NetUtils.parseIpPortFromURI("rest://[::1]:8080").getHostOrIp()); + Assertions.assertEquals("[::]", NetUtils.parseIpPortFromURI("rest://[::]:8080").getHostOrIp()); + Assertions.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", NetUtils.parseIpPortFromURI("rest://[fe80::f816:3eff:feda:38cd%eth0]:8080").getHostOrIp()); - Assert.assertEquals("[fe80::38f7:44b8:8ab1:468%16]", + Assertions.assertEquals("[fe80::38f7:44b8:8ab1:468%16]", NetUtils.parseIpPortFromURI("rest://[fe80::38f7:44b8:8ab1:468%16]:8080").getHostOrIp()); - Assert.assertEquals(8080, NetUtils.parseIpPortFromURI("rest://[::1]:8080").getPort()); - Assert.assertEquals(80, NetUtils.parseIpPortFromURI("http://[::1]").getPort()); - Assert.assertEquals(8080, NetUtils.parseIpPortFromURI("https://[::1]:8080").getPort()); - Assert.assertEquals(443, NetUtils.parseIpPortFromURI("https://[::1]").getPort()); + Assertions.assertEquals(8080, NetUtils.parseIpPortFromURI("rest://[::1]:8080").getPort()); + Assertions.assertEquals(80, NetUtils.parseIpPortFromURI("http://[::1]").getPort()); + Assertions.assertEquals(8080, NetUtils.parseIpPortFromURI("https://[::1]:8080").getPort()); + Assertions.assertEquals(443, NetUtils.parseIpPortFromURI("https://[::1]").getPort()); - Assert.assertEquals(30000, NetUtils.parseIpPort("http", "[fe80::f816:3eff:feda:38cd%eth0]:30000").getPort()); - Assert.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", + Assertions.assertEquals(30000, NetUtils.parseIpPort("http", "[fe80::f816:3eff:feda:38cd%eth0]:30000").getPort()); + Assertions.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", NetUtils.parseIpPort("http", "[fe80::f816:3eff:feda:38cd%eth0]:30000").getHostOrIp()); - Assert.assertEquals(30000, NetUtils.parseIpPort("https", "[fe80::f816:3eff:feda:38cd%eth0]:30000").getPort()); - Assert.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", + Assertions.assertEquals(30000, NetUtils.parseIpPort("https", "[fe80::f816:3eff:feda:38cd%eth0]:30000").getPort()); + Assertions.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", NetUtils.parseIpPort("https", "[fe80::f816:3eff:feda:38cd%eth0]:30000").getHostOrIp()); - Assert.assertEquals(80, NetUtils.parseIpPort("http", "[fe80::f816:3eff:feda:38cd%eth0]").getPort()); - Assert.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", + Assertions.assertEquals(80, NetUtils.parseIpPort("http", "[fe80::f816:3eff:feda:38cd%eth0]").getPort()); + Assertions.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", NetUtils.parseIpPort("http", "[fe80::f816:3eff:feda:38cd%eth0]").getHostOrIp()); - Assert.assertEquals(443, NetUtils.parseIpPort("https", "[fe80::f816:3eff:feda:38cd%eth0]").getPort()); - Assert.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", + Assertions.assertEquals(443, NetUtils.parseIpPort("https", "[fe80::f816:3eff:feda:38cd%eth0]").getPort()); + Assertions.assertEquals("[fe80::f816:3eff:feda:38cd%eth0]", NetUtils.parseIpPort("https", "[fe80::f816:3eff:feda:38cd%eth0]").getHostOrIp()); } @Test public void testFullOperation() { - Assert.assertNotNull(NetUtils.getHostAddress()); - Assert.assertNotNull(NetUtils.getHostName()); + Assertions.assertNotNull(NetUtils.getHostAddress()); + Assertions.assertNotNull(NetUtils.getHostName()); } @Test public void testGetRealListenAddress() { - Assert.assertNull(NetUtils.getRealListenAddress("http", null)); - Assert.assertEquals("http://1.1.1.1:8080", NetUtils.getRealListenAddress("http", "1.1.1.1:8080")); + Assertions.assertNull(NetUtils.getRealListenAddress("http", null)); + Assertions.assertEquals("http://1.1.1.1:8080", NetUtils.getRealListenAddress("http", "1.1.1.1:8080")); checkException(v -> NetUtils.getRealListenAddress("http:1", "1.1.1.1:8080")); } @@ -150,14 +148,14 @@ public void testNetworkInterface() { newValue.put("eth100", addr); Deencapsulation.setField(NetUtils.class, "allInterfaceAddresses", newValue); - Assert.assertEquals(addr, NetUtils.getInterfaceAddress("eth100")); - Assert.assertEquals(addr, NetUtils.ensureGetInterfaceAddress("eth100")); + Assertions.assertEquals(addr, NetUtils.getInterfaceAddress("eth100")); + Assertions.assertEquals(addr, NetUtils.ensureGetInterfaceAddress("eth100")); try { NetUtils.ensureGetInterfaceAddress("xxx"); - fail("must throw exception"); + Assertions.fail("must throw exception"); } catch (IllegalArgumentException e) { - Assert.assertEquals("Can not find address for interface name: xxx", e.getMessage()); + Assertions.assertEquals("Can not find address for interface name: xxx", e.getMessage()); } Deencapsulation.setField(NetUtils.class, "allInterfaceAddresses", org); @@ -167,7 +165,7 @@ public void testNetworkInterface() { public void testCanTcpListenNo() throws IOException { InetAddress address = InetAddress.getByName("127.0.0.1"); try (ServerSocket ss = new ServerSocket(0, 0, address)) { - Assert.assertFalse(NetUtils.canTcpListen(address, ss.getLocalPort())); + Assertions.assertFalse(NetUtils.canTcpListen(address, ss.getLocalPort())); } } @@ -178,66 +176,66 @@ public void testCanTcpListenYes() throws IOException { int port = ss.getLocalPort(); ss.close(); - Assert.assertTrue(NetUtils.canTcpListen(address, port)); + Assertions.assertTrue(NetUtils.canTcpListen(address, port)); } @Test public void humanReadableBytes() { - Assert.assertEquals("0", NetUtils.humanReadableBytes(0L)); - Assert.assertEquals("1", NetUtils.humanReadableBytes(1L)); - Assert.assertEquals("1023", NetUtils.humanReadableBytes(1023L)); - - Assert.assertEquals("1.000K", NetUtils.humanReadableBytes(1024L)); - Assert.assertEquals("1.001K", NetUtils.humanReadableBytes(1025L)); - Assert.assertEquals("1023.999K", NetUtils.humanReadableBytes(1024L * 1024 - 1)); - - Assert.assertEquals("1.000M", NetUtils.humanReadableBytes(1024L * 1024)); - Assert.assertEquals("1.000M", NetUtils.humanReadableBytes(1024L * 1024 + 1)); - Assert.assertEquals("1.001M", NetUtils.humanReadableBytes(1024L * 1024 + 1024)); - Assert.assertEquals("1023.999M", NetUtils.humanReadableBytes(1024L * 1024 * 1024 - 1024)); - Assert.assertEquals("1024.000M", NetUtils.humanReadableBytes(1024L * 1024 * 1024 - 1)); - Assert.assertEquals("1.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024)); - Assert.assertEquals("1.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 + 1)); - Assert.assertEquals("1.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 + 1024)); - Assert.assertEquals("1023.999G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 - 1024 * 1024)); - Assert.assertEquals("1024.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 - 1024)); - Assert.assertEquals("1.000T", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024)); - Assert.assertEquals("1.001T", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 + 1024 * 1024 * 1024)); - Assert.assertEquals("1023.999T", + Assertions.assertEquals("0", NetUtils.humanReadableBytes(0L)); + Assertions.assertEquals("1", NetUtils.humanReadableBytes(1L)); + Assertions.assertEquals("1023", NetUtils.humanReadableBytes(1023L)); + + Assertions.assertEquals("1.000K", NetUtils.humanReadableBytes(1024L)); + Assertions.assertEquals("1.001K", NetUtils.humanReadableBytes(1025L)); + Assertions.assertEquals("1023.999K", NetUtils.humanReadableBytes(1024L * 1024 - 1)); + + Assertions.assertEquals("1.000M", NetUtils.humanReadableBytes(1024L * 1024)); + Assertions.assertEquals("1.000M", NetUtils.humanReadableBytes(1024L * 1024 + 1)); + Assertions.assertEquals("1.001M", NetUtils.humanReadableBytes(1024L * 1024 + 1024)); + Assertions.assertEquals("1023.999M", NetUtils.humanReadableBytes(1024L * 1024 * 1024 - 1024)); + Assertions.assertEquals("1024.000M", NetUtils.humanReadableBytes(1024L * 1024 * 1024 - 1)); + Assertions.assertEquals("1.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024)); + Assertions.assertEquals("1.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 + 1)); + Assertions.assertEquals("1.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 + 1024)); + Assertions.assertEquals("1023.999G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 - 1024 * 1024)); + Assertions.assertEquals("1024.000G", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 - 1024)); + Assertions.assertEquals("1.000T", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024)); + Assertions.assertEquals("1.001T", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 + 1024 * 1024 * 1024)); + Assertions.assertEquals("1023.999T", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024 - 1024L * 1024 * 1024)); - Assert.assertEquals("1.000P", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024)); - Assert.assertEquals("1.001P", + Assertions.assertEquals("1.000P", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024)); + Assertions.assertEquals("1.001P", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024 + 1024L * 1024 * 1024 * 1024)); - Assert.assertEquals("1023.999P", + Assertions.assertEquals("1023.999P", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024 * 1024 - 1024L * 1024 * 1024 * 1024)); - Assert.assertEquals("1.000E", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024 * 1024)); - Assert.assertEquals("1.001E", + Assertions.assertEquals("1.000E", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024 * 1024)); + Assertions.assertEquals("1.001E", NetUtils.humanReadableBytes(1024L * 1024 * 1024 * 1024 * 1024 * 1024 + 1024L * 1024 * 1024 * 1024 * 1024)); - Assert.assertEquals("8.000E", NetUtils.humanReadableBytes(Long.MAX_VALUE)); + Assertions.assertEquals("8.000E", NetUtils.humanReadableBytes(Long.MAX_VALUE)); } @Test public void testGetHostName() { - Assert.assertNotEquals(null, NetUtils.getHostName()); + Assertions.assertNotEquals(null, NetUtils.getHostName()); Deencapsulation.setField(NetUtils.class, "hostName", null); - Assert.assertNotEquals(null, NetUtils.getHostName()); + Assertions.assertNotEquals(null, NetUtils.getHostName()); } @Test public void testGetHostAddress() { - Assert.assertNotEquals(null, NetUtils.getHostAddress()); + Assertions.assertNotEquals(null, NetUtils.getHostAddress()); Deencapsulation.setField(NetUtils.class, "hostAddress", null); - Assert.assertNotEquals(null, NetUtils.getHostAddress()); + Assertions.assertNotEquals(null, NetUtils.getHostAddress()); } public void checkException(Consumer testedBehavior) { try { testedBehavior.accept(null); - fail("IllegalArgumentException is expected!"); + Assertions.fail("IllegalArgumentException is expected!"); } catch (Exception e) { - Assert.assertEquals(IllegalArgumentException.class, e.getClass()); + Assertions.assertEquals(IllegalArgumentException.class, e.getClass()); } } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java index 973414eb6e9..dc3323fecc3 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java @@ -23,41 +23,40 @@ import java.util.List; import java.util.Map; -import org.junit.Assert; -import org.junit.Test; - import mockit.Deencapsulation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestURIEndpointObject { @Test public void testRestEndpointObject() { URIEndpointObject obj = new URIEndpointObject("http://127.0.2.0:8080"); - Assert.assertEquals("127.0.2.0", obj.getHostOrIp()); - Assert.assertEquals(8080, obj.getPort()); - Assert.assertFalse(obj.isSslEnabled()); + Assertions.assertEquals("127.0.2.0", obj.getHostOrIp()); + Assertions.assertEquals(8080, obj.getPort()); + Assertions.assertFalse(obj.isSslEnabled()); obj = new URIEndpointObject("http://127.0.2.0:8080?sslEnabled=true"); - Assert.assertEquals("127.0.2.0", obj.getHostOrIp()); - Assert.assertEquals(8080, obj.getPort()); - Assert.assertTrue(obj.isSslEnabled()); - Assert.assertNull(obj.getFirst("notExist")); + Assertions.assertEquals("127.0.2.0", obj.getHostOrIp()); + Assertions.assertEquals(8080, obj.getPort()); + Assertions.assertTrue(obj.isSslEnabled()); + Assertions.assertNull(obj.getFirst("notExist")); obj = new URIEndpointObject("http://127.0.2.0:8080?sslEnabled=true&protocol=http2"); - Assert.assertEquals("127.0.2.0", obj.getHostOrIp()); - Assert.assertEquals(8080, obj.getPort()); - Assert.assertTrue(obj.isSslEnabled()); - Assert.assertTrue(obj.isHttp2Enabled()); - Assert.assertNull(obj.getFirst("notExist")); + Assertions.assertEquals("127.0.2.0", obj.getHostOrIp()); + Assertions.assertEquals(8080, obj.getPort()); + Assertions.assertTrue(obj.isSslEnabled()); + Assertions.assertTrue(obj.isHttp2Enabled()); + Assertions.assertNull(obj.getFirst("notExist")); obj = new URIEndpointObject("rest://127.0.2.0:8080?urlPrefix=%2Froot"); - Assert.assertEquals("127.0.2.0", obj.getHostOrIp()); - Assert.assertEquals(8080, obj.getPort()); - Assert.assertEquals("/root", obj.getQuery("urlPrefix").get(0)); + Assertions.assertEquals("127.0.2.0", obj.getHostOrIp()); + Assertions.assertEquals(8080, obj.getPort()); + Assertions.assertEquals("/root", obj.getQuery("urlPrefix").get(0)); } - @Test(expected = IllegalArgumentException.class) + @Test public void testRestEndpointObjectException() { - new URIEndpointObject("http://127.0.2.0"); + Assertions.assertThrows(IllegalArgumentException.class, () -> new URIEndpointObject("http://127.0.2.0")); } @Test @@ -66,16 +65,16 @@ public void testQueryChineseAndSpaceAndEmpty() throws UnsupportedEncodingExcepti "cse://1.1.1.1:1234/abc?a=1&b=&country=" + URLEncoder.encode("中 国", StandardCharsets.UTF_8.name()); URIEndpointObject ep = new URIEndpointObject(strUri); - Map> querys = Deencapsulation.getField(ep, "querys"); - Assert.assertEquals(3, querys.size()); + Map> queries = Deencapsulation.getField(ep, "queries"); + Assertions.assertEquals(3, queries.size()); - Assert.assertEquals(1, ep.getQuery("a").size()); - Assert.assertEquals("1", ep.getFirst("a")); + Assertions.assertEquals(1, ep.getQuery("a").size()); + Assertions.assertEquals("1", ep.getFirst("a")); - Assert.assertEquals(1, ep.getQuery("b").size()); - Assert.assertEquals("", ep.getFirst("b")); + Assertions.assertEquals(1, ep.getQuery("b").size()); + Assertions.assertEquals("", ep.getFirst("b")); - Assert.assertEquals(1, ep.getQuery("country").size()); - Assert.assertEquals("中 国", ep.getFirst("country")); + Assertions.assertEquals(1, ep.getQuery("country").size()); + Assertions.assertEquals("中 国", ep.getFirst("country")); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestAbstractPart.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestAbstractPart.java index 3b4f82858e9..ae84a460e98 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestAbstractPart.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestAbstractPart.java @@ -19,57 +19,49 @@ import java.io.IOException; -import javax.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MediaType; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestAbstractPart { AbstractPart part = new AbstractPart(); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private void initExpectedException() { - expectedException.expect(Error.class); - expectedException.expectMessage(Matchers.is("not supported method")); + private void checkError(Error error) { + Assertions.assertEquals("not supported method", error.getMessage()); } @Test public void getInputStream() throws IOException { - initExpectedException(); - - part.getInputStream(); + Error error = Assertions.assertThrows(Error.class, () -> part.getInputStream()); + checkError(error); } @Test public void getContentType() throws IOException { - Assert.assertEquals(MediaType.APPLICATION_OCTET_STREAM, part.getContentType()); + Assertions.assertEquals(MediaType.APPLICATION_OCTET_STREAM, part.getContentType()); String contentType = "abc"; part.contentType(contentType); - Assert.assertEquals(contentType, part.getContentType()); + Assertions.assertEquals(contentType, part.getContentType()); } @Test public void getName() throws IOException { - Assert.assertNull(part.getName()); + Assertions.assertNull(part.getName()); String name = "abc"; part.name = name; - Assert.assertEquals(name, part.getName()); + Assertions.assertEquals(name, part.getName()); } @Test public void getSubmittedFileName() throws IOException { - Assert.assertNull(part.getSubmittedFileName()); + Assertions.assertNull(part.getSubmittedFileName()); String submittedFileName = "abc"; part.setSubmittedFileName(submittedFileName); - Assert.assertEquals(submittedFileName, part.getSubmittedFileName()); + Assertions.assertEquals(submittedFileName, part.getSubmittedFileName()); } @Test @@ -77,62 +69,56 @@ public void setSubmittedFileName_contentTypeNotNull() { part.contentType(MediaType.TEXT_PLAIN); part.setSubmittedFileName("a.zip"); - Assert.assertEquals(MediaType.TEXT_PLAIN, part.getContentType()); + Assertions.assertEquals(MediaType.TEXT_PLAIN, part.getContentType()); } @Test public void setSubmittedFileName_setNull() { part.setSubmittedFileName(null); - Assert.assertEquals(MediaType.APPLICATION_OCTET_STREAM, part.getContentType()); + Assertions.assertEquals(MediaType.APPLICATION_OCTET_STREAM, part.getContentType()); } @Test public void setSubmittedFileName_setNormal() { part.setSubmittedFileName("a.zip"); - Assert.assertEquals("application/zip", part.getContentType()); + Assertions.assertEquals("application/zip", part.getContentType()); } @Test public void getSize() { - initExpectedException(); - - part.getSize(); + Error error = Assertions.assertThrows(Error.class, () -> part.getSize()); + checkError(error); } @Test public void write() throws IOException { - initExpectedException(); - - part.write("file"); + Error error = Assertions.assertThrows(Error.class, () -> part.write("file")); + checkError(error); } @Test public void delete() throws IOException { - initExpectedException(); - - part.delete(); + Error error = Assertions.assertThrows(Error.class, () -> part.delete()); + checkError(error); } @Test public void getHeader() { - initExpectedException(); - - part.getHeader("header"); + Error error = Assertions.assertThrows(Error.class, () -> part.getHeader("header")); + checkError(error); } @Test public void getHeaders() { - initExpectedException(); - - part.getHeaders("header"); + Error error = Assertions.assertThrows(Error.class, () -> part.getHeaders("header")); + checkError(error); } @Test public void getHeaderNames() { - initExpectedException(); - - part.getHeaderNames(); + Error error = Assertions.assertThrows(Error.class, () -> part.getHeaderNames()); + checkError(error); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestFilePart.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestFilePart.java index c2e87417960..b129bc2ec42 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestFilePart.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestFilePart.java @@ -24,10 +24,10 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class TestFilePart { static File file = new File("testFilePart.txt"); @@ -38,32 +38,32 @@ public class TestFilePart { FilePart part = new FilePart(name, file.getAbsolutePath()); - @BeforeClass + @BeforeAll public static void setup() throws IOException { file.delete(); FileUtils.write(file, content, StandardCharsets.UTF_8); } - @AfterClass + @AfterAll public static void teardown() { file.delete(); } @Test public void getName() { - Assert.assertEquals(name, part.getName()); + Assertions.assertEquals(name, part.getName()); } @Test public void getInputStream() throws IOException { try (InputStream is = part.getInputStream()) { - Assert.assertEquals(content, IOUtils.toString(is, StandardCharsets.UTF_8)); + Assertions.assertEquals(content, IOUtils.toString(is, StandardCharsets.UTF_8)); } } @Test public void getSize() { - Assert.assertEquals(content.length(), part.getSize()); + Assertions.assertEquals(content.length(), part.getSize()); } @Test @@ -71,22 +71,22 @@ public void write() throws IOException { File destFile = new File("testFilePartCopy.txt"); part.write(destFile.getPath()); - Assert.assertEquals(content, FileUtils.readFileToString(destFile, StandardCharsets.UTF_8)); + Assertions.assertEquals(content, FileUtils.readFileToString(destFile, StandardCharsets.UTF_8)); FilePart destPart = new FilePart(null, destFile); destPart.delete(); - Assert.assertFalse(destFile.exists()); + Assertions.assertFalse(destFile.exists()); } @Test public void deleteAfterFinished() { - Assert.assertFalse(part.isDeleteAfterFinished()); + Assertions.assertFalse(part.isDeleteAfterFinished()); - Assert.assertTrue(part.setDeleteAfterFinished(true).isDeleteAfterFinished()); + Assertions.assertTrue(part.setDeleteAfterFinished(true).isDeleteAfterFinished()); } @Test public void getAbsolutePath() { - Assert.assertEquals(file.getAbsolutePath(), part.getAbsolutePath()); + Assertions.assertEquals(file.getAbsolutePath(), part.getAbsolutePath()); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestInputStreamPart.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestInputStreamPart.java index f7e9a970ec7..6af3016ecd3 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestInputStreamPart.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestInputStreamPart.java @@ -22,8 +22,8 @@ import java.io.InputStream; import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestInputStreamPart { String name = "paramName"; @@ -36,14 +36,14 @@ public class TestInputStreamPart { @Test public void getName() { - Assert.assertEquals(name, part.getName()); + Assertions.assertEquals(name, part.getName()); } @Test public void test() throws IOException { try (InputStream is = part.getInputStream()) { byte[] content = IOUtils.toByteArray(is); - Assert.assertArrayEquals(bytes, content); + Assertions.assertArrayEquals(bytes, content); } } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestResourcePart.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestResourcePart.java index 2608bba11a1..e0d398e697c 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestResourcePart.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/part/TestResourcePart.java @@ -21,8 +21,8 @@ import java.io.InputStream; import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; @@ -37,14 +37,14 @@ public class TestResourcePart { @Test public void getName() { - Assert.assertEquals(name, part.getName()); + Assertions.assertEquals(name, part.getName()); } @Test public void getInputStream() throws IOException { try (InputStream is = part.getInputStream()) { byte[] content = IOUtils.toByteArray(is); - Assert.assertArrayEquals(bytes, content); + Assertions.assertArrayEquals(bytes, content); } } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/spring/TestPaasNamespaceHandler.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/spring/TestPaasNamespaceHandler.java index 93729f031df..41d5c03640a 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/spring/TestPaasNamespaceHandler.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/spring/TestPaasNamespaceHandler.java @@ -17,21 +17,21 @@ package org.apache.servicecomb.foundation.common.spring; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class TestPaasNamespaceHandler { PaasNamespaceHandler paasNamespaceHandler = null; - @Before + @BeforeEach public void setUp() throws Exception { paasNamespaceHandler = new PaasNamespaceHandler(); } - @After + @AfterEach public void tearDown() throws Exception { paasNamespaceHandler = null; } @@ -44,6 +44,6 @@ public void testInit() { } catch (Exception e) { status = true; } - Assert.assertFalse(status); + Assertions.assertFalse(status); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/AsyncUtilsTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/AsyncUtilsTest.java index 8b38da0bc2a..7ec1a215034 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/AsyncUtilsTest.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/AsyncUtilsTest.java @@ -41,4 +41,4 @@ void should_convert_fail_async_to_sync() { Throwable catchThrowable = catchThrowable(() -> AsyncUtils.toSync(future)); assertThat(catchThrowable).isSameAs(throwable); } -} \ No newline at end of file +} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/JsonUtilsTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/JsonUtilsTest.java new file mode 100644 index 00000000000..60c5d9c43a0 --- /dev/null +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/JsonUtilsTest.java @@ -0,0 +1,45 @@ +/* + * 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.foundation.common.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.Map; + +public class JsonUtilsTest { + + @Test + void testWriteUnicodeValueAsString() throws JsonProcessingException { + String unicodeStr = "测试"; + Map inMap = new HashMap<>(); + inMap.put("key", unicodeStr); + + Assertions.assertFalse(StringUtils.isAsciiPrintable(JsonUtils.writeValueAsString(inMap))); + String jsonStr = JsonUtils.writeUnicodeValueAsString(inMap); + Assertions.assertTrue(StringUtils.isAsciiPrintable(jsonStr)); + + Map outMap = JsonUtils.OBJ_MAPPER.readValue(jsonStr, new TypeReference>() { + }); + Assertions.assertEquals(unicodeStr, outMap.get("key")); + } +} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/Log4jUtilsTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/Log4jUtilsTest.java deleted file mode 100644 index 0d1962f873a..00000000000 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/Log4jUtilsTest.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.foundation.common.utils; - -import static org.junit.Assert.fail; - -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import org.apache.log4j.PropertyConfigurator; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.common.config.impl.PropertiesLoader; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.springframework.core.io.Resource; - -import mockit.Deencapsulation; -import mockit.Mock; -import mockit.MockUp; - -public class Log4jUtilsTest { - - @Before - public void before() { - Deencapsulation.setField(Log4jUtils.class, "inited", false); - } - - @Test - public void init() { - Holder propertiesLoaded = new Holder<>(false); - Holder logConfigured = new Holder<>(false); - Holder mergedFileWritten = new Holder<>(false); - final Properties logProperties = new Properties(); - logProperties.setProperty("paas.logs.file", "cse.log"); - final ArrayList logResList = new ArrayList<>(); - new MockUp() { - @Mock - Properties load() { - propertiesLoaded.value = true; - return logProperties; - } - - @Mock - List getFoundResList() { - return logResList; - } - }; - new MockUp() { - @Mock - void configure(Properties properties) { - logConfigured.value = true; - Assert.assertSame(properties, logProperties); - } - }; - new MockUp() { - @Mock - void outputFile(List resList, Properties properties) { - mergedFileWritten.value = true; - Assert.assertSame(logResList, resList); - Assert.assertSame(logProperties, properties); - } - }; - - Assert.assertFalse(Deencapsulation.getField(Log4jUtils.class, "inited")); - try { - Log4jUtils.init(); - } catch (Exception e) { - fail(e.getMessage()); - } - Assert.assertTrue(Deencapsulation.getField(Log4jUtils.class, "inited")); - Assert.assertTrue(propertiesLoaded.value); - Assert.assertTrue(logConfigured.value); - Assert.assertTrue(mergedFileWritten.value); - } - - @Test - public void initOnMergedFileOutputDisabled() { - Holder propertiesLoaded = new Holder<>(false); - Holder logConfigured = new Holder<>(false); - Holder mergedFileWritten = new Holder<>(false); - final Properties logProperties = new Properties(); - logProperties.setProperty("log4j.logger.outputConfig.enabled", "false"); - final ArrayList logResList = new ArrayList<>(); - new MockUp() { - @Mock - Properties load() { - propertiesLoaded.value = true; - return logProperties; - } - }; - new MockUp() { - @Mock - void configure(Properties properties) { - logConfigured.value = true; - Assert.assertSame(properties, logProperties); - } - }; - new MockUp() { - @Mock - void outputFile(List resList, Properties properties) { - mergedFileWritten.value = true; - Assert.assertSame(logResList, resList); - Assert.assertSame(logProperties, properties); - } - }; - - Assert.assertFalse(Deencapsulation.getField(Log4jUtils.class, "inited")); - try { - Log4jUtils.init(); - } catch (Exception e) { - fail(e.getMessage()); - } - Assert.assertTrue(Deencapsulation.getField(Log4jUtils.class, "inited")); - Assert.assertTrue(propertiesLoaded.value); - Assert.assertTrue(logConfigured.value); - Assert.assertFalse(mergedFileWritten.value); - } -} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/ResourceUtilTest.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/ResourceUtilTest.java index f2a579bd14d..9982eca9252 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/ResourceUtilTest.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/ResourceUtilTest.java @@ -22,38 +22,26 @@ import java.net.URISyntaxException; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class ResourceUtilTest { - /** - * This case is coupled with the Spring dependency, but in order to check the ability to read resources inside the - * jar packs, this may be the simplest way. - */ - @Test - public void loadResources_in_jar() throws IOException, URISyntaxException { - List uris = ResourceUtil.findResources("META-INF", p -> p.toString().endsWith("spring.factories")); - Assert.assertEquals(1, uris.size()); - Assert.assertTrue(uris.get(0).toString().startsWith("jar:file:")); - Assert.assertTrue(uris.get(0).toString().endsWith("!/META-INF/spring.factories")); - } - @Test public void loadResources_in_disk() throws IOException, URISyntaxException { List uris = ResourceUtil.findResourcesBySuffix("META-INF/spring", ".xml"); - Assert.assertEquals(1, uris.size()); + Assertions.assertEquals(1, uris.size()); URI uri = uris.get(0); - Assert.assertTrue("unexpected uri: " + uri, uri.toString().startsWith("file:")); - Assert.assertTrue("unexpected uri: " + uri, uri.toString().endsWith("META-INF/spring/config.bean.xml")); + Assertions.assertTrue(uri.toString().startsWith("file:"), "unexpected uri: " + uri); + Assertions.assertTrue(uri.toString().endsWith("META-INF/spring/config.bean.xml"), "unexpected uri: " + uri); } @Test public void loadResources_exact_file_in_disk() throws IOException, URISyntaxException { List uris = ResourceUtil.findResources("META-INF/spring/config.bean.xml"); - Assert.assertEquals(1, uris.size()); + Assertions.assertEquals(1, uris.size()); URI uri = uris.get(0); - Assert.assertTrue("unexpected uri: " + uri, uri.toString().startsWith("file:")); - Assert.assertTrue("unexpected uri: " + uri, uri.toString().endsWith("META-INF/spring/config.bean.xml")); + Assertions.assertTrue(uri.toString().startsWith("file:"), "unexpected uri: " + uri); + Assertions.assertTrue(uri.toString().endsWith("META-INF/spring/config.bean.xml"), "unexpected uri: " + uri); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java deleted file mode 100644 index 826ac2289bc..00000000000 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestBeanUtils.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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.foundation.common.utils; - -import java.math.BigDecimal; - -import org.aspectj.lang.annotation.Aspect; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; -import org.springframework.aop.SpringProxy; -import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -import mockit.Expectations; -import mockit.Mocked; - -public class TestBeanUtils { - static interface Intf { - - } - - static class Impl implements Intf { - - } - - // 被代理的类 - static class TestBean{ - - } - - // 模拟 CgLib 代理产生的子类 - static class TestBean$$TestBeanByCGLIB$$e1a36bab extends TestBean implements SpringProxy { - - } - - @Aspect - static class MyAspect { - } - - @BeforeClass - public static void setup() { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - } - - @AfterClass - public static void tearDown() { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - } - - @Test - public void test() { - Intf target = new Impl(); - AspectJProxyFactory factory = new AspectJProxyFactory(target); - MyAspect aspect = new MyAspect(); - factory.addAspect(aspect); - Intf proxy = factory.getProxy(); - - Assert.assertEquals(Impl.class, BeanUtils.getImplClassFromBean(proxy)); - Assert.assertEquals(Impl.class, BeanUtils.getImplClassFromBean(new Impl())); - } - - @Test - public void prepareServiceCombScanPackage_noExist_noMain() { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - new Expectations(JvmUtils.class) { - { - JvmUtils.findMainClass(); - result = null; - JvmUtils.findMainClassByStackTrace(); - result = null; - } - }; - - BeanUtils.prepareServiceCombScanPackage(); - - Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); - } - - @Test - public void prepareServiceCombScanPackage_noExist_scbMain() { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - new Expectations(JvmUtils.class) { - { - JvmUtils.findMainClass(); - result = TestBeanUtils.class; - JvmUtils.findMainClassByStackTrace(); - result = TestBeanUtils.class; - } - }; - - BeanUtils.prepareServiceCombScanPackage(); - - Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); - } - - @Test - public void prepareServiceCombScanPackage_noExist_otherMain() { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - new Expectations(JvmUtils.class) { - { - JvmUtils.findMainClass(); - result = String.class; - JvmUtils.findMainClassByStackTrace(); - result = BigDecimal.class; - } - }; - - BeanUtils.prepareServiceCombScanPackage(); - - Assert.assertEquals("org.apache.servicecomb,java.lang,java.math", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); - } - - @Test - public void prepareServiceCombScanPackage_exist() { - System.setProperty(BeanUtils.SCB_SCAN_PACKAGE, "a.b,,c.d"); - new Expectations(JvmUtils.class) { - { - JvmUtils.findMainClass(); - result = null; - JvmUtils.findMainClassByStackTrace(); - result = null; - } - }; - - BeanUtils.prepareServiceCombScanPackage(); - - Assert.assertEquals("a.b,c.d,org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); - } - - @Test - public void init(@Mocked ClassPathXmlApplicationContext context) { - System.clearProperty(BeanUtils.SCB_SCAN_PACKAGE); - new Expectations(JvmUtils.class) { - { - JvmUtils.findMainClass(); - result = TestBeanUtils.class; - JvmUtils.findMainClassByStackTrace(); - result = TestBeanUtils.class; - } - }; - BeanUtils.init(); - - Assert.assertEquals("org.apache.servicecomb", System.getProperty(BeanUtils.SCB_SCAN_PACKAGE)); - } - - @Test - public void testGetImplClassFromBeanFromCglib(){ - TestBean testBeanByCGLIB = new TestBean$$TestBeanByCGLIB$$e1a36bab(); - Class generatedClass = BeanUtils.getImplClassFromBean(testBeanByCGLIB); - Assert.assertNotNull(generatedClass); - Assert.assertEquals(TestBean.class, generatedClass); - } - - -} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestExceptionUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestExceptionUtils.java index 1d075444b17..a9746b078e6 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestExceptionUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestExceptionUtils.java @@ -19,16 +19,16 @@ import java.io.IOException; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestExceptionUtils { @Test public void testExceptionUtils() { Exception e = new Exception("Hello"); - Assert.assertEquals("cause:Exception,message:Hello", ExceptionUtils.getExceptionMessageWithoutTrace(e)); + Assertions.assertEquals("cause:Exception,message:Hello", ExceptionUtils.getExceptionMessageWithoutTrace(e)); Exception e2 = new Exception("FAIL", new IOException("IO")); - Assert.assertEquals("cause:Exception,message:FAIL;cause:IOException,message:IO", + Assertions.assertEquals("cause:Exception,message:FAIL;cause:IOException,message:IO", ExceptionUtils.getExceptionMessageWithoutTrace(e2)); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFileNameTooLong.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFileNameTooLong.java index bf13d88087e..0ccf049ffba 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFileNameTooLong.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFileNameTooLong.java @@ -22,8 +22,8 @@ import java.util.LinkedList; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,29 +41,29 @@ public void assertFileNotTooLong() { LOGGER.error(folder.getAbsolutePath()); // $ROOT\foundations\foundation-common File root = new File(folder.getParentFile().getParent()); LOGGER.error(root.getAbsolutePath()); // $ROOT\foundations\foundation-common - Assert.assertTrue(root.exists()); - Assert.assertTrue(root.isDirectory()); + Assertions.assertTrue(root.exists()); + Assertions.assertTrue(root.isDirectory()); List names = new LinkedList<>(); findLongFileName(root, names, root.getAbsolutePath().length()); Collections.sort(names); - names.forEach(e -> LOGGER.error(e)); + names.forEach(LOGGER::error); if (!names.isEmpty()) { // for debug - Assert.assertEquals("", names.toString()); + Assertions.assertEquals("", names.toString()); } - Assert.assertTrue(names.isEmpty()); + Assertions.assertTrue(names.isEmpty()); } - private static void findLongFileName(File folder, List holder, int baseLenght) { + private static void findLongFileName(File folder, List holder, int baseLength) { if (folder.isFile()) { - if (folder.getAbsolutePath().length() >= MAN_FILE_SIZE + baseLenght) { + if (folder.getAbsolutePath().length() >= MAN_FILE_SIZE + baseLength) { holder.add(folder.getAbsolutePath()); } } else if (folder.isDirectory() && !"target".equals(folder.getName())) { File[] children = folder.listFiles(); for (File child : children) { - findLongFileName(child, holder, baseLenght); + findLongFileName(child, holder, baseLength); } } else { return; diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFortifyUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFortifyUtils.java index 03b568b4086..5ca8147e146 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFortifyUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestFortifyUtils.java @@ -17,26 +17,23 @@ package org.apache.servicecomb.foundation.common.utils; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - import java.io.IOException; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestFortifyUtils { @Test public void testFortifyUtils() throws IOException { - Assert.assertEquals("", FortifyUtils.getErrorMsg(null)); - Assert.assertEquals("", FortifyUtils.getErrorStack(null)); + Assertions.assertEquals("", FortifyUtils.getErrorMsg(null)); + Assertions.assertEquals("", FortifyUtils.getErrorStack(null)); } @Test public void testFilePerm() { - Assert.assertEquals(10, (FilePerm.getDefaultAclPerm().size())); - Assert.assertEquals(3, (FilePerm.getDefaultPosixPerm().size())); - Assert.assertEquals(4, (FilePerm.getPosixPerm(400).size())); + Assertions.assertEquals(10, (FilePerm.getDefaultAclPerm().size())); + Assertions.assertEquals(3, (FilePerm.getDefaultPosixPerm().size())); + Assertions.assertEquals(4, (FilePerm.getPosixPerm(400).size())); } @Test @@ -46,7 +43,7 @@ public void testGetErrorMsg() { FortifyUtils.getErrorMsg(e); - assertNull(FortifyUtils.getErrorMsg(e)); + Assertions.assertNull(FortifyUtils.getErrorMsg(e)); } @Test @@ -54,10 +51,10 @@ public void testGetSecurityXmlDocumentFactory() { try { FortifyUtils.getSecurityXmlDocumentFactory(); - assertNotNull(FortifyUtils.getSecurityXmlDocumentFactory()); + Assertions.assertNotNull(FortifyUtils.getSecurityXmlDocumentFactory()); } catch (Exception e) { /* Do not Worry */ - Assert.assertTrue(false); + Assertions.fail(); } } @@ -66,7 +63,7 @@ public void testGetErrorStack() { Throwable e = new Throwable(); FortifyUtils.getErrorStack(e); - Assert.assertNotEquals(true, FortifyUtils.getErrorStack(e)); + Assertions.assertNotEquals(true, FortifyUtils.getErrorStack(e)); } @Test @@ -74,6 +71,5 @@ public void testGetErrorInfo() { Throwable e = new Throwable(); FortifyUtils.getErrorInfo(e, true); - Assert.assertNotEquals(true, FortifyUtils.getErrorInfo(e, true)); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestGenericsUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestGenericsUtils.java index d54320afbec..06de9612dd2 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestGenericsUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestGenericsUtils.java @@ -20,22 +20,22 @@ import java.util.List; import java.util.Map; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.springframework.core.ParameterizedTypeReference; public class TestGenericsUtils { @Test public void testIsGenerics() { - Assert.assertTrue(GenericsUtils.isGenericResponseType(List.class)); - Assert.assertTrue(GenericsUtils.isGenericResponseType(Map.class)); - Assert.assertTrue(GenericsUtils.isGenericResponseType(Person.class)); + Assertions.assertTrue(GenericsUtils.isGenericResponseType(List.class)); + Assertions.assertTrue(GenericsUtils.isGenericResponseType(Map.class)); + Assertions.assertTrue(GenericsUtils.isGenericResponseType(Person.class)); - Assert.assertFalse(GenericsUtils.isGenericResponseType(Man.class)); - Assert.assertFalse(GenericsUtils.isGenericResponseType(String.class)); - Assert.assertFalse(GenericsUtils.isGenericResponseType(GenericsUtils.class)); + Assertions.assertFalse(GenericsUtils.isGenericResponseType(Man.class)); + Assertions.assertFalse(GenericsUtils.isGenericResponseType(String.class)); + Assertions.assertFalse(GenericsUtils.isGenericResponseType(GenericsUtils.class)); - Assert.assertFalse(GenericsUtils.isGenericResponseType(new ParameterizedTypeReference>() { + Assertions.assertFalse(GenericsUtils.isGenericResponseType(new ParameterizedTypeReference>() { }.getType())); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestIOUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestIOUtils.java index fe4f0e4dc87..42c7abe5d4a 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestIOUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestIOUtils.java @@ -17,29 +17,28 @@ package org.apache.servicecomb.foundation.common.utils; -import static org.junit.Assert.assertEquals; - -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestIOUtils { @Test public void testAnonymousPath() { - assertEquals(":/:/r/2/y/b/y/0/s/microservice.yaml", + Assertions.assertEquals(":/:/r/2/y/b/y/0/s/microservice.yaml", IOUtils.anonymousPath("jar:file:/D:/User/.m2/repository/servicecomb" + "/transport-highway/2.3.0/classes/microservice.yaml")); - assertEquals(":/:/r/microservice.yaml", IOUtils.anonymousPath("file:/D:/User/microservice.yaml")); + Assertions.assertEquals(":/:/r/microservice.yaml", IOUtils.anonymousPath("file:/D:/User/microservice.yaml")); - assertEquals(":\\:\\r\\microservice.yaml", IOUtils.anonymousPath("file:\\D:\\User\\microservice.yaml")); + Assertions.assertEquals(":\\:\\r\\microservice.yaml", IOUtils.anonymousPath("file:\\D:\\User\\microservice.yaml")); - assertEquals("r\\t\\a.txt", IOUtils.anonymousPath("user\\test\\a.txt")); + Assertions.assertEquals("r\\t\\a.txt", IOUtils.anonymousPath("user\\test\\a.txt")); - assertEquals(":\\:\\a.txt", IOUtils.anonymousPath("file:\\D:\\a.txt")); + Assertions.assertEquals(":\\:\\a.txt", IOUtils.anonymousPath("file:\\D:\\a.txt")); - assertEquals(":\\a.txt", IOUtils.anonymousPath("D:\\a.txt")); + Assertions.assertEquals(":\\a.txt", IOUtils.anonymousPath("D:\\a.txt")); - assertEquals("a.txt", IOUtils.anonymousPath("a.txt")); + Assertions.assertEquals("a.txt", IOUtils.anonymousPath("a.txt")); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java index 890ea21dacb..10054efe4e8 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestJvmUtils.java @@ -16,181 +16,191 @@ */ package org.apache.servicecomb.foundation.common.utils; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.InputStream; -import java.net.URL; -import java.util.jar.JarFile; - +import mockit.Mock; +import mockit.MockUp; import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.powermock.api.mockito.PowerMockito; -import org.powermock.core.classloader.annotations.PrepareForTest; -import org.powermock.modules.junit4.PowerMockRunner; - - -@RunWith(PowerMockRunner.class) -@PrepareForTest({JvmUtils.class}) -public class TestJvmUtils { - static String orgCmd = System.getProperty(JvmUtils.SUN_JAVA_COMMAND); +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnJre; +import org.junit.jupiter.api.condition.JRE; - @Before - public void setup() { - System.clearProperty(JvmUtils.SUN_JAVA_COMMAND); - } +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.net.URL; - @AfterClass - public static void tearDown() { - if (orgCmd == null) { - System.clearProperty(JvmUtils.SUN_JAVA_COMMAND); - return; - } - System.setProperty(JvmUtils.SUN_JAVA_COMMAND, orgCmd); - } +public class TestJvmUtils { @Test + @Disabled public void findMainClass_notExist() { - Assert.assertNull(JvmUtils.findMainClass()); + System.clearProperty(JvmUtils.SUN_JAVA_COMMAND); + Assertions.assertNull(JvmUtils.findMainClass()); } @Test + @Disabled public void findMainClass_existButEmpty() { System.setProperty(JvmUtils.SUN_JAVA_COMMAND, ""); - Assert.assertNull(JvmUtils.findMainClass()); + Assertions.assertNull(JvmUtils.findMainClass()); } @Test + @Disabled public void findMainClass_invalid() { LogCollector logCollector = new LogCollector(); System.setProperty(JvmUtils.SUN_JAVA_COMMAND, "invalidCls"); - Assert.assertNull(JvmUtils.findMainClass()); - Assert.assertEquals("\"invalidCls\" is not a valid class.", logCollector.getEvents().get(0).getMessage()); - logCollector.teardown(); + Assertions.assertNull(JvmUtils.findMainClass()); + Assertions.assertEquals("\"invalidCls\" is not a valid class.", logCollector.getEvents().get(0).getMessage()); + logCollector.tearDown(); } @Test + @Disabled public void findMainClass_class_normal() { System.setProperty(JvmUtils.SUN_JAVA_COMMAND, TestJvmUtils.class.getName() + " arg"); - Assert.assertEquals(TestJvmUtils.class, JvmUtils.findMainClass()); + Assertions.assertEquals(TestJvmUtils.class, JvmUtils.findMainClass()); } @Test + @Disabled public void findMainClass_jar_normal() throws Exception { - - URL url = PowerMockito.mock(URL.class); - String command = "a.jar"; - String manifestUri = "jar:file:" + new File(command).getAbsolutePath() + "!/" + JarFile.MANIFEST_NAME; - PowerMockito.whenNew(URL.class).withParameterTypes(String.class) - .withArguments(manifestUri).thenReturn(url); String content = String.format("Manifest-Version: 1.0\nMain-Class: %s\n", TestJvmUtils.class.getName()); InputStream inputStream = new ByteArrayInputStream(content.getBytes()); - PowerMockito.when(url.openStream()).thenReturn(inputStream); + new MockUp() { + @Mock + InputStream openStream() throws Exception { + return inputStream; + } + }; System.setProperty(JvmUtils.SUN_JAVA_COMMAND, command + " arg"); - Assert.assertEquals(TestJvmUtils.class, JvmUtils.findMainClass()); + Assertions.assertEquals(TestJvmUtils.class, JvmUtils.findMainClass()); } @Test + @Disabled public void findMainClass_jar_null() throws Exception { String content = "Manifest-Version: 1.0\n"; InputStream inputStream = new ByteArrayInputStream(content.getBytes()); - URL url = PowerMockito.mock(URL.class); - String command = "a.jar"; - String manifestUri = "jar:file:/" + new File(command).getAbsolutePath() + "!/" + JarFile.MANIFEST_NAME; - PowerMockito.whenNew(URL.class).withParameterTypes(String.class) - .withArguments(manifestUri).thenReturn(url); - PowerMockito.when(url.openStream()).thenReturn(inputStream); + new MockUp() { + @Mock + InputStream openStream() throws Exception { + return inputStream; + } + }; System.setProperty(JvmUtils.SUN_JAVA_COMMAND, command + " arg"); - Assert.assertNull(JvmUtils.findMainClass()); + Assertions.assertNull(JvmUtils.findMainClass()); } @Test + @Disabled + @EnabledOnJre(JRE.JAVA_17) public void findMainClass_jar_readFailed() throws Exception { - URL url = PowerMockito.mock(URL.class); String command = "a.jar"; - String manifestUri = "jar:file:" + new File(command).getAbsolutePath() + "!/" + JarFile.MANIFEST_NAME; - - PowerMockito.whenNew(URL.class).withParameterTypes(String.class) - .withArguments(manifestUri).thenReturn(url); - PowerMockito.when(url.openStream()).thenThrow(new RuntimeExceptionWithoutStackTrace()); + new MockUp() { + @Mock + InputStream openStream() throws Exception { + throw new RuntimeExceptionWithoutStackTrace(); + } + }; System.setProperty(JvmUtils.SUN_JAVA_COMMAND, command + " arg"); - Assert.assertNull(JvmUtils.findMainClass()); + Assertions.assertNull(JvmUtils.findMainClass()); } @Test + @Disabled public void findMainClassByStackTrace_normal() throws Exception{ - RuntimeException re = PowerMockito.mock(RuntimeException.class); - PowerMockito.when(re.getStackTrace()).thenReturn(new StackTraceElement[]{ - new StackTraceElement("declaring.class.fileName", "methodName", "fileName", 100), - new StackTraceElement("java.lang.String", "main", "fileName", 120) - }); - PowerMockito.whenNew(RuntimeException.class).withNoArguments().thenReturn(re); - - Assert.assertEquals(String.class, JvmUtils.findMainClassByStackTrace()); + StackTraceElement[] stackTraceElements = { + new StackTraceElement("declaring.class.fileName", "methodName", "fileName", 100), + new StackTraceElement("java.lang.String", "main", "fileName", 120) + }; + new MockUp() { + @Mock + public StackTraceElement[] getStackTrace() { + return stackTraceElements; + } + }; + + Assertions.assertEquals(String.class, JvmUtils.findMainClassByStackTrace()); } @Test + @Disabled public void findMainClassByStackTrace_invalidClass() throws Exception{ - RuntimeException re = PowerMockito.mock(RuntimeException.class); - PowerMockito.when(re.getStackTrace()).thenReturn(new StackTraceElement[]{ - new StackTraceElement("declaring.class.fileName", "methodName", "fileName", 100), - new StackTraceElement("InvalidClass", "main", "fileName", 120) - }); - PowerMockito.whenNew(RuntimeException.class).withNoArguments().thenReturn(re); - - Assert.assertNull(JvmUtils.findMainClassByStackTrace()); + StackTraceElement[] stackTraceElements = { + new StackTraceElement("declaring.class.fileName", "methodName", "fileName", 100), + new StackTraceElement("InvalidClass", "main", "fileName", 120) + }; + new MockUp() { + @Mock + public StackTraceElement[] getStackTrace() { + return stackTraceElements; + } + }; + + Assertions.assertNull(JvmUtils.findMainClassByStackTrace()); } @Test + @Disabled public void findMainClassByStackTrace_withoutMainMethod() throws Exception{ - RuntimeException re = PowerMockito.mock(RuntimeException.class); - PowerMockito.when(re.getStackTrace()).thenReturn(new StackTraceElement[]{ - new StackTraceElement("declaring.class.fileName", "methodName", "fileName", 100), - new StackTraceElement("InvalidClass", "methodName", "fileName", 120) - }); - PowerMockito.whenNew(RuntimeException.class).withNoArguments().thenReturn(re); - - Assert.assertNull(JvmUtils.findMainClassByStackTrace()); + StackTraceElement[] stackTraceElements = { + new StackTraceElement("declaring.class.fileName", "methodName", "fileName", 100), + new StackTraceElement("InvalidClass", "methodName", "fileName", 120) + }; + new MockUp() { + @Mock + public StackTraceElement[] getStackTrace() { + return stackTraceElements; + } + }; + + Assertions.assertNull(JvmUtils.findMainClassByStackTrace()); } @Test + @Disabled public void findMainClassByStackTrace_emptyStackTrace() throws Exception{ - RuntimeException re = PowerMockito.mock(RuntimeException.class); - PowerMockito.when(re.getStackTrace()).thenReturn(new StackTraceElement[]{}); - PowerMockito.whenNew(RuntimeException.class).withNoArguments().thenReturn(re); - - Assert.assertNull(JvmUtils.findMainClassByStackTrace()); + new MockUp() { + @Mock + public StackTraceElement[] getStackTrace() { + return new StackTraceElement[]{}; + } + }; + + Assertions.assertNull(JvmUtils.findMainClassByStackTrace()); } @Test + @Disabled public void findMainClassByStackTrace_nullStackTrace() throws Exception{ - RuntimeException re = PowerMockito.mock(RuntimeException.class); - PowerMockito.when(re.getStackTrace()).thenReturn(null); - PowerMockito.whenNew(RuntimeException.class).withNoArguments().thenReturn(re); - - Assert.assertNull(JvmUtils.findMainClassByStackTrace()); + new MockUp() { + @Mock + public StackTraceElement[] getStackTrace() { + return null; + } + }; + + Assertions.assertNull(JvmUtils.findMainClassByStackTrace()); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestLambdaMetafactoryUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestLambdaMetafactoryUtils.java index 014e9561d78..39647ba3dcf 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestLambdaMetafactoryUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestLambdaMetafactoryUtils.java @@ -33,14 +33,18 @@ import org.apache.servicecomb.foundation.common.utils.bean.IntGetter; import org.apache.servicecomb.foundation.common.utils.bean.IntSetter; import org.apache.servicecomb.foundation.common.utils.bean.Setter; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; import com.fasterxml.jackson.databind.BeanDescription; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnJre; +import org.junit.jupiter.api.condition.JRE; +@EnabledOnJre(JRE.JAVA_8) public class TestLambdaMetafactoryUtils { public static class Model { public int f1; @@ -79,8 +83,8 @@ public void createLambda_withInstance() throws Throwable { setter.accept(1); int f1 = (int) getter.get(); - Assert.assertEquals(1, f1); - Assert.assertThat((List) echo.apply(Arrays.asList(2)), Matchers.contains(2)); + Assertions.assertEquals(1, f1); + MatcherAssert.assertThat((List) echo.apply(Arrays.asList(2)), Matchers.contains(2)); } @SuppressWarnings("unchecked") @@ -95,12 +99,12 @@ public void createGetterSetterByMethod() throws Throwable { setter.set(model, 1); int f1 = getter.get(model); - Assert.assertEquals(1, f1); - Assert.assertThat((List) echo.apply(model, Arrays.asList(2)), Matchers.contains(2)); + Assertions.assertEquals(1, f1); + MatcherAssert.assertThat((List) echo.apply(model, Arrays.asList(2)), Matchers.contains(2)); fluentSetter.set(model, 2); int ff1 = getter.get(model); - Assert.assertEquals(2, ff1); + Assertions.assertEquals(2, ff1); } @Test diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestMimeTypesUtils.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestMimeTypesUtils.java index 2b5efe27f18..55d88f6ef96 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestMimeTypesUtils.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestMimeTypesUtils.java @@ -17,82 +17,80 @@ package org.apache.servicecomb.foundation.common.utils; -import static org.junit.Assert.assertEquals; - import java.util.Collections; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestMimeTypesUtils { @Test public void testSortedAcceptableMimeTypes1() { String accept = "text/html"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(1, types.size()); - assertEquals("text/html", types.get(0)); + Assertions.assertEquals(1, types.size()); + Assertions.assertEquals("text/html", types.get(0)); } @Test public void testSortedAcceptableMimeTypes2() { String accept = "text/html, application/json"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(2, types.size()); - assertEquals("text/html", types.get(0)); - assertEquals("application/json", types.get(1)); + Assertions.assertEquals(2, types.size()); + Assertions.assertEquals("text/html", types.get(0)); + Assertions.assertEquals("application/json", types.get(1)); } @Test public void testSortedAcceptableMimeTypes3() { String accept = "text/html,application/json"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(2, types.size()); - assertEquals("text/html", types.get(0)); - assertEquals("application/json", types.get(1)); + Assertions.assertEquals(2, types.size()); + Assertions.assertEquals("text/html", types.get(0)); + Assertions.assertEquals("application/json", types.get(1)); } @Test public void testSortedAcceptableMimeTypes4() { String accept = "text/html; q=0.8,application/json; q=0.9"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(2, types.size()); - assertEquals("application/json", types.get(0)); - assertEquals("text/html", types.get(1)); + Assertions.assertEquals(2, types.size()); + Assertions.assertEquals("application/json", types.get(0)); + Assertions.assertEquals("text/html", types.get(1)); } @Test public void testSortedAcceptableMimeTypes5() { String accept = "text/html;q=0.8,application/json;q=0.9"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(2, types.size()); - assertEquals("application/json", types.get(0)); - assertEquals("text/html", types.get(1)); + Assertions.assertEquals(2, types.size()); + Assertions.assertEquals("application/json", types.get(0)); + Assertions.assertEquals("text/html", types.get(1)); } @Test public void testSortedAcceptableMimeTypes6() { String accept = "text/html; q=0.8,application/json; q=0.9, text/plain"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(3, types.size()); - assertEquals("text/plain", types.get(0)); - assertEquals("application/json", types.get(1)); - assertEquals("text/html", types.get(2)); + Assertions.assertEquals(3, types.size()); + Assertions.assertEquals("text/plain", types.get(0)); + Assertions.assertEquals("application/json", types.get(1)); + Assertions.assertEquals("text/html", types.get(2)); } @Test public void testSortedAcceptableMimeTypes7() { String accept = "text/html;q=0.8,application/json;q=0.9,text/plain"; List types = MimeTypesUtils.getSortedAcceptableMimeTypes(accept); - assertEquals(3, types.size()); - assertEquals("text/plain", types.get(0)); - assertEquals("application/json", types.get(1)); - assertEquals("text/html", types.get(2)); + Assertions.assertEquals(3, types.size()); + Assertions.assertEquals("text/plain", types.get(0)); + Assertions.assertEquals("application/json", types.get(1)); + Assertions.assertEquals("text/html", types.get(2)); } @Test public void getSortedAcceptableMimeTypesNull() { List types = MimeTypesUtils.getSortedAcceptableMimeTypes(null); - Assert.assertSame(Collections.emptyList(), types); + Assertions.assertSame(Collections.emptyList(), types); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRSAUtil.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRSAUtil.java index 2d43ff9d729..6bd9b386e36 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRSAUtil.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRSAUtil.java @@ -21,22 +21,37 @@ import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestRSAUtil { + @BeforeAll + public static void setUpClass() { + Environment environment = Mockito.mock(Environment.class); + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keyGeneratorAlgorithm", "RSA")) + .thenReturn("RSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.signAlgorithm", "SHA256withRSA")) + .thenReturn("SHA256withRSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keySize", int.class, 2048)) + .thenReturn(2048); + } @Test public void testSignVerify() throws InvalidKeyException, NoSuchAlgorithmException, InvalidKeySpecException, SignatureException { - RSAKeyPairEntry rsaKeyPairEntry = RSAUtils.generateRSAKeyPair(); + KeyPairEntry keyPairEntry = KeyPairUtils.generateALGKeyPair(); - Assert.assertNotNull(rsaKeyPairEntry.getPublicKeyEncoded()); - Assert.assertNotNull(rsaKeyPairEntry.getPrivateKey()); - Assert.assertNotNull(rsaKeyPairEntry.getPublicKey()); + Assertions.assertNotNull(keyPairEntry.getPublicKeyEncoded()); + Assertions.assertNotNull(keyPairEntry.getPrivateKey()); + Assertions.assertNotNull(keyPairEntry.getPublicKey()); String testContent = "instance-id@201711201930@randomstr"; - String signstr = RSAUtils.sign(testContent, rsaKeyPairEntry.getPrivateKey()); - Assert.assertTrue(RSAUtils.verify(rsaKeyPairEntry.getPublicKeyEncoded(), signstr, testContent)); + String signstr = KeyPairUtils.sign(testContent, keyPairEntry.getPrivateKey()); + Assertions.assertTrue(KeyPairUtils.verify(keyPairEntry.getPublicKeyEncoded(), signstr, testContent)); } @Test @@ -48,6 +63,6 @@ public void testSignVerify2() "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ"; String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxKl5TNUTec7fL2degQcCk6vKf3c0wsfNK5V6elKzjWxm0MwbRj/UeR20VSnicBmVIOWrBS9LiERPPvjmmWUOSS2vxwr5XfhBhZ07gCAUNxBOTzgMo5nE45DhhZu5Jzt5qSV6o10Kq7+fCCBlDZ1UoWxZceHkUt5AxcrhEDulFjQIDAQAB"; - Assert.assertTrue(RSAUtils.verify(pubKey, sign, content)); + Assertions.assertTrue(KeyPairUtils.verify(pubKey, sign, content)); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRollingFileAppenderExt.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRollingFileAppenderExt.java deleted file mode 100644 index e7fe419b2fa..00000000000 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestRollingFileAppenderExt.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.foundation.common.utils; - -import java.io.File; - -import org.apache.log4j.Layout; -import org.apache.log4j.spi.LoggingEvent; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Injectable; - -public class TestRollingFileAppenderExt { - @Test - public void testRollingFileAppenderExt(@Injectable LoggingEvent event, - @Injectable Layout layout) throws Exception { - new Expectations() { - { - layout.format(event); - result = "test"; - } - }; - File cur = new File(System.getProperty("user.dir")); - File temp = new File(cur, "temptestfile.log"); - if (temp.exists()) { - temp.delete(); - } - RollingFileAppenderExt ext = new RollingFileAppenderExt(); - ext.setLayout(layout); - ext.setLogPermission("rw-------"); - ext.setFile(temp.getAbsolutePath()); - ext.setFile(temp.getAbsolutePath(), false, false, 300000); - Assert.assertEquals(ext.getLogPermission(), "rw-------"); - Assert.assertTrue(temp.exists()); - - temp.delete(); - ext.subAppend(event); - Assert.assertTrue(temp.exists()); - - ext.close(); - temp.delete(); - Assert.assertFalse(temp.exists()); - } -} diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java index c2fe52c58be..487ad288585 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/utils/TestTypesUtil.java @@ -16,17 +16,17 @@ */ package org.apache.servicecomb.foundation.common.utils; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestTypesUtil { @Test public void testTypesUtil() { - Assert.assertEquals(double.class, TypesUtil.wrapperTypeToPrimitive(Double.class)); - Assert.assertEquals(Float.class, TypesUtil.primitiveTypeToWrapper(float.class)); - Assert + Assertions.assertEquals(double.class, TypesUtil.wrapperTypeToPrimitive(Double.class)); + Assertions.assertEquals(Float.class, TypesUtil.primitiveTypeToWrapper(float.class)); + Assertions .assertEquals(TypesUtil.PRIMITIVE_CHAR, TypesUtil.wrapperJavaTypeToPrimitive(TypesUtil.PRIMITIVE_WRAPPER_CHAR)); - Assert + Assertions .assertEquals(TypesUtil.PRIMITIVE_WRAPPER_BYTE, TypesUtil.primitiveJavaTypeToWrapper(TypesUtil.PRIMITIVE_BYTE)); } } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/logback/TestMarkerFilter.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/logback/TestMarkerFilter.java deleted file mode 100644 index eb48d1b7402..00000000000 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/logback/TestMarkerFilter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.foundation.logback; - -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; -import org.slf4j.Marker; - -import ch.qos.logback.classic.spi.ILoggingEvent; -import ch.qos.logback.core.spi.FilterReply; - -public class TestMarkerFilter { - @Test - public void testMarkerFilter() { - MarkerFilter filter = new MarkerFilter(); - filter.setMarker("hello"); - filter.start(); - Assert.assertEquals(filter.getOnMatch(), FilterReply.ACCEPT); - Assert.assertEquals(filter.getOnMismatch(), FilterReply.DENY); - - ILoggingEvent event = Mockito.mock(ILoggingEvent.class); - Marker marker = Mockito.mock(Marker.class); - Mockito.when(event.getMarker()).thenReturn(marker); - Mockito.when(marker.getName()).thenReturn("hello"); - Assert.assertEquals(FilterReply.ACCEPT, filter.decide(event)); - - Mockito.when(event.getMarker()).thenReturn(null); - Assert.assertEquals(FilterReply.DENY, filter.decide(event)); - } -} diff --git a/foundations/foundation-common/src/test/resources/config/log4j.common.test.properties b/foundations/foundation-common/src/test/resources/config/log4j.common.test.properties deleted file mode 100644 index 0f636e4bacf..00000000000 --- a/foundations/foundation-common/src/test/resources/config/log4j.common.test.properties +++ /dev/null @@ -1,22 +0,0 @@ -# -# 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. -# - -# Override the log setting -paas.logs.dir=./target/logs -paas.logs.file=cse.log - -log4j.rootLogger=INFO,paas,stdout diff --git a/foundations/foundation-common/src/test/resources/log4j.properties b/foundations/foundation-common/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/foundations/foundation-common/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/foundations/foundation-common/src/test/resources/log4j2.xml b/foundations/foundation-common/src/test/resources/log4j2.xml new file mode 100644 index 00000000000..8cee07220ec --- /dev/null +++ b/foundations/foundation-common/src/test/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/foundations/foundation-config/pom.xml b/foundations/foundation-config/pom.xml index 301fecfaa99..12c4a54c5be 100644 --- a/foundations/foundation-config/pom.xml +++ b/foundations/foundation-config/pom.xml @@ -21,7 +21,7 @@ foundations org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -40,30 +40,31 @@ spring-beans - com.netflix.archaius - archaius-core - - - commons-configuration - commons-configuration + org.springframework.boot + spring-boot-autoconfigure + org.yaml snakeyaml + + jakarta.annotation + jakarta.annotation-api + org.slf4j slf4j-api - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test @@ -73,6 +74,12 @@ org.apache.httpcomponents httpclient + + + commons-logging + commons-logging + + io.netty @@ -118,5 +125,10 @@ com.google.guava guava + + org.jmockit + jmockit + test + diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/BootStrapProperties.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/BootStrapProperties.java index 079bf86bed3..046b326b8b2 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/BootStrapProperties.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/BootStrapProperties.java @@ -17,20 +17,29 @@ package org.apache.servicecomb.config; -import java.util.LinkedHashMap; -import java.util.List; +import java.util.HashMap; import java.util.Map; -import java.util.Objects; +import java.util.Set; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.env.Environment; -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.PropertyConverter; -import org.apache.commons.configuration.SubsetConfiguration; -import org.springframework.util.StringUtils; /** * This class holds configurations that need to be configured * through property files or environment variables. + * + * These properties are core model for java chassis, e.g. + *
+ *   servicecomb:
+ *     service:
+ *       application:
+ *       name:
+ *       version:
+ *       environment:
+ *       properties:
+ * 
+ * */ public class BootStrapProperties { // start of : service definition keys @@ -43,6 +52,8 @@ public class BootStrapProperties { public static final String OLD_CONFIG_SERVICE_ROLE = "service_description.role"; + public static final String OLD_CONFIG_SERVICE_ALIAS = "service_description.alias"; + public static final String OLD_CONFIG_SERVICE_DESCRIPTION = "service_description.description"; public static final String OLD_CONFIG_SERVICE_ENVIRONMENT = "service_description.environment"; @@ -51,19 +62,13 @@ public class BootStrapProperties { public static final String OLD_CONFIG_SERVICE_PROPERTIES = "service_description.properties"; - public static final String OLD_CONFIG_SERVICE_PATHS = "service_description.paths"; - // service instance definition keys of old version public static final String OLD_CONFIG_SERVICE_INSTANCE_PROPERTIES = "instance_description.properties"; public static final String OLD_CONFIG_SERVICE_INSTANCE_EXTENDED_CLASS = "instance_description.propertyExtendedClass"; - public static final String OLD_CONFIG_SERVICE_INSTANCE_ENVIRONMENT = "instance_description.environment"; - public static final String OLD_CONFIG_SERVICE_INSTANCE_INITIAL_STATUS = "instance_description.initialStatus"; - private static final String OLD_CONFIG_SERVICE_INSTANCE_TAGS = "instance_description.properties.tags"; - // service definition keys of new version public static final String CONFIG_SERVICE_APPLICATION = "servicecomb.service.application"; @@ -73,6 +78,8 @@ public class BootStrapProperties { public static final String CONFIG_SERVICE_ROLE = "servicecomb.service.role"; + public static final String CONFIG_SERVICE_ALIAS = "servicecomb.service.alias"; + public static final String CONFIG_SERVICE_DESCRIPTION = "servicecomb.service.description"; public static final String CONFIG_SERVICE_ENVIRONMENT = "servicecomb.service.environment"; @@ -81,19 +88,13 @@ public class BootStrapProperties { public static final String CONFIG_SERVICE_PROPERTIES = "servicecomb.service.properties"; - public static final String CONFIG_SERVICE_PATHS = "servicecomb.service.paths"; - // service instance definition keys of new version public static final String CONFIG_SERVICE_INSTANCE_PROPERTIES = "servicecomb.instance.properties"; public static final String CONFIG_SERVICE_INSTANCE_EXTENDED_CLASS = "servicecomb.instance.propertyExtendedClass"; - public static final String CONFIG_SERVICE_INSTANCE_ENVIRONMENT = "servicecomb.instance.environment"; - public static final String CONFIG_SERVICE_INSTANCE_INITIAL_STATUS = "servicecomb.instance.initialStatus"; - private static final String CONFIG_SERVICE_INSTANCE_TAGS = "servicecomb.instance.properties.tags"; - // configuration default values public static final String DEFAULT_APPLICATION = "default"; @@ -105,53 +106,37 @@ public class BootStrapProperties { public static final String DEFAULT_MICROSERVICE_ENVIRONMENT = ""; - public static final String DEFAULT_MICROSERVICE_INSTANCE_ENVIRONMENT = "production"; - public static final String DEFAULT_MICROSERVICE_INSTANCE_INITIAL_STATUS = "UP"; - private static final Configuration configuration = ConfigUtil.createLocalConfig(); - - public static String readApplication(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_APPLICATION, + public static String readApplication(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_APPLICATION, OLD_CONFIG_SERVICE_APPLICATION, DEFAULT_APPLICATION); } - public static String readApplication() { - return readApplication(BootStrapProperties.configuration); - } - - public static String readServiceName(Configuration configuration) { - String result = readStringValue(configuration, CONFIG_SERVICE_NAME, OLD_CONFIG_SERVICE_NAME, + public static String readServiceName(Environment environment) { + String result = readStringValue(environment, CONFIG_SERVICE_NAME, OLD_CONFIG_SERVICE_NAME, DEFAULT_MICROSERVICE_NAME); checkMicroserviceName(result); return result; } - public static String readServiceName() { - return readServiceName(BootStrapProperties.configuration); - } - - public static String readServiceVersion(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_VERSION, OLD_CONFIG_SERVICE_VERSION, + public static String readServiceVersion(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_VERSION, OLD_CONFIG_SERVICE_VERSION, DEFAULT_MICROSERVICE_VERSION); } - public static String readServiceVersion() { - return readServiceVersion(BootStrapProperties.configuration); + public static String readServiceRole(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_ROLE, OLD_CONFIG_SERVICE_ROLE, DEFAULT_MICROSERVICE_ROLE); } - public static String readServiceRole(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_ROLE, OLD_CONFIG_SERVICE_ROLE, DEFAULT_MICROSERVICE_ROLE); + public static String readServiceAlias(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_ALIAS, OLD_CONFIG_SERVICE_ALIAS, null); } - public static String readServiceRole() { - return readServiceRole(BootStrapProperties.configuration); - } - - public static String readServiceDescription(Configuration configuration) { - String[] descriptionArray = configuration.getStringArray(CONFIG_SERVICE_DESCRIPTION); + public static String readServiceDescription(Environment environment) { + String[] descriptionArray = environment.getProperty(CONFIG_SERVICE_DESCRIPTION, String[].class); if (null == descriptionArray || descriptionArray.length < 1) { - descriptionArray = configuration.getStringArray(OLD_CONFIG_SERVICE_DESCRIPTION); + descriptionArray = environment.getProperty(OLD_CONFIG_SERVICE_DESCRIPTION, String[].class); } if (null == descriptionArray || descriptionArray.length < 1) { @@ -166,131 +151,57 @@ public static String readServiceDescription(Configuration configuration) { return rawDescriptionBuilder.substring(0, rawDescriptionBuilder.length() - 1); } - public static String readServiceDescription() { - return readServiceDescription(BootStrapProperties.configuration); - } - - public static String readServiceEnvironment(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_ENVIRONMENT, OLD_CONFIG_SERVICE_ENVIRONMENT, + public static String readServiceEnvironment(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_ENVIRONMENT, OLD_CONFIG_SERVICE_ENVIRONMENT, DEFAULT_MICROSERVICE_ENVIRONMENT); } - public static String readServiceEnvironment() { - return readServiceEnvironment(BootStrapProperties.configuration); - } - - public static String readServiceExtendedClass(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_EXTENDED_CLASS, OLD_CONFIG_SERVICE_EXTENDED_CLASS, + public static String readServiceExtendedClass(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_EXTENDED_CLASS, OLD_CONFIG_SERVICE_EXTENDED_CLASS, null); } - public static String readServiceExtendedClass() { - return readServiceExtendedClass(BootStrapProperties.configuration); - } - - public static Map readServiceProperties(Configuration configuration) { - return readProperties(configuration, CONFIG_SERVICE_PROPERTIES, OLD_CONFIG_SERVICE_PROPERTIES); - } - - public static Map readServiceProperties() { - return readServiceProperties(BootStrapProperties.configuration); + public static Map readServiceProperties(Environment environment) { + return readProperties(environment, CONFIG_SERVICE_PROPERTIES, OLD_CONFIG_SERVICE_PROPERTIES); } - public static List readServicePaths(Configuration configuration) { - List result = configuration.getList(CONFIG_SERVICE_PATHS); - if (result == null || result.isEmpty()) { - result = configuration.getList(OLD_CONFIG_SERVICE_PATHS); - } - return result; - } - - public static List readServicePaths() { - return readServicePaths(BootStrapProperties.configuration); - } - - public static Map readServiceInstanceProperties(Configuration configuration) { - return readProperties(configuration, CONFIG_SERVICE_INSTANCE_PROPERTIES, OLD_CONFIG_SERVICE_INSTANCE_PROPERTIES); - } - - public static Map readServiceInstanceProperties() { - return readServiceInstanceProperties(BootStrapProperties.configuration); + public static Map readServiceInstanceProperties(Environment environment) { + return readProperties(environment, CONFIG_SERVICE_INSTANCE_PROPERTIES, OLD_CONFIG_SERVICE_INSTANCE_PROPERTIES); } - public static String readServiceInstanceExtendedClass(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_INSTANCE_EXTENDED_CLASS, + public static String readServiceInstanceExtendedClass(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_INSTANCE_EXTENDED_CLASS, OLD_CONFIG_SERVICE_INSTANCE_EXTENDED_CLASS, null); } - public static String readServiceInstanceExtendedClass() { - return readServiceInstanceExtendedClass(BootStrapProperties.configuration); - } - - public static String readServiceInstanceEnvironment(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_INSTANCE_ENVIRONMENT, - OLD_CONFIG_SERVICE_INSTANCE_ENVIRONMENT, - DEFAULT_MICROSERVICE_INSTANCE_ENVIRONMENT); - } - - public static String readServiceInstanceEnvironment() { - return readServiceInstanceEnvironment(BootStrapProperties.configuration); - } - - public static String readServiceInstanceInitialStatus(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_INSTANCE_INITIAL_STATUS, + public static String readServiceInstanceInitialStatus(Environment environment) { + return readStringValue(environment, CONFIG_SERVICE_INSTANCE_INITIAL_STATUS, OLD_CONFIG_SERVICE_INSTANCE_INITIAL_STATUS, DEFAULT_MICROSERVICE_INSTANCE_INITIAL_STATUS); } - public static String readServiceInstanceInitialStatus() { - return readServiceInstanceInitialStatus(BootStrapProperties.configuration); - } - - public static String readServiceInstanceTags(Configuration configuration) { - return readStringValue(configuration, CONFIG_SERVICE_INSTANCE_TAGS, - OLD_CONFIG_SERVICE_INSTANCE_TAGS, - null); - } - - public static String readServiceInstanceTags() { - return readServiceInstanceTags(BootStrapProperties.configuration); - } - - private static String readStringValue(Configuration configuration, String newKey, String oldKey, + private static String readStringValue(Environment environment, String newKey, String oldKey, String defaultValue) { - String result = configuration.getString(newKey, null); + String result = environment.getProperty(newKey); if (result == null) { - return configuration.getString(oldKey, defaultValue); + return environment.getProperty(oldKey, defaultValue); } return result; } - private static Map readProperties(Configuration configuration, String newKey, String oldKey) { - AbstractConfiguration subset = (AbstractConfiguration) configuration.subset(newKey); - if (subset.isEmpty()) { - subset = (AbstractConfiguration) configuration.subset(oldKey); + private static Map readProperties(Environment environment, String newKey, String oldKey) { + String prefix = newKey; + Set keys = ConfigUtil.propertiesWithPrefix(environment, prefix); + if (keys.isEmpty()) { + prefix = oldKey; + keys = ConfigUtil.propertiesWithPrefix(environment, oldKey); } - return toStringMap(subset); - } - - private static Map toStringMap(AbstractConfiguration configuration) { - AbstractConfiguration root = findRoot(configuration); - Map map = new LinkedHashMap<>(); - configuration.getKeys().forEachRemaining(key -> { - Object value = configuration.getProperty(key); - // support placeholder - value = PropertyConverter.interpolate(value, root); - map.put(key, Objects.toString(value, null)); - }); - return map; - } - - private static AbstractConfiguration findRoot(AbstractConfiguration configuration) { - if (configuration instanceof SubsetConfiguration) { - return findRoot((AbstractConfiguration) ((SubsetConfiguration) configuration).getParent()); + Map result = new HashMap<>(keys.size()); + for (String key : keys) { + result.put(key.substring(prefix.length() + 1), environment.getProperty(key)); } - - return configuration; + return result; } private static void checkMicroserviceName(String name) { diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConcurrentMapConfigurationExt.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConcurrentMapConfigurationExt.java deleted file mode 100644 index 847342c43b1..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConcurrentMapConfigurationExt.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.config; - -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.configuration.AbstractConfiguration; - -import com.netflix.config.ConcurrentMapConfiguration; - -/** - * Disable delimiter parsing for string - */ -@SuppressWarnings("unchecked") -public class ConcurrentMapConfigurationExt extends ConcurrentMapConfiguration { - public ConcurrentMapConfigurationExt() { - super(); - setDelimiterParsingDisabled(true); - } - - public ConcurrentMapConfigurationExt(Map mapToCopy) { - super(); - setDelimiterParsingDisabled(true); - map = new ConcurrentHashMap(mapToCopy); - } - - public ConcurrentMapConfigurationExt(AbstractConfiguration config) { - super(); - config.setDelimiterParsingDisabled(true); - for (Iterator i = config.getKeys(); i.hasNext(); ) { - String name = i.next(); - Object value = config.getProperty(name); - map.put(name, value); - } - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigEnvironmentPostProcessor.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigEnvironmentPostProcessor.java new file mode 100644 index 00000000000..8462da9057d --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigEnvironmentPostProcessor.java @@ -0,0 +1,141 @@ +/* + * 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.config; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.servicecomb.config.file.MicroserviceConfigLoader; +import org.apache.servicecomb.foundation.bootstrap.BootStrapService; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; + +/** + * Initialize configuration. + */ +public class ConfigEnvironmentPostProcessor implements EnvironmentPostProcessor { + public static final String MICROSERVICE_PROPERTY_SOURCE_NAME = "microservice.yaml"; + + public static final String MAPPING_PROPERTY_SOURCE_NAME = "mapping.yaml"; + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + LegacyPropertyFactory.setEnvironment(environment); + addMicroserviceDefinitions(environment); + startupBootStrapService(environment); + addDynamicConfigurationToSpring(environment); + } + + public static void addMicroserviceDefinitions(Environment environment) { + addMicroserviceYAMLToSpring(environment); + addMappingToSpring(environment); + } + + private void startupBootStrapService(Environment environment) { + for (BootStrapService bootStrapService : SPIServiceUtils.getSortedService(BootStrapService.class)) { + bootStrapService.startup(environment); + } + } + + /** + * make springboot have a change to add microservice.yaml source earlier
+ * to affect {@link Conditional} + * @param environment environment + */ + private static void addMicroserviceYAMLToSpring(Environment environment) { + if (!(environment instanceof ConfigurableEnvironment)) { + return; + } + + MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources(); + if (propertySources.contains(MICROSERVICE_PROPERTY_SOURCE_NAME)) { + return; + } + + propertySources.addLast(new EnumerablePropertySource(MICROSERVICE_PROPERTY_SOURCE_NAME) { + private final Map values = new HashMap<>(); + + private final String[] propertyNames; + + { + MicroserviceConfigLoader loader = new MicroserviceConfigLoader(); + loader.loadAndSort(); + + loader.getConfigModels() + .forEach(configModel -> values.putAll(YAMLUtil.retrieveItems("", configModel.getConfig()))); + + propertyNames = values.keySet().toArray(new String[0]); + } + + @Override + public String[] getPropertyNames() { + return propertyNames; + } + + @SuppressWarnings("unchecked") + @Override + public Object getProperty(String name) { + Object value = this.values.get(name); + + // spring will not resolve nested placeholder of list, so try to fix the problem + if (value instanceof List) { + value = ((List) value).stream() + .filter(item -> item instanceof String) + .map(item -> environment.resolvePlaceholders((String) item)) + .collect(Collectors.toList()); + } + return value; + } + }); + } + + private static void addMappingToSpring(Environment environment) { + if (!(environment instanceof ConfigurableEnvironment)) { + return; + } + + MutablePropertySources propertySources = ((ConfigurableEnvironment) environment).getPropertySources(); + if (propertySources.contains(MAPPING_PROPERTY_SOURCE_NAME)) { + return; + } + + Map mappings = ConfigMapping.getConvertedMap(environment); + propertySources.addFirst(new MapPropertySource(MAPPING_PROPERTY_SOURCE_NAME, mappings)); + } + + private void addDynamicConfigurationToSpring(Environment environment) { + if (!(environment instanceof ConfigurableEnvironment)) { + return; + } + + for (DynamicPropertiesSource dynamicPropertiesSource : + SPIServiceUtils.getOrLoadSortedService(DynamicPropertiesSource.class)) { + ((ConfigurableEnvironment) environment).getPropertySources() + .addFirst(dynamicPropertiesSource.create(environment)); + } + } +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigMapping.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigMapping.java index 0dace2143a4..d80caaa51a9 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigMapping.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigMapping.java @@ -27,8 +27,7 @@ import java.util.List; import java.util.Map; -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.config.archaius.sources.AbstractConfigLoader; +import org.apache.servicecomb.config.file.AbstractConfigLoader; import org.apache.servicecomb.foundation.common.utils.JvmUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +39,7 @@ * Created by on 2017/1/5. */ public final class ConfigMapping { - private static Map configMap; + private static final Map configMap; private static final Logger LOGGER = LoggerFactory.getLogger(ConfigMapping.class); @@ -95,15 +94,6 @@ public static Map getConvertedMap(Map oldMap) { return retMap; } - public static Map getConvertedMap(Configuration config) { - if (configMap == null) { - return new LinkedHashMap<>(); - } - Map retMap = new LinkedHashMap<>(); - configMap.entrySet().forEach(entry -> putConfigsToRetMap(retMap, entry, config.getProperty(entry.getKey()))); - return retMap; - } - public static Map getConvertedMap(Environment environment) { if (configMap == null) { return new LinkedHashMap<>(); diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java index ecb51932e98..a09b2eaac36 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigUtil.java @@ -17,325 +17,59 @@ package org.apache.servicecomb.config; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_CSE_PREFIX; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_KEY_SPLITER; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_SERVICECOMB_PREFIX; - +import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.stream.Collectors; - -import javax.annotation.Nonnull; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.EnvironmentConfiguration; -import org.apache.commons.configuration.PropertyConverter; -import org.apache.commons.configuration.SystemConfiguration; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.reflect.FieldUtils; -import org.apache.servicecomb.config.archaius.scheduler.NeverStartPollingScheduler; -import org.apache.servicecomb.config.archaius.sources.ConfigModel; -import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigLoader; -import org.apache.servicecomb.config.archaius.sources.MicroserviceConfigurationSource; -import org.apache.servicecomb.config.event.DynamicConfigurationChangedEvent; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSourceLoader; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import java.util.Set; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.ConcurrentMapConfiguration; -import com.netflix.config.ConfigurationManager; -import com.netflix.config.DynamicProperty; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; public final class ConfigUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(ConfigUtil.class); - - private static final String IS_PRINT_URL = "servicecomb.config.log.verbose"; - - private static Map localConfig = new HashMap<>(); - - /** - *

The configurations not read by ServiceComb.

- *

- * For example, this map can store the configurations read by SpringBoot from application.properties, - * If users write the configurations of ServiceComb into application.yml instead of microservice.yaml, - * this can help {@link ConfigUtil} load config correctly. - *

- */ - private static final Map> EXTRA_CONFIG_MAP = new LinkedHashMap<>(); - private ConfigUtil() { } - public static void setConfigs(Map config) { - localConfig = config; - } - - public static void addConfig(String key, Object value) { - localConfig.put(key, value); - } - - public static Object getProperty(String key) { - AbstractConfiguration config = ConfigurationManager.getConfigInstance(); - return getProperty(config, key); - } - - public static Object getProperty(Object config, String key) { - if (null != config && Configuration.class.isInstance(config)) { - Configuration configuration = (Configuration) config; - return configuration.getProperty(key); - } - return null; - } - - /** - * get comma separated list values from yaml string - */ - public static List getStringList(@Nonnull Configuration config, @Nonnull String key) { - return parseArrayValue(config.getString(key)).stream() - .map(v -> Objects.toString(v, null)) - .collect(Collectors.toList()); - } - public static List parseArrayValue(String value) { - return PropertyConverter.split(value, ',', true); - } - - public static ConcurrentCompositeConfiguration createLocalConfig() { - MicroserviceConfigLoader loader = new MicroserviceConfigLoader(); - loader.loadAndSort(); - if (localConfig.size() > 0) { - ConfigModel model = new ConfigModel(); - model.setConfig(localConfig); - loader.getConfigModels().add(model); - } - - boolean isPrintUrl = DynamicPropertyFactory.getInstance() - .getBooleanProperty(IS_PRINT_URL, true).get(); - if (isPrintUrl) { - LOGGER.info("create local config from paths=[{}]", StringUtils.join(loader.getConfigModels(), ",")); - } - - ConcurrentCompositeConfiguration config = ConfigUtil.createLocalConfig(loader.getConfigModels()); - return config; - } - - private static ConcurrentCompositeConfiguration createLocalConfig(List configModelList) { - ConcurrentCompositeConfiguration config = new ConcurrentCompositeConfiguration(); - - duplicateCseConfigToServicecomb(config, - new ConcurrentMapConfigurationExt(new SystemConfiguration()), - "configFromSystem"); - duplicateCseConfigToServicecomb(config, - convertEnvVariable(new ConcurrentMapConfigurationExt(new EnvironmentConfiguration())), - "configFromEnvironment"); - // If there is extra configurations, add it into config. - EXTRA_CONFIG_MAP.entrySet() - .stream() - .filter(mapEntry -> !mapEntry.getValue().isEmpty()) - .forEachOrdered(configMapEntry -> duplicateCseConfigToServicecomb(config, - new ConcurrentMapConfigurationExt(configMapEntry.getValue()), - configMapEntry.getKey())); - // we have already copy the cse config to the serviceComb config when we load the config from local yaml files - // hence, we do not need duplicate copy it. - config.addConfiguration(new DynamicConfigurationExt( - new MicroserviceConfigurationSource(configModelList), new NeverStartPollingScheduler()), - "configFromYamlFile"); - duplicateCseConfigToServicecombAtFront(config, - new ConcurrentMapConfigurationExt(ConfigMapping.getConvertedMap(config)), - "configFromMapping"); - return config; - } - - public static AbstractConfiguration convertEnvVariable(AbstractConfiguration source) { - Iterator keys = source.getKeys(); - while (keys.hasNext()) { - String key = keys.next(); - String[] separatedKey = key.split(CONFIG_KEY_SPLITER); - if (separatedKey.length == 1) { - continue; - } - String newKey = String.join(".", separatedKey); - source.addProperty(newKey, source.getProperty(key)); - } - return source; - } - - //inject a copy of servicecomb.xxx for cse.xxx - private static void duplicateCseConfigToServicecomb(AbstractConfiguration source) { - Iterator keys = source.getKeys(); - while (keys.hasNext()) { - String key = keys.next(); - if (!key.startsWith(CONFIG_CSE_PREFIX)) { - continue; - } - - String servicecombKey = CONFIG_SERVICECOMB_PREFIX + key.substring(key.indexOf(".") + 1); - if (!source.containsKey(servicecombKey)) { - source.addProperty(servicecombKey, source.getProperty(key)); - } else { - LOGGER - .warn( - "Key {} with an ambiguous item {} exists, it's recommended to use only one of them.", - key, servicecombKey); - } - } - } - - private static void duplicateCseConfigToServicecomb(ConcurrentCompositeConfiguration compositeConfiguration, - AbstractConfiguration source, - String sourceName) { - duplicateCseConfigToServicecomb(source); - - compositeConfiguration.addConfiguration(source, sourceName); - } - - private static void duplicateCseConfigToServicecombAtFront(ConcurrentCompositeConfiguration compositeConfiguration, - AbstractConfiguration source, - String sourceName) { - duplicateCseConfigToServicecomb(source); - - compositeConfiguration.addConfigurationAtFront(source, sourceName); - } - - private static ConfigCenterConfigurationSource createConfigCenterConfigurationSource( - Configuration localConfiguration) { - ConfigCenterConfigurationSource configCenterConfigurationSource = ConfigCenterConfigurationSourceLoader - .getConfigCenterConfigurationSource(localConfiguration); - - if (null == configCenterConfigurationSource) { - LOGGER.info("none of config center source enabled."); - return null; - } - - LOGGER.info("use config center source {}", configCenterConfigurationSource.getClass().getName()); - return configCenterConfigurationSource; - } - - private static void createDynamicWatchedConfiguration( - ConcurrentCompositeConfiguration localConfiguration, - ConfigCenterConfigurationSource configCenterConfigurationSource) { - ConcurrentMapConfiguration injectConfig = new ConcurrentMapConfigurationExt(); - localConfiguration.addConfigurationAtFront(injectConfig, "extraInjectConfig"); - configCenterConfigurationSource.addUpdateListener(new ServiceCombPropertyUpdateListener(injectConfig)); - - DynamicWatchedConfigurationExt configFromConfigCenter = - new DynamicWatchedConfigurationExt(configCenterConfigurationSource); - duplicateCseConfigToServicecomb(configFromConfigCenter); - localConfiguration.addConfigurationAtFront(configFromConfigCenter, "configCenterConfig"); - } - - public static ConfigCenterConfigurationSource installDynamicConfig() { - if (ConfigurationManager.isConfigurationInstalled()) { - LOGGER.warn("Configuration installed by others, will ignore this configuration."); - return null; + if (value == null) { + return new ArrayList<>(0); } - - ConcurrentCompositeConfiguration compositeConfig = ConfigUtil.createLocalConfig(); - ConfigCenterConfigurationSource configCenterConfigurationSource = - createConfigCenterConfigurationSource(compositeConfig); - if (configCenterConfigurationSource != null) { - // add listeners - createDynamicWatchedConfiguration(compositeConfig, configCenterConfigurationSource); - // then init data - configCenterConfigurationSource.init(compositeConfig); + String[] tokens = value.split(","); + List result = new ArrayList<>(tokens.length); + for (String t : tokens) { + result.add(t.trim()); } - - ConfigurationManager.install(compositeConfig); - - return configCenterConfigurationSource; - } - - public static void destroyConfigCenterConfigurationSource() { - SPIServiceUtils.getAllService(ConfigCenterConfigurationSource.class).forEach(source -> { - try { - source.destroy(); - } catch (Throwable e) { - LOGGER.error("Failed to destroy {}", source.getClass().getName()); - } - }); - } - - public static void addExtraConfig(String extraConfigName, Map extraConfig) { - EXTRA_CONFIG_MAP.put(extraConfigName, extraConfig); - } - - public static void clearExtraConfig() { - EXTRA_CONFIG_MAP.clear(); + return result; } - private static class ServiceCombPropertyUpdateListener implements WatchedUpdateListener { - - private final ConcurrentMapConfiguration injectConfig; - - ServiceCombPropertyUpdateListener(ConcurrentMapConfiguration injectConfig) { - this.injectConfig = injectConfig; - } - - @Override - public void updateConfiguration(WatchedUpdateResult watchedUpdateResult) { - Map adds = watchedUpdateResult.getAdded(); - if (adds != null) { - for (String add : adds.keySet()) { - if (add.startsWith(CONFIG_CSE_PREFIX)) { - String key = CONFIG_SERVICECOMB_PREFIX + add.substring(add.indexOf(".") + 1); - injectConfig.addProperty(key, adds.get(add)); - } - } - } - - Map deletes = watchedUpdateResult.getDeleted(); - if (deletes != null) { - for (String delete : deletes.keySet()) { - if (delete.startsWith(CONFIG_CSE_PREFIX)) { - injectConfig.clearProperty(CONFIG_SERVICECOMB_PREFIX + delete.substring(delete.indexOf(".") + 1)); + public static Set propertiesWithPrefix(Environment environment, String prefix) { + Set result = new HashSet<>(); + for (PropertySource propertySource : ((ConfigurableEnvironment) environment).getPropertySources()) { + if (propertySource instanceof EnumerablePropertySource) { + for (String key : ((EnumerablePropertySource) propertySource).getPropertyNames()) { + if (key.startsWith(prefix)) { + result.add(key); } } } + } + return result; + } - Map changes = watchedUpdateResult.getChanged(); - if (changes != null) { - for (String change : changes.keySet()) { - if (change.startsWith(CONFIG_CSE_PREFIX)) { - String key = CONFIG_SERVICECOMB_PREFIX + change.substring(change.indexOf(".") + 1); - injectConfig.setProperty(key, changes.get(change)); + public static Map stringPropertiesWithPrefix(Environment environment, String prefix) { + Map result = new HashMap<>(); + for (PropertySource propertySource : ((ConfigurableEnvironment) environment).getPropertySources()) { + if (propertySource instanceof EnumerablePropertySource) { + for (String key : ((EnumerablePropertySource) propertySource).getPropertyNames()) { + if (key.startsWith(prefix)) { + result.put(key, environment.getProperty(key)); } } } - - EventManager.post(new DynamicConfigurationChangedEvent(watchedUpdateResult)); - } - } - - @SuppressWarnings("unchecked") - public static ConcurrentHashMap getAllDynamicProperties() { - try { - return (ConcurrentHashMap) FieldUtils - .readDeclaredStaticField(DynamicProperty.class, "ALL_PROPS", true); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); - } - } - - @SuppressWarnings("unchecked") - public static CopyOnWriteArraySet getCallbacks(DynamicProperty property) { - try { - return (CopyOnWriteArraySet) FieldUtils.readDeclaredField(property, "callbacks", true); - } catch (IllegalAccessException e) { - throw new IllegalStateException(e); } + return result; } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationChangedEvent.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationChangedEvent.java new file mode 100644 index 00000000000..2c0532a6543 --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/ConfigurationChangedEvent.java @@ -0,0 +1,100 @@ +/* + * 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.config; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +/** + * This event is fired when configuration changed. And the change is already applied to Environment. + * + * Listeners can use Environment to get the latest value. + */ +public class ConfigurationChangedEvent { + private final Map added; + + private final Map deleted; + + private final Map updated; + + private Set changed; + + private ConfigurationChangedEvent(Map added, Map updated, + Map deleted) { + this.added = added; + this.deleted = deleted; + this.updated = updated; + this.changed = new HashSet<>(); + this.changed.addAll(added.keySet()); + this.changed.addAll(updated.keySet()); + this.changed.addAll(deleted.keySet()); + } + + public static ConfigurationChangedEvent createIncremental(Map latest, Map last) { + Map itemsCreated = new HashMap<>(); + Map itemsDeleted = new HashMap<>(); + Map itemsModified = new HashMap<>(); + + for (Map.Entry entry : latest.entrySet()) { + String itemKey = entry.getKey(); + if (!last.containsKey(itemKey)) { + itemsCreated.put(itemKey, entry.getValue()); + } else if (!Objects.equals(last.get(itemKey), latest.get(itemKey))) { + itemsModified.put(itemKey, entry.getValue()); + } + } + for (String itemKey : last.keySet()) { + if (!latest.containsKey(itemKey)) { + itemsDeleted.put(itemKey, null); + } + } + ConfigurationChangedEvent event = ConfigurationChangedEvent + .createIncremental(itemsCreated, itemsModified, itemsDeleted); + return event; + } + + public static ConfigurationChangedEvent createIncremental(Map added, Map updated, + Map deleted) { + return new ConfigurationChangedEvent(added, updated, deleted); + } + + public static ConfigurationChangedEvent createIncremental(Map updated) { + return new ConfigurationChangedEvent(new HashMap<>(), updated, new HashMap<>()); + } + + public final Map getAdded() { + return added; + } + + + public final Map getUpdated() { + return updated; + } + + + public final Map getDeleted() { + return deleted; + } + + public final Set getChanged() { + return changed; + } +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DataCenterProperties.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DataCenterProperties.java new file mode 100644 index 00000000000..df61c22f547 --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DataCenterProperties.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.config; + +public class DataCenterProperties { + public static final String PREFIX = "servicecomb.datacenter"; + + private String name; + + private String region; + + private String availableZone; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getAvailableZone() { + return availableZone; + } + + public void setAvailableZone(String availableZone) { + this.availableZone = availableZone; + } +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicConfigurationExt.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicConfigurationExt.java deleted file mode 100644 index a89e89bf26c..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicConfigurationExt.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.config; - -import com.netflix.config.AbstractPollingScheduler; -import com.netflix.config.DynamicConfiguration; -import com.netflix.config.PolledConfigurationSource; - -/** - * Disable delimiter parsing for string - */ -@SuppressWarnings("unchecked") -public class DynamicConfigurationExt extends DynamicConfiguration { - public DynamicConfigurationExt(PolledConfigurationSource source, AbstractPollingScheduler scheduler) { - super(); - setDelimiterParsingDisabled(true); - startPolling(source, scheduler); - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicProperties.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicProperties.java index 47e060af733..58f84dd97b0 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicProperties.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicProperties.java @@ -23,10 +23,6 @@ import java.util.function.LongConsumer; public interface DynamicProperties { - - DynamicProperties DEFAULT_PROPERTY_OBSERVATION = new DynamicProperties() { - }; - default String getStringProperty(String propertyName, Consumer consumer, String defaultValue) { return defaultValue; } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesImpl.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesImpl.java index c90caa4c7f6..323e84d80aa 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesImpl.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesImpl.java @@ -17,110 +17,163 @@ package org.apache.servicecomb.config; -import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Consumer; import java.util.function.DoubleConsumer; import java.util.function.IntConsumer; import java.util.function.LongConsumer; -import org.apache.commons.configuration.AbstractConfiguration; -import org.springframework.stereotype.Component; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.springframework.core.env.Environment; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.ConfigurationManager; -import com.netflix.config.DynamicBooleanProperty; -import com.netflix.config.DynamicDoubleProperty; -import com.netflix.config.DynamicFloatProperty; -import com.netflix.config.DynamicIntProperty; -import com.netflix.config.DynamicLongProperty; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.DynamicStringProperty; +import com.google.common.eventbus.Subscribe; -@Component -class DynamicPropertiesImpl implements DynamicProperties { - public DynamicPropertiesImpl() { +public class DynamicPropertiesImpl implements DynamicProperties { + private static class Holder { + C callback; + + D defaultValue; + + Holder(C callback, D defaultValue) { + this.callback = callback; + this.defaultValue = defaultValue; + } + } + + private final Map, String>>> stringCallbacks = new ConcurrentHashMap<>(); + + private final Map>> intCallbacks = new ConcurrentHashMap<>(); + + private final Map>> longCallbacks = new ConcurrentHashMap<>(); + + private final Map>> floatCallbacks = new ConcurrentHashMap<>(); + + private final Map>> doubleCallbacks = new ConcurrentHashMap<>(); + + private final Map, Boolean>>> booleanCallbacks = new ConcurrentHashMap<>(); + + private final Environment environment; + + public DynamicPropertiesImpl(Environment environment) { + this.environment = environment; + EventManager.register(this); } - public DynamicPropertiesImpl(AbstractConfiguration... configurations) { - ConcurrentCompositeConfiguration configuration = new ConcurrentCompositeConfiguration(); - Arrays.stream(configurations).forEach(configuration::addConfiguration); + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + for (Entry entry : event.getAdded().entrySet()) { + updateValue(entry); + } + + for (Entry entry : event.getUpdated().entrySet()) { + updateValue(entry); + } - ConfigurationManager.install(configuration); + for (Entry entry : event.getDeleted().entrySet()) { + updateValue(entry); + } + } + + private void updateValue(Entry entry) { + if (stringCallbacks.containsKey(entry.getKey())) { + for (Holder, String> callbacks : stringCallbacks.get(entry.getKey())) { + callbacks.callback.accept(environment.getProperty(entry.getKey(), callbacks.defaultValue)); + } + } + if (intCallbacks.containsKey(entry.getKey())) { + for (Holder callbacks : intCallbacks.get(entry.getKey())) { + callbacks.callback.accept(environment.getProperty(entry.getKey(), Integer.class, callbacks.defaultValue)); + } + } + if (longCallbacks.containsKey(entry.getKey())) { + for (Holder callbacks : longCallbacks.get(entry.getKey())) { + callbacks.callback.accept(environment.getProperty(entry.getKey(), Long.class, callbacks.defaultValue)); + } + } + if (floatCallbacks.containsKey(entry.getKey())) { + for (Holder callbacks : floatCallbacks.get(entry.getKey())) { + callbacks.callback.accept(environment.getProperty(entry.getKey(), Float.class, callbacks.defaultValue)); + } + } + if (doubleCallbacks.containsKey(entry.getKey())) { + for (Holder callbacks : doubleCallbacks.get(entry.getKey())) { + callbacks.callback.accept(environment.getProperty(entry.getKey(), Double.class, callbacks.defaultValue)); + } + } + if (booleanCallbacks.containsKey(entry.getKey())) { + for (Holder, Boolean> callbacks : booleanCallbacks.get(entry.getKey())) { + callbacks.callback.accept(environment.getProperty(entry.getKey(), Boolean.class, callbacks.defaultValue)); + } + } } @Override public String getStringProperty(String propertyName, Consumer consumer, String defaultValue) { - DynamicStringProperty prop = propertyFactoryInstance().getStringProperty(propertyName, defaultValue); - prop.addCallback(() -> consumer.accept(prop.get())); - return prop.get(); + stringCallbacks.computeIfAbsent(propertyName, key -> new HashSet<>()).add(new Holder<>(consumer, defaultValue)); + return environment.getProperty(propertyName, defaultValue); } @Override public String getStringProperty(String propertyName, String defaultValue) { - return propertyFactoryInstance().getStringProperty(propertyName, defaultValue).get(); + return environment.getProperty(propertyName, defaultValue); } @Override public int getIntProperty(String propertyName, IntConsumer consumer, int defaultValue) { - DynamicIntProperty prop = propertyFactoryInstance().getIntProperty(propertyName, defaultValue); - prop.addCallback(() -> consumer.accept(prop.get())); - return prop.get(); + intCallbacks.computeIfAbsent(propertyName, key -> new HashSet<>()).add(new Holder<>(consumer, defaultValue)); + return environment.getProperty(propertyName, int.class, defaultValue); } @Override public int getIntProperty(String propertyName, int defaultValue) { - return propertyFactoryInstance().getIntProperty(propertyName, defaultValue).get(); + return environment.getProperty(propertyName, int.class, defaultValue); } @Override public long getLongProperty(String propertyName, LongConsumer consumer, long defaultValue) { - DynamicLongProperty prop = propertyFactoryInstance().getLongProperty(propertyName, defaultValue); - prop.addCallback(() -> consumer.accept(prop.get())); - return prop.get(); + longCallbacks.computeIfAbsent(propertyName, key -> new HashSet<>()).add(new Holder<>(consumer, defaultValue)); + return environment.getProperty(propertyName, long.class, defaultValue); } @Override public long getLongProperty(String propertyName, long defaultValue) { - return propertyFactoryInstance().getLongProperty(propertyName, defaultValue).get(); + return environment.getProperty(propertyName, long.class, defaultValue); } @Override public float getFloatProperty(String propertyName, DoubleConsumer consumer, float defaultValue) { - DynamicFloatProperty prop = propertyFactoryInstance().getFloatProperty(propertyName, defaultValue); - prop.addCallback(() -> consumer.accept(prop.get())); - return prop.get(); + floatCallbacks.computeIfAbsent(propertyName, key -> new HashSet<>()).add(new Holder<>(consumer, defaultValue)); + return environment.getProperty(propertyName, float.class, defaultValue); } @Override public float getFloatProperty(String propertyName, float defaultValue) { - return propertyFactoryInstance().getFloatProperty(propertyName, defaultValue).get(); + return environment.getProperty(propertyName, float.class, defaultValue); } @Override public double getDoubleProperty(String propertyName, DoubleConsumer consumer, double defaultValue) { - DynamicDoubleProperty prop = propertyFactoryInstance().getDoubleProperty(propertyName, defaultValue); - prop.addCallback(() -> consumer.accept(prop.get())); - return prop.get(); + doubleCallbacks.computeIfAbsent(propertyName, key -> new HashSet<>()).add(new Holder<>(consumer, defaultValue)); + return environment.getProperty(propertyName, double.class, defaultValue); } @Override public double getDoubleProperty(String propertyName, double defaultValue) { - return propertyFactoryInstance().getDoubleProperty(propertyName, defaultValue).get(); + return environment.getProperty(propertyName, double.class, defaultValue); } @Override public boolean getBooleanProperty(String propertyName, Consumer consumer, boolean defaultValue) { - DynamicBooleanProperty prop = propertyFactoryInstance().getBooleanProperty(propertyName, defaultValue); - prop.addCallback(() -> consumer.accept(prop.get())); - return prop.get(); + booleanCallbacks.computeIfAbsent(propertyName, key -> new HashSet<>()).add(new Holder<>(consumer, defaultValue)); + return environment.getProperty(propertyName, boolean.class, defaultValue); } @Override public boolean getBooleanProperty(String propertyName, boolean defaultValue) { - return propertyFactoryInstance().getBooleanProperty(propertyName, defaultValue).get(); - } - - private DynamicPropertyFactory propertyFactoryInstance() { - return DynamicPropertyFactory.getInstance(); + return environment.getProperty(propertyName, boolean.class, defaultValue); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesSource.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesSource.java new file mode 100644 index 00000000000..8634bff29f3 --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicPropertiesSource.java @@ -0,0 +1,28 @@ +/* + * 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.config; + +import org.springframework.core.Ordered; +import org.springframework.core.env.Environment; +import org.springframework.core.env.PropertySource; + +/** + * SPI to add new DynamicPropertiesSource. + */ +public interface DynamicPropertiesSource extends Ordered { + PropertySource create(Environment environment); +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicWatchedConfigurationExt.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicWatchedConfigurationExt.java deleted file mode 100644 index 3ea8a029056..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/DynamicWatchedConfigurationExt.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.config; - -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.ConcurrentMapConfiguration; -import com.netflix.config.DynamicPropertyUpdater; -import com.netflix.config.DynamicWatchedConfiguration; -import com.netflix.config.WatchedConfigurationSource; -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; - -/** - * Same as DynamicWatchedConfiguration but Disable delimiter parsing for string - * - * @see DynamicWatchedConfiguration - */ -@SuppressWarnings("unchecked") -public class DynamicWatchedConfigurationExt extends ConcurrentMapConfiguration implements WatchedUpdateListener { - - private final boolean ignoreDeletesFromSource; - - private final DynamicPropertyUpdater updater; - - private static final Logger LOGGER = LoggerFactory.getLogger(DynamicWatchedConfigurationExt.class); - - private DynamicWatchedConfigurationExt(WatchedConfigurationSource source, boolean ignoreDeletesFromSource, - DynamicPropertyUpdater updater) { - this.ignoreDeletesFromSource = ignoreDeletesFromSource; - this.updater = updater; - - setDelimiterParsingDisabled(true); - - // get a current snapshot of the config source data - try { - Map currentData = source.getCurrentData(); - WatchedUpdateResult result = WatchedUpdateResult.createFull(currentData); - - updateConfiguration(result); - } catch (final Exception exc) { - LOGGER.error("could not getCurrentData() from the WatchedConfigurationSource", exc); - } - - // add a listener for subsequent config updates - source.addUpdateListener(this); - } - - public DynamicWatchedConfigurationExt(final WatchedConfigurationSource source) { - this(source, false, new DynamicPropertyUpdater()); - } - - @Override - public void updateConfiguration(final WatchedUpdateResult result) { - updater.updateProperties(result, this, ignoreDeletesFromSource); - } -} \ No newline at end of file diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/FoundationConfigConfiguration.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/FoundationConfigConfiguration.java new file mode 100644 index 00000000000..1f74e897dd6 --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/FoundationConfigConfiguration.java @@ -0,0 +1,69 @@ +/* + * 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.config; + +import org.apache.servicecomb.config.inject.InjectBeanPostProcessor; +import org.apache.servicecomb.config.priority.ConfigObjectFactory; +import org.apache.servicecomb.config.priority.PriorityPropertyFactory; +import org.apache.servicecomb.config.priority.PriorityPropertyManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import org.springframework.core.env.Environment; + +@Configuration +@SuppressWarnings("unused") +public class FoundationConfigConfiguration { + @Bean + public static InjectBeanPostProcessor scbInjectBeanPostProcessor( + @Autowired @Lazy PriorityPropertyManager priorityPropertyManager) { + return new InjectBeanPostProcessor(priorityPropertyManager); + } + + @Bean + public PriorityPropertyManager scbPriorityPropertyManager(ConfigObjectFactory configObjectFactory) { + return new PriorityPropertyManager(configObjectFactory); + } + + @Bean + public PriorityPropertyFactory scbPriorityPropertyFactory(Environment environment) { + return new PriorityPropertyFactory(environment); + } + + @Bean + public DynamicPropertiesImpl scbDynamicProperties(Environment environment) { + return new DynamicPropertiesImpl(environment); + } + + @Bean + public ConfigObjectFactory scbConfigObjectFactory(PriorityPropertyFactory propertyFactory) { + return new ConfigObjectFactory(propertyFactory); + } + + @Bean + @ConfigurationProperties(prefix = DataCenterProperties.PREFIX) + public DataCenterProperties scbDataCenterProperties() { + return new DataCenterProperties(); + } + + @Bean + public InMemoryDynamicPropertiesSource scbInMemoryDynamicPropertiesSource() { + return new InMemoryDynamicPropertiesSource(); + } +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/InMemoryDynamicPropertiesSource.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/InMemoryDynamicPropertiesSource.java new file mode 100644 index 00000000000..f6139af0a24 --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/InMemoryDynamicPropertiesSource.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.config; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.PropertySource; + +/** + * This DynamicPropertiesSource is created for easier system tests. + */ +public class InMemoryDynamicPropertiesSource implements DynamicPropertiesSource { + public static final String SOURCE_NAME = "in-memory"; + + private static final Map DYNAMIC = new HashMap<>(); + + @Override + public PropertySource create(Environment environment) { + return new MapPropertySource(SOURCE_NAME, DYNAMIC); + } + + @Override + public int getOrder() { + return -100; + } + + public static void update(String key, Object value) { + DYNAMIC.put(key, value); + + HashMap updated = new HashMap<>(); + updated.put(key, value); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + } + + public static void reset() { + DYNAMIC.clear(); + } +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/LastPropertyPlaceholderConfigurer.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/LastPropertyPlaceholderConfigurer.java deleted file mode 100644 index 769582fa6e7..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/LastPropertyPlaceholderConfigurer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.config; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanFactoryPostProcessor; -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.core.Ordered; -import org.springframework.stereotype.Component; - -// do not implements PriorityOrdered, must be Ordered -// because this bean must run after PropertyPlaceholderConfigurer -// this class's purpose: when asked to resolve placeholder, then throw exception directly -@Component -public class LastPropertyPlaceholderConfigurer implements BeanFactoryPostProcessor, Ordered { - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { - new PropertySourcesPlaceholderConfigurer().postProcessBeanFactory(beanFactory); - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/YAMLUtil.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/YAMLUtil.java index fc0de9c0719..2dc116a304b 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/YAMLUtil.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/YAMLUtil.java @@ -17,31 +17,25 @@ package org.apache.servicecomb.config; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_CSE_PREFIX; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_SERVICECOMB_PREFIX; - import java.io.InputStream; import java.util.LinkedHashMap; import java.util.Map; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; import org.yaml.snakeyaml.constructor.SafeConstructor; -/** - * Created by on 2017/1/5. - */ public final class YAMLUtil { - private static final Yaml SAFE_PARSER = new Yaml(new SafeConstructor()); - - private static final Logger LOGGER = LoggerFactory.getLogger(YAMLUtil.class); - private YAMLUtil() { } + private static Yaml safeParser() { + // Yaml instance is not thread safe, create a new instance for each parser + return new Yaml(new SafeConstructor(new LoaderOptions())); + } + /** * load a input {@link InputStream} to be a map {@link Map}, you have to close the inputStream by yourself, such as:
*

try (InputStream in = url.openStream()) {
@@ -54,16 +48,32 @@ private YAMLUtil() { @SuppressWarnings("unchecked") public static Map yaml2Properties(InputStream input) { Map configurations = new LinkedHashMap<>(); - SAFE_PARSER.loadAll(input).forEach(data -> { - if (data instanceof Map) { + safeParser().loadAll(input).forEach(data -> { + if (data instanceof Map && isValidMap((Map) data)) { configurations.putAll(retrieveItems("", (Map) data)); } else { - LOGGER.warn("input cannot be convert to map"); + throw new IllegalArgumentException("input cannot be convert to map"); } }); return configurations; } + @SuppressWarnings("unchecked") + private static boolean isValidMap(Map data) { + for (Map.Entry entry : data.entrySet()) { + Object key = entry.getKey(); + Object value = entry.getValue(); + if (key instanceof String) { + if (value instanceof Map) { + return isValidMap((Map) value); + } + continue; + } + return false; + } + return true; + } + /** * load a input {@link String} to be a map {@link Map} * @param input the String to be loaded @@ -72,37 +82,33 @@ public static Map yaml2Properties(InputStream input) { @SuppressWarnings("unchecked") public static Map yaml2Properties(String input) { Map configurations = new LinkedHashMap<>(); - SAFE_PARSER.loadAll(input).forEach(data -> { - if (data instanceof Map) { + safeParser().loadAll(input).forEach(data -> { + if (data instanceof Map && isValidMap((Map) data)) { configurations.putAll(retrieveItems("", (Map) data)); } else { - LOGGER.warn("input cannot be convert to map"); + throw new IllegalArgumentException("input cannot be convert to map"); } }); return configurations; } public static T parserObject(String yamlContent, Class clazz) { - Yaml parser = new Yaml(new Constructor(new TypeDescription(clazz, clazz))); + Yaml parser = new Yaml(new Constructor(new TypeDescription(clazz, clazz), new LoaderOptions())); return parser.loadAs(yamlContent, clazz); } @SuppressWarnings("unchecked") - public static Map retrieveItems(String prefix, Map propertieMap) { + public static Map retrieveItems(String prefix, Map propertiesMap) { Map result = new LinkedHashMap<>(); if (!prefix.isEmpty()) { prefix += "."; } - for (Map.Entry entry : propertieMap.entrySet()) { + for (Map.Entry entry : propertiesMap.entrySet()) { if (entry.getValue() instanceof Map) { result.putAll(retrieveItems(prefix + entry.getKey(), (Map) entry.getValue())); } else { String key = prefix + entry.getKey(); - if (key.startsWith(CONFIG_CSE_PREFIX)) { - String servicecombKey = CONFIG_SERVICECOMB_PREFIX + key.substring(key.indexOf(".") + 1); - result.put(servicecombKey, entry.getValue()); - } result.put(key, entry.getValue()); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/scheduler/NeverStartPollingScheduler.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/scheduler/NeverStartPollingScheduler.java deleted file mode 100644 index fb52d066385..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/scheduler/NeverStartPollingScheduler.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.config.archaius.scheduler; - -import com.netflix.config.AbstractPollingScheduler; - -/** - * Created by on 2017/3/29. - */ -public class NeverStartPollingScheduler extends AbstractPollingScheduler { - @Override - protected void schedule(Runnable runnable) { - return; - } - - @Override - public void stop() { - return; - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigSourceMaker.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigSourceMaker.java deleted file mode 100644 index f822e30d985..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigSourceMaker.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.config.archaius.sources; - -public class ConfigSourceMaker { - - public static MicroserviceConfigurationSource yamlConfigSource() { - MicroserviceConfigLoader loader = new MicroserviceConfigLoader(); - loader.loadAndSort(); - - return new MicroserviceConfigurationSource(loader.getConfigModels()); - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/MicroserviceConfigurationSource.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/MicroserviceConfigurationSource.java deleted file mode 100644 index e39c987a710..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/MicroserviceConfigurationSource.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.config.archaius.sources; - -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.config.YAMLUtil; - -import com.netflix.config.PollResult; -import com.netflix.config.PolledConfigurationSource; - -public class MicroserviceConfigurationSource implements PolledConfigurationSource { - private final List configModels; - - public MicroserviceConfigurationSource(List configModels) { - this.configModels = configModels; - } - - public List getConfigModels() { - return configModels; - } - - public PollResult poll(boolean b, Object o) throws Exception { - Map configurations = new LinkedHashMap<>(); - - for (ConfigModel configModel : configModels) { - configurations.putAll(YAMLUtil.retrieveItems("", configModel.getConfig())); - } - - return PollResult.createFull(configurations); - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/event/DynamicConfigurationChangedEvent.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/event/DynamicConfigurationChangedEvent.java deleted file mode 100644 index b466d219127..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/event/DynamicConfigurationChangedEvent.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.config.event; - -import com.netflix.config.WatchedUpdateResult; - -public class DynamicConfigurationChangedEvent { - private final WatchedUpdateResult event; - - public DynamicConfigurationChangedEvent(WatchedUpdateResult event) { - this.event = event; - } - - public WatchedUpdateResult getEvent() { - return this.event; - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/event/RefreshGovernanceConfigurationEvent.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/event/RefreshGovernanceConfigurationEvent.java deleted file mode 100644 index a3e1d799f17..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/event/RefreshGovernanceConfigurationEvent.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.config.event; - -import com.netflix.config.WatchedUpdateResult; - -public class RefreshGovernanceConfigurationEvent { - private final WatchedUpdateResult event; - - public RefreshGovernanceConfigurationEvent(WatchedUpdateResult event) { - this.event = event; - } - - public WatchedUpdateResult getEvent() { - return this.event; - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/AbstractConfigLoader.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/AbstractConfigLoader.java similarity index 97% rename from foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/AbstractConfigLoader.java rename to foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/AbstractConfigLoader.java index 46a9f374c1d..085afc8c7e5 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/AbstractConfigLoader.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/AbstractConfigLoader.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.config.archaius.sources; +package org.apache.servicecomb.config.file; import java.io.IOException; import java.net.URL; @@ -98,7 +98,7 @@ protected List findURLFromClassPath(String resourceName) throws IOException return urlList; } - private class ConfigModelWrapper { + private static class ConfigModelWrapper { ConfigModel model; int addOrder; diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigModel.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/ConfigModel.java similarity index 96% rename from foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigModel.java rename to foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/ConfigModel.java index bb702bf597e..41732f9ab71 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/ConfigModel.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/ConfigModel.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.config.archaius.sources; +package org.apache.servicecomb.config.file; import java.net.URL; import java.util.Map; diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/MicroserviceConfigLoader.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/MicroserviceConfigLoader.java similarity index 93% rename from foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/MicroserviceConfigLoader.java rename to foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/MicroserviceConfigLoader.java index f0229782739..f33f9cc237f 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/MicroserviceConfigLoader.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/MicroserviceConfigLoader.java @@ -15,15 +15,16 @@ * limitations under the License. */ -package org.apache.servicecomb.config.archaius.sources; +package org.apache.servicecomb.config.file; import java.io.IOException; import java.net.URL; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; + public class MicroserviceConfigLoader extends YAMLConfigLoader { private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceConfigLoader.class); @@ -52,8 +53,9 @@ public MicroserviceConfigLoader() { } public void loadAndSort() { + String configFileFromClasspath = null; try { - String configFileFromClasspath = + configFileFromClasspath = System.getProperty(DEFAULT_FILE_NAME) == null ? DEFAULT_CONFIG_FILE_NAME : System.getProperty(DEFAULT_FILE_NAME); super.load(configFileFromClasspath); @@ -68,8 +70,8 @@ public void loadAndSort() { } sort(); - } catch (IOException e) { - throw new ServiceCombException("Failed to load microservice config", e); + } catch (Exception e) { + throw new ServiceCombException("Failed to load microservice configFile " + configFileFromClasspath, e); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/YAMLConfigLoader.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/YAMLConfigLoader.java similarity index 95% rename from foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/YAMLConfigLoader.java rename to foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/YAMLConfigLoader.java index f50451f6d86..ac69e8d4df0 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/archaius/sources/YAMLConfigLoader.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/file/YAMLConfigLoader.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.config.archaius.sources; +package org.apache.servicecomb.config.file; import java.io.IOException; import java.io.InputStream; diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/InjectBeanPostProcessor.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/InjectBeanPostProcessor.java index a5202504dbd..fbdeff42554 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/InjectBeanPostProcessor.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/InjectBeanPostProcessor.java @@ -23,9 +23,7 @@ import org.apache.servicecomb.foundation.common.utils.BeanUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; -import org.springframework.stereotype.Component; -@Component public class InjectBeanPostProcessor implements BeanPostProcessor { private final PriorityPropertyManager priorityPropertyManager; diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/PlaceholderResolver.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/PlaceholderResolver.java index 08614178e7a..b05ab11a73c 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/PlaceholderResolver.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/inject/PlaceholderResolver.java @@ -25,7 +25,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; /** *

@@ -86,10 +86,7 @@ public List replace(String str, Map parameters) {
       resolve(row, replaced);
     }
 
-    for (int idx = 0; idx < replaced.size(); idx++) {
-      String row = replaced.get(idx);
-      replaced.set(idx, row.replace("\\$", "$"));
-    }
+    replaced.replaceAll(s -> s.replace("\\$", "$"));
     return replaced;
   }
 
@@ -206,8 +203,8 @@ private void resolve(Row row, List resolvedRows) {
   private Object findValue(Map parameters, String key) {
     Object value = parameters.get(key);
     if (value == null) {
-      value = ConfigUtil.getProperty(key);
+      value = LegacyPropertyFactory.getStringProperty(key);
     }
     return value;
   }
-}
\ No newline at end of file
+}
diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java
index 4ce566525f6..fd572eaab55 100644
--- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java
+++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/parser/YamlParser.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.config.parser;
 
+import java.nio.charset.StandardCharsets;
 import java.util.Map;
 import java.util.Properties;
 
@@ -27,7 +28,7 @@ public class YamlParser implements Parser {
   @Override
   public Map parse(String content, String prefix, boolean addPrefix) {
     YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
-    yamlFactory.setResources(new ByteArrayResource(content.getBytes()));
+    yamlFactory.setResources(new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)));
     Properties properties = yamlFactory.getObject();
     return Parser.propertiesToMap(properties, prefix, addPrefix);
   }
diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/ConfigObjectFactory.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/ConfigObjectFactory.java
index 66fbf79170e..ff18b827e39 100644
--- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/ConfigObjectFactory.java
+++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/ConfigObjectFactory.java
@@ -16,8 +16,6 @@
  */
 package org.apache.servicecomb.config.priority;
 
-import static org.apache.servicecomb.foundation.common.utils.LambdaMetafactoryUtils.createObjectSetter;
-
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.List;
@@ -26,9 +24,10 @@
 import org.apache.servicecomb.config.inject.InjectProperties;
 import org.apache.servicecomb.config.inject.InjectProperty;
 import org.apache.servicecomb.config.inject.PlaceholderResolver;
+import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.foundation.common.utils.LambdaMetafactoryUtils;
 import org.apache.servicecomb.foundation.common.utils.bean.Setter;
-import org.springframework.stereotype.Component;
 
 import com.fasterxml.jackson.databind.BeanDescription;
 import com.fasterxml.jackson.databind.JavaType;
@@ -42,10 +41,15 @@
  * ${} or ${not-exist-key} is valid key in archaius
* so this wrapper mechanism will not throw exception even can not find value by placeholder */ -@Component public class ConfigObjectFactory { private final PriorityPropertyFactory propertyFactory; + private final Map, JavaType> classCache = new ConcurrentHashMapEx<>(); + + private final Map javaTypeCache = new ConcurrentHashMapEx<>(); + + private final Map> beanDescriptionCache = new ConcurrentHashMapEx<>(); + public ConfigObjectFactory(PriorityPropertyFactory propertyFactory) { this.propertyFactory = propertyFactory; } @@ -56,7 +60,7 @@ public PriorityPropertyFactory getPropertyFactory() { public ConfigObject create(Class cls, Map parameters) { try { - return create(cls.newInstance(), parameters); + return create(cls.getDeclaredConstructor().newInstance(), parameters); } catch (Throwable e) { throw new IllegalStateException("create config object failed, class=" + cls.getName(), e); } @@ -84,8 +88,9 @@ private String initPrefix(Class cls) { public List createProperties(Object instance, String prefix, Map parameters) { List properties = new ArrayList<>(); - JavaType javaType = TypeFactory.defaultInstance().constructType(instance.getClass()); - BeanDescription beanDescription = JsonUtils.OBJ_MAPPER.getSerializationConfig().introspect(javaType); + JavaType javaType = classCache.computeIfAbsent(instance.getClass(), TypeFactory.defaultInstance()::constructType); + BeanDescription beanDescription = javaTypeCache.computeIfAbsent(javaType, + JsonUtils.OBJ_MAPPER.getSerializationConfig()::introspect); for (BeanPropertyDefinition propertyDefinition : beanDescription.findProperties()) { if (propertyDefinition.getField() == null) { continue; @@ -95,9 +100,13 @@ public List createProperties(Object instance, String prefi continue; } - Setter setter = createObjectSetter(propertyDefinition); PriorityProperty priorityProperty = createPriorityProperty(propertyDefinition.getField().getAnnotated(), prefix, parameters); + if (priorityProperty == null) { + continue; + } + Setter setter = beanDescriptionCache.computeIfAbsent(propertyDefinition, + LambdaMetafactoryUtils::createObjectSetter); setter.set(instance, priorityProperty.getValue()); properties.add(new ConfigObjectProperty(setter, priorityProperty)); } @@ -131,9 +140,9 @@ private PriorityProperty createPriorityProperty(Field field, String prefix, M return createBooleanProperty(field, keys, false); case "java.lang.Boolean": return createBooleanProperty(field, keys, null); + default: + return null; } - - throw new IllegalStateException("not support, field=" + field); } private PriorityProperty createStringProperty(Field field, String[] keys) { @@ -225,4 +234,4 @@ private String[] collectPropertyKeys(Field field, String prefix, Map setter, PriorityProperty p this.property = property; } - public void updateValueWhenChanged(Object instance, @Nullable String changedKey) { + public void updateValueWhenChanged(Object instance, String changedKey) { if (property.isChangedKey(changedKey)) { + property.updateValue(); setter.set(instance, property.getValue()); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/DynamicProperty.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/DynamicProperty.java new file mode 100644 index 00000000000..48588b6ec04 --- /dev/null +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/DynamicProperty.java @@ -0,0 +1,58 @@ +/* + * 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.config.priority; + +import org.springframework.core.env.Environment; + +public class DynamicProperty { + private final Environment environment; + + private final String propName; + + public DynamicProperty(Environment environment, String propName) { + this.environment = environment; + this.propName = propName; + } + + public Integer getInteger() { + return environment.getProperty(propName, Integer.class); + } + + public Long getLong() { + return environment.getProperty(propName, Long.class); + } + + public String getString() { + return environment.getProperty(propName); + } + + public Boolean getBoolean() { + return environment.getProperty(propName, Boolean.class); + } + + public Double getDouble() { + return environment.getProperty(propName, Double.class); + } + + public Float getFloat() { + return environment.getProperty(propName, Float.class); + } + + public String getName() { + return propName; + } +} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java index 3af93c84c1d..c1c30896159 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityProperty.java @@ -23,15 +23,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicProperty; +import org.springframework.core.env.Environment; /** * must create by PriorityPropertyManager
* or register to PriorityPropertyManager manually * @param */ -public class PriorityProperty { +public final class PriorityProperty { private static final Logger LOGGER = LoggerFactory.getLogger(PriorityProperty.class); private final PriorityPropertyType propertyType; @@ -44,19 +43,19 @@ public class PriorityProperty { private T finalValue; - public PriorityProperty(PriorityPropertyType propertyType) { + public PriorityProperty(Environment environment, PriorityPropertyType propertyType) { this.propertyType = propertyType; this.joinedPriorityKeys = Arrays.toString(propertyType.getPriorityKeys()); this.internalValueReader = collectReader(propertyType.getType()); - this.properties = createProperties(propertyType.getPriorityKeys()); + this.properties = createProperties(environment, propertyType.getPriorityKeys()); initValue(); } - private DynamicProperty[] createProperties(String[] priorityKeys) { + private DynamicProperty[] createProperties(Environment environment, String[] priorityKeys) { DynamicProperty[] properties = new DynamicProperty[priorityKeys.length]; for (int idx = 0; idx < priorityKeys.length; idx++) { String key = priorityKeys[idx].trim(); - properties[idx] = DynamicProperty.getInstance(key); + properties[idx] = new DynamicProperty(environment, key); } return properties; } @@ -90,32 +89,32 @@ private Function collectReader(Type type) { } @SuppressWarnings("unchecked") - protected T readInt(DynamicProperty property) { + private T readInt(DynamicProperty property) { return (T) property.getInteger(); } @SuppressWarnings("unchecked") - protected T readLong(DynamicProperty property) { + private T readLong(DynamicProperty property) { return (T) property.getLong(); } @SuppressWarnings("unchecked") - protected T readString(DynamicProperty property) { + private T readString(DynamicProperty property) { return (T) property.getString(); } @SuppressWarnings("unchecked") - protected T readBoolean(DynamicProperty property) { + private T readBoolean(DynamicProperty property) { return (T) property.getBoolean(); } @SuppressWarnings("unchecked") - protected T readDouble(DynamicProperty property) { + private T readDouble(DynamicProperty property) { return (T) property.getDouble(); } @SuppressWarnings("unchecked") - protected T readFloat(DynamicProperty property) { + private T readFloat(DynamicProperty property) { return (T) property.getFloat(); } @@ -192,7 +191,7 @@ public boolean isChangedKey(String changedKey) { return true; } } - + return false; } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyFactory.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyFactory.java index f3ec2a72e63..abd43f8d404 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyFactory.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyFactory.java @@ -21,53 +21,29 @@ import java.util.Map; import java.util.stream.Stream; -import javax.annotation.PreDestroy; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.configuration.event.ConfigurationEvent; -import org.apache.commons.configuration.event.ConfigurationListener; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.springframework.stereotype.Component; +import org.springframework.core.env.Environment; -import com.netflix.config.ConfigurationManager; +import com.google.common.annotations.VisibleForTesting; -@Component public class PriorityPropertyFactory { - private final AbstractConfiguration configuration; - - private final ConfigurationListener configurationListener = this::configurationListener; - - // same to com.netflix.config.DynamicProperty.ALL_PROPS - // the set is finite - // will not cause OOM exception private final Map, PriorityProperty> properties = new ConcurrentHashMapEx<>(); - public PriorityPropertyFactory() { - this.configuration = ConfigurationManager.getConfigInstance(); - this.configuration.addConfigurationListener(configurationListener); - } + private final Environment environment; - @PreDestroy - public void onDestroy() { - this.configuration.removeConfigurationListener(configurationListener); + public PriorityPropertyFactory(Environment environment) { + this.environment = environment; } + @VisibleForTesting public Stream> getProperties() { return properties.values().stream(); } - private void configurationListener(ConfigurationEvent event) { - if (event.isBeforeUpdate()) { - return; - } - - // just update all properties, it's very fast, no need to do any optimize - getProperties().forEach(PriorityProperty::updateValue); - } - @SuppressWarnings("unchecked") public PriorityProperty getOrCreate(Type type, T invalidValue, T defaultValue, String... priorityKeys) { PriorityPropertyType propertyType = new PriorityPropertyType<>(type, invalidValue, defaultValue, priorityKeys); - return (PriorityProperty) properties.computeIfAbsent(propertyType, PriorityProperty::new); + return (PriorityProperty) properties.computeIfAbsent(propertyType, + key -> new PriorityProperty<>(environment, key)); } } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java index 15a1b5bcf66..8ed1e7dea2e 100644 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java +++ b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/priority/PriorityPropertyManager.java @@ -24,19 +24,13 @@ import java.util.Map.Entry; import java.util.WeakHashMap; -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.configuration.event.ConfigurationEvent; -import org.apache.commons.configuration.event.ConfigurationListener; -import org.springframework.stereotype.Component; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.foundation.common.event.EventManager; -import com.netflix.config.ConfigurationManager; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.eventbus.Subscribe; -@Component public class PriorityPropertyManager { - private final AbstractConfiguration configuration; - - private final ConfigurationListener configurationListener = this::configurationListener; - private final ConfigObjectFactory configObjectFactory; // key is config object instance @@ -44,10 +38,8 @@ public class PriorityPropertyManager { private final Map> configObjectMap = synchronizedMap(new WeakHashMap<>()); public PriorityPropertyManager(ConfigObjectFactory configObjectFactory) { - this.configuration = ConfigurationManager.getConfigInstance(); - this.configuration.addConfigurationListener(configurationListener); - this.configObjectFactory = configObjectFactory; + EventManager.register(this); } public PriorityPropertyFactory getPropertyFactory() { @@ -55,23 +47,24 @@ public PriorityPropertyFactory getPropertyFactory() { } public void close() { - configuration.removeConfigurationListener(configurationListener); - } - public synchronized void configurationListener(ConfigurationEvent event) { - if (event.isBeforeUpdate()) { - return; - } + } + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { // just loop all properties, it's very fast, no need to do any optimize for (Entry> entry : configObjectMap.entrySet()) { Object instance = entry.getKey(); - entry.getValue() - .forEach( - configObjectProperty -> configObjectProperty.updateValueWhenChanged(instance, event.getPropertyName())); + entry.getValue().forEach( + configObjectProperty -> { + for (String updatedKey : event.getChanged()) { + configObjectProperty.updateValueWhenChanged(instance, updatedKey); + } + }); } } + @VisibleForTesting public Map> getConfigObjectMap() { return configObjectMap; } diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/spi/ConfigCenterConfigurationSource.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/spi/ConfigCenterConfigurationSource.java deleted file mode 100644 index 604e7f8b3f0..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/spi/ConfigCenterConfigurationSource.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.config.spi; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.foundation.common.utils.SPIOrder; - -import com.netflix.config.WatchedConfigurationSource; - -public interface ConfigCenterConfigurationSource extends WatchedConfigurationSource, SPIOrder { - int ORDER_BASE = 100; - - boolean isValidSource(Configuration localConfiguration); - - void init(Configuration localConfiguration); - - default void destroy() { - - } -} diff --git a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/spi/ConfigCenterConfigurationSourceLoader.java b/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/spi/ConfigCenterConfigurationSourceLoader.java deleted file mode 100644 index 053bfde9c19..00000000000 --- a/foundations/foundation-config/src/main/java/org/apache/servicecomb/config/spi/ConfigCenterConfigurationSourceLoader.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.config.spi; - -import java.util.List; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; - -public class ConfigCenterConfigurationSourceLoader { - private static List configCenterConfigurationSources = - SPIServiceUtils.getSortedService(ConfigCenterConfigurationSource.class); - - public static ConfigCenterConfigurationSource getConfigCenterConfigurationSource(Configuration localConfiguration) { - - ConfigCenterConfigurationSource configCenterConfigurationSource = null; - - for (ConfigCenterConfigurationSource item : configCenterConfigurationSources) { - if (item.isValidSource(localConfiguration)) { - configCenterConfigurationSource = item; - break; - } - } - - return configCenterConfigurationSource; - } -} diff --git a/foundations/foundation-config/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource b/foundations/foundation-config/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource new file mode 100644 index 00000000000..1f148e651eb --- /dev/null +++ b/foundations/foundation-config/src/main/resources/META-INF/services/org.apache.servicecomb.config.DynamicPropertiesSource @@ -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.servicecomb.config.InMemoryDynamicPropertiesSource diff --git a/spring-boot/spring-boot-starters/java-chassis-spring-boot-starter/src/main/resources/META-INF/spring.factories b/foundations/foundation-config/src/main/resources/META-INF/spring.factories similarity index 85% rename from spring-boot/spring-boot-starters/java-chassis-spring-boot-starter/src/main/resources/META-INF/spring.factories rename to foundations/foundation-config/src/main/resources/META-INF/spring.factories index 8874ae75515..1654b618370 100644 --- a/spring-boot/spring-boot-starters/java-chassis-spring-boot-starter/src/main/resources/META-INF/spring.factories +++ b/foundations/foundation-config/src/main/resources/META-INF/spring.factories @@ -14,4 +14,5 @@ # See the License for the specific language governing permissions and # limitations under the License. # -org.springframework.boot.env.EnvironmentPostProcessor=org.apache.servicecomb.springboot2.starter.ConfigurationSpringBootInitializer \ No newline at end of file +org.springframework.boot.env.EnvironmentPostProcessor=\ + org.apache.servicecomb.config.ConfigEnvironmentPostProcessor diff --git a/foundations/foundation-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/foundations/foundation-config/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..5d39e597fdc --- /dev/null +++ b/foundations/foundation-config/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.servicecomb.config.FoundationConfigConfiguration diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/BootStrapPropertiesTest.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/BootStrapPropertiesTest.java index 488546a045f..38a8a4a8b5d 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/BootStrapPropertiesTest.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/BootStrapPropertiesTest.java @@ -21,16 +21,28 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.Map; +import java.util.Map.Entry; -import org.apache.commons.configuration.MapConfiguration; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; -class BootStrapPropertiesTest { +public class BootStrapPropertiesTest { private Map readInstanceProperties(String yaml) { Map properties = YAMLUtil.yaml2Properties(yaml); - MapConfiguration configuration = new MapConfiguration(properties); + ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + MapPropertySource propertySource = new MapPropertySource("yaml", properties); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); - return BootStrapProperties.readServiceInstanceProperties(configuration); + for (Entry entry : properties.entrySet()) { + Mockito.when(environment.getProperty(entry.getKey())).thenReturn(entry.getValue().toString()); + } + + return BootStrapProperties.readServiceInstanceProperties(environment); } @Test @@ -42,107 +54,62 @@ void should_be_empty_when_old_and_new_key_not_exists() { @Test void should_read_boolean_to_string() { - Map properties = readInstanceProperties("" - + "servicecomb:\n" - + " instance:\n" - + " properties:\n" - + " k: true"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"true\"\n" - + "}"); + Map properties = readInstanceProperties(""" + servicecomb: + instance: + properties: + k: true"""); + + assertPrettyJson(properties).isEqualTo(""" + { + "k" : "true" + }"""); } @Test void should_read_number_to_string() { - Map properties = readInstanceProperties("" - + "servicecomb:\n" - + " instance:\n" - + " properties:\n" - + " k: 1"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"1\"\n" - + "}"); - } - - @Test - void should_resolve_placeholder_for_instance_properties() { - Map properties = readInstanceProperties("" - + "k1: new\n" - + "servicecomb:\n" - + " instance:\n" - + " properties:\n" - + " k: ${k1}"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"new\"\n" - + "}"); - } - - @Test - void should_resolve_boolean_to_string() { - Map properties = readInstanceProperties("" - + "k: true\n" - + "servicecomb:\n" - + " instance:\n" - + " properties:\n" - + " k: ${k}"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"true\"\n" - + "}"); - } - - @Test - void should_resolve_number_to_string() { - Map properties = readInstanceProperties("" - + "k: 1\n" - + "servicecomb:\n" - + " instance:\n" - + " properties:\n" - + " k: ${k}"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"1\"\n" - + "}"); + Map properties = readInstanceProperties(""" + servicecomb: + instance: + properties: + k: 1"""); + + assertPrettyJson(properties).isEqualTo(""" + { + "k" : "1" + }"""); } @Test void should_read_by_old_prefix_when_new_prefix_not_exists() { - Map properties = readInstanceProperties("" - + "instance_description:\n" - + " properties:\n" - + " k: v\n" - + " k1: v1"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"v\",\n" - + " \"k1\" : \"v1\"\n" - + "}"); + Map properties = readInstanceProperties(""" + instance_description: + properties: + k: v + k1: v1"""); + + assertPrettyJson(properties).isEqualTo(""" + { + "k1" : "v1", + "k" : "v" + }"""); } @Test void should_ignore_old_prefix_when_new_prefix_exists() { - Map properties = readInstanceProperties("" - + "instance_description:\n" - + " properties:\n" - + " k: v\n" - + " k1: v1\n" - + "servicecomb:\n" - + " instance:\n" - + " properties:\n" - + " k: new"); - - assertPrettyJson(properties).isEqualTo("" - + "{\n" - + " \"k\" : \"new\"\n" - + "}"); + Map properties = readInstanceProperties(""" + instance_description: + properties: + k: v + k1: v1 + servicecomb: + instance: + properties: + k: new"""); + + assertPrettyJson(properties).isEqualTo(""" + { + "k" : "new" + }"""); } -} \ No newline at end of file +} diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/DynamicPropertiesTest.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/DynamicPropertiesTest.java index 9090a64ae8f..3f72af9b2cb 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/DynamicPropertiesTest.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/DynamicPropertiesTest.java @@ -23,22 +23,20 @@ import static org.hamcrest.core.Is.is; import static org.hamcrest.number.IsCloseTo.closeTo; +import java.util.HashMap; import java.util.Objects; +import org.apache.servicecomb.foundation.common.event.EventManager; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import com.netflix.config.ConcurrentMapConfiguration; -import com.netflix.config.ConfigurationManager; -import com.netflix.config.DynamicPropertyFactory; import com.seanyinx.github.unit.scaffolding.Poller; import com.seanyinx.github.unit.scaffolding.Randomness; -import mockit.Deencapsulation; - public class DynamicPropertiesTest { - private static final String stringPropertyName = uniquify("stringPropertyName"); private static final String intPropertyName = uniquify("intPropertyName"); @@ -57,7 +55,7 @@ public class DynamicPropertiesTest { private static final long longOldValue = Randomness.nextLong(); - private static final double floatOldValue = Randomness.nextDouble(); + private static final float floatOldValue = Double.valueOf(Randomness.nextDouble()).floatValue(); private static final double doubleOldValue = Randomness.nextDouble(); @@ -65,9 +63,9 @@ public class DynamicPropertiesTest { private static final double ERROR = 0.0000001; - private static DynamicProperties dynamicProperties; + private static Environment environment; - private static ConcurrentMapConfiguration configuration; + private static DynamicProperties dynamicProperties; private final Poller poller = new Poller(2000, 100); @@ -86,26 +84,24 @@ public class DynamicPropertiesTest { @BeforeClass public static void setUpClass() throws Exception { - tearDown(); - configuration = new ConcurrentMapConfiguration(); + environment = Mockito.mock(Environment.class); writeInitialConfig(); - dynamicProperties = new DynamicPropertiesImpl(configuration); + dynamicProperties = new DynamicPropertiesImpl(environment); } @AfterClass public static void tearDown() throws Exception { - Deencapsulation.setField(ConfigurationManager.class, "instance", null); - Deencapsulation.setField(ConfigurationManager.class, "customConfigurationInstalled", false); - Deencapsulation.setField(DynamicPropertyFactory.class, "config", null); + } private static void writeInitialConfig() throws Exception { - configuration.setProperty(stringPropertyName, stringOldValue); - configuration.setProperty(intPropertyName, String.valueOf(intOldValue)); - configuration.setProperty(longPropertyName, String.valueOf(longOldValue)); - configuration.setProperty(floatPropertyName, String.valueOf(floatOldValue)); - configuration.setProperty(doublePropertyName, String.valueOf(doubleOldValue)); - configuration.setProperty(booleanPropertyName, String.valueOf(booleanOldValue)); + Mockito.when(environment.getProperty(stringPropertyName, (String) null)).thenReturn(stringOldValue); + Mockito.when(environment.getProperty(intPropertyName, int.class, 0)).thenReturn(intOldValue); + Mockito.when(environment.getProperty(longPropertyName, long.class, 0L)).thenReturn(longOldValue); + Mockito.when(environment.getProperty(floatPropertyName, float.class, 0F)).thenReturn(floatOldValue); + Mockito.when(environment.getProperty(doublePropertyName, double.class, 0D)).thenReturn(doubleOldValue); + Mockito.when(environment.getProperty(booleanPropertyName, boolean.class, false)) + .thenReturn(booleanOldValue); } @Test @@ -118,7 +114,10 @@ public void observesSpecifiedStringProperty() throws Exception { String newValue = uniquify("newValue"); - configuration.setProperty(stringPropertyName, newValue); + Mockito.when(environment.getProperty(stringPropertyName, (String) null)).thenReturn(newValue); + HashMap updated = new HashMap<>(); + updated.put(stringPropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); poller.assertEventually(() -> Objects.equals(stringPropertyValue, newValue)); } @@ -133,24 +132,37 @@ public void observesSpecifiedIntProperty() throws Exception { int newValue = Randomness.nextInt(); - configuration.setProperty(intPropertyName, String.valueOf(newValue)); + Mockito.when(environment.getProperty(intPropertyName, Integer.class, 0)).thenReturn(newValue); + HashMap updated = new HashMap<>(); + updated.put(intPropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); poller.assertEventually(() -> intPropertyValue == newValue); } @Test public void observesSpecifiedLongProperty() throws Exception { + Mockito.when(environment.getProperty(longPropertyName, long.class, 3L)).thenReturn(longOldValue); + long property = dynamicProperties.getLongProperty(longPropertyName, 0); assertThat(property, is(longOldValue)); - property = dynamicProperties.getLongProperty(longPropertyName, value -> longPropertyValue = value, 0); + property = dynamicProperties.getLongProperty(longPropertyName, value -> longPropertyValue = value, 3L); assertThat(property, is(longOldValue)); long newValue = Randomness.nextLong(); - configuration.setProperty(longPropertyName, String.valueOf(newValue)); + Mockito.when(environment.getProperty(longPropertyName, Long.class, 3L)).thenReturn(newValue); + HashMap updated = new HashMap<>(); + updated.put(longPropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); - poller.assertEventually(() -> longPropertyValue == newValue); + Mockito.when(environment.getProperty(longPropertyName, Long.class, 3L)).thenReturn(3L); + HashMap deleted = new HashMap<>(); + deleted.put(longPropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(new HashMap<>(), new HashMap<>(), deleted)); + + poller.assertEventually(() -> longPropertyValue == 3L); } @Test @@ -158,12 +170,15 @@ public void observesSpecifiedFloatProperty() throws Exception { double property = dynamicProperties.getFloatProperty(floatPropertyName, 0); assertThat(property, closeTo(floatOldValue, ERROR)); - property = dynamicProperties.getFloatProperty(floatPropertyName, value -> floatPropertyValue = value, 0); + property = dynamicProperties.getFloatProperty(floatPropertyName, value -> floatPropertyValue = value, 0f); assertThat(property, closeTo(floatOldValue, ERROR)); - double newValue = Randomness.nextDouble(); + float newValue = Double.valueOf(Randomness.nextDouble()).floatValue(); - configuration.setProperty(floatPropertyName, String.valueOf(newValue)); + Mockito.when(environment.getProperty(floatPropertyName, Float.class, 0f)).thenReturn(newValue); + HashMap updated = new HashMap<>(); + updated.put(floatPropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); poller.assertEventually(() -> Math.abs(floatPropertyValue - newValue) < ERROR); } @@ -173,12 +188,15 @@ public void observesSpecifiedDoubleProperty() throws Exception { double property = dynamicProperties.getDoubleProperty(doublePropertyName, 0); assertThat(property, closeTo(doubleOldValue, ERROR)); - property = dynamicProperties.getDoubleProperty(doublePropertyName, value -> doublePropertyValue = value, 0); + property = dynamicProperties.getDoubleProperty(doublePropertyName, value -> doublePropertyValue = value, 0d); assertThat(property, closeTo(doubleOldValue, ERROR)); double newValue = Randomness.nextDouble(); - configuration.setProperty(doublePropertyName, String.valueOf(newValue)); + Mockito.when(environment.getProperty(doublePropertyName, Double.class, 0d)).thenReturn(newValue); + HashMap updated = new HashMap<>(); + updated.put(doublePropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); poller.assertEventually(() -> Math.abs(doublePropertyValue - newValue) < ERROR); } @@ -196,7 +214,10 @@ public void observesSpecifiedBooleanProperty() throws Exception { boolean newValue = !booleanOldValue; - configuration.setProperty(booleanPropertyName, String.valueOf(newValue)); + Mockito.when(environment.getProperty(booleanPropertyName, Boolean.class, booleanOldValue)).thenReturn(newValue); + HashMap updated = new HashMap<>(); + updated.put(booleanPropertyName, newValue); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); poller.assertEventually(() -> booleanPropertyValue == newValue); } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/MapBasedConfigurationSource.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/MapBasedConfigurationSource.java deleted file mode 100644 index 5f08c8a8905..00000000000 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/MapBasedConfigurationSource.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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.config; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; - -import com.netflix.config.WatchedUpdateListener; -import com.netflix.config.WatchedUpdateResult; - -public class MapBasedConfigurationSource implements ConfigCenterConfigurationSource { - - private static final Map properties = new ConcurrentHashMap<>(); - - private static final Set listeners = new HashSet<>(); - - static { - properties.put("servicecomb.abc.key", "xyz"); - } - - @Override - public boolean isValidSource(Configuration localConfiguration) { - if (localConfiguration.getProperty("cse.config.client.serverUri") == null) { - return false; - } - return true; - } - - @Override - public void init(Configuration localConfiguration) { - - } - - @Override - public void addUpdateListener(WatchedUpdateListener listener) { - listeners.add(listener); - } - - @Override - public void removeUpdateListener(WatchedUpdateListener listener) { - listeners.remove(listener); - } - - @Override - public Map getCurrentData() throws Exception { - return properties; - } - - void addProperty(String property, Object value) { - properties.put(property, value); - - Map adds = new HashMap<>(); - adds.put(property, value); - - listeners.forEach( - listener -> listener.updateConfiguration(WatchedUpdateResult.createIncremental(adds, null, null))); - } - - void setProperty(String property, Object value) { - properties.replace(property, value); - - Map changeds = new HashMap<>(); - changeds.put(property, value); - - listeners.forEach(listener -> listener - .updateConfiguration(WatchedUpdateResult.createIncremental(null, changeds, null))); - } - - void deleteProperty(String property) { - properties.remove(property); - - Map deletes = new HashMap<>(); - deletes.put(property, null); - - listeners.forEach( - listener -> listener.updateConfiguration(WatchedUpdateResult.createIncremental(null, null, deletes))); - } - - public Map getProperties() { - return properties; - } -} diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigMapping.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigMapping.java index ff1601e965c..1da5a2f5938 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigMapping.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigMapping.java @@ -17,24 +17,22 @@ package org.apache.servicecomb.config; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - import java.util.List; import java.util.Map; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestConfigMapping { @Test public void testMapping() { List value = ConfigMapping.map("SERVICECOMB_ENV"); - assertEquals(2, value.size()); - assertEquals("service_description.environment", value.get(0)); - assertEquals("service_description.environment.old", value.get(1)); + Assertions.assertEquals(2, value.size()); + Assertions.assertEquals("service_description.environment", value.get(0)); + Assertions.assertEquals("service_description.environment.old", value.get(1)); Map m = ConfigMapping.getMapping(); - assertNotNull(m); + Assertions.assertNotNull(m); } @Test @@ -42,7 +40,7 @@ public void testConvertedMap() { String value = ConfigMapping.map("CSE_ENV_MAPPING"); Map m = ConfigMapping.getMapping(); Map m1 = ConfigMapping.getConvertedMap(m); - assertEquals("servicecomb.testmapping.key", value); - assertNotNull(m1); + Assertions.assertEquals("servicecomb.testmapping.key", value); + Assertions.assertNotNull(m1); } } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java deleted file mode 100644 index e220bc615dc..00000000000 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestConfigUtil.java +++ /dev/null @@ -1,380 +0,0 @@ -/* - * 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.config; - -import static com.seanyinx.github.unit.scaffolding.Randomness.uniquify; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertThat; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicConfiguration; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.DynamicWatchedConfiguration; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; - -public class TestConfigUtil { - private static final String systemPropertyName = "servicecomb.cse.servicecomb.system.setting"; - - private static final String systemExpected = uniquify("ran"); - - private static final String environmentPropertyName = "servicecomb.cse.servicecomb.environment.setting"; - - private static final String environmentExpected = uniquify("ran"); - - private final MapBasedConfigurationSource configurationSource = new MapBasedConfigurationSource(); - - @BeforeClass - public static void beforeTest() { - Logger.getRootLogger().setLevel(Level.OFF); - - ArchaiusUtils.resetConfig(); - - System.setProperty(systemPropertyName, systemExpected); - try { - setEnv(environmentPropertyName, environmentExpected); - setEnv("MY_SERVICES_ENDPOINT", "https://myhost:8888"); - } catch (Exception e) { - throw new IllegalStateException(e); - } - - ConfigUtil.installDynamicConfig(); - - Logger.getRootLogger().setLevel(Level.INFO); - } - - @AfterClass - public static void tearDown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testArrayData() { - Configuration configuration = ConfigUtil.createLocalConfig(); - Assert.assertEquals("a,b,c", configuration.getString("test.commonSeparatedString")); - Assert.assertEquals(1, configuration.getStringArray("test.commonSeparatedString").length); - Assert.assertEquals("a,b,c", configuration.getStringArray("test.commonSeparatedString")[0]); - - Assert.assertEquals("b,c,d", configuration.getString("test.commonSeparatedStringHolder")); - Assert.assertEquals(1, configuration.getStringArray("test.commonSeparatedStringHolder").length); - Assert.assertEquals("b,c,d", configuration.getStringArray("test.commonSeparatedStringHolder")[0]); - - Assert.assertEquals("m", configuration.getString("test.stringArray")); // first element - Assert.assertEquals(2, configuration.getStringArray("test.stringArray").length); - Assert.assertEquals("m", configuration.getStringArray("test.stringArray")[0]); - Assert.assertEquals("n", configuration.getStringArray("test.stringArray")[1]); - } - - @Test - public void testAddConfig() { - Map config = new HashMap<>(); - config.put("service_description.name", "service_name_test"); - ConfigUtil.setConfigs(config); - ConfigUtil.addConfig("service_description.version", "1.0.2"); - ConfigUtil.addConfig("cse.test.enabled", true); - ConfigUtil.addConfig("cse.test.num", 10); - AbstractConfiguration configuration = ConfigUtil.createLocalConfig(); - Assert.assertEquals(configuration.getString("service_description.name"), "service_name_test"); - Assert.assertTrue(configuration.getBoolean("cse.test.enabled")); - Assert.assertEquals(configuration.getInt("cse.test.num"), 10); - } - - @Test - public void testCreateDynamicConfigNoConfigCenterSPI() { - AbstractConfiguration dynamicConfig = ConfigUtil.createLocalConfig(); - Assert.assertNotEquals(DynamicWatchedConfiguration.class, - ((ConcurrentCompositeConfiguration) dynamicConfig).getConfiguration(0).getClass()); - } - - @Test - public void testGetPropertyInvalidConfig() { - Assert.assertNull(ConfigUtil.getProperty(null, "any")); - Assert.assertNull(ConfigUtil.getProperty(new Object(), "any")); - } - - @Test - public void propertiesFromFileIsDuplicatedToCse() { - String expected = "value"; - - assertThat(DynamicPropertyFactory - .getInstance() - .getStringProperty("cse.cse.servicecomb.file", null) - .get(), - equalTo(null)); - - assertThat(DynamicPropertyFactory - .getInstance() - .getStringProperty("servicecomb.cse.servicecomb.file", null) - .get(), - equalTo(expected)); - } - - @Test - public void propertiesFromSystemIsDuplicatedToCse() { - assertThat(DynamicPropertyFactory - .getInstance() - .getStringProperty(systemPropertyName, null) - .get(), - equalTo(systemExpected)); - - assertThat(DynamicPropertyFactory - .getInstance() - .getStringProperty("servicecomb.cse.servicecomb.system.setting", null) - .get(), - equalTo(systemExpected)); - } - - @Test - public void propertiesFromEnvironmentIsDuplicatedToCse() { - assertThat(DynamicPropertyFactory - .getInstance() - .getStringProperty(environmentPropertyName, null) - .get(), - equalTo(environmentExpected)); - - assertThat(DynamicPropertyFactory - .getInstance() - .getStringProperty("servicecomb.cse.servicecomb.environment.setting", null) - .get(), - equalTo(environmentExpected)); - } - - @Test - public void duplicateServiceCombConfigToCseListValue() { - List list = Arrays.asList("a", "b"); - - AbstractConfiguration config = new DynamicConfiguration(); - config.addProperty("cse.list", list); - Deencapsulation.invoke(ConfigUtil.class, "duplicateCseConfigToServicecomb", config); - - Object result = config.getProperty("servicecomb.list"); - assertThat(result, instanceOf(List.class)); - assertThat(result, equalTo(list)); - } - - @Test - public void propertiesAddFromDynamicConfigSourceIsDuplicated() { - String expected = uniquify("ran"); - String someProperty = "cse.cse.servicecomb.add"; - String injectProperty = "servicecomb.cse.servicecomb.add"; - - configurationSource.addProperty(someProperty, expected); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(expected)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(expected)); - - String changed = uniquify("changed"); - configurationSource.addProperty(someProperty, changed); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(changed)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(changed)); - - expected = uniquify("ran"); - someProperty = "cse.servicecomb.cse.add"; - injectProperty = "servicecomb.servicecomb.cse.add"; - - configurationSource.addProperty(someProperty, expected); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(expected)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(expected)); - - changed = uniquify("changed"); - configurationSource.addProperty(someProperty, changed); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(changed)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(changed)); - } - - @Test - public void propertiesChangeFromDynamicConfigSourceIsDuplicated() { - String expected = uniquify("ran"); - String someProperty = "cse.cse.servicecomb.change"; - String injectProperty = "servicecomb.cse.servicecomb.change"; - configurationSource.addProperty(someProperty, expected); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(expected)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(expected)); - - String changed = uniquify("changed"); - configurationSource.setProperty(someProperty, changed); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(changed)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(changed)); - - expected = uniquify("ran"); - someProperty = "cse.servicecomb.cse.change"; - injectProperty = "servicecomb.servicecomb.cse.change"; - configurationSource.addProperty(someProperty, expected); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(expected)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(expected)); - - changed = uniquify("changed"); - configurationSource.setProperty(someProperty, changed); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(changed)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(changed)); - } - - @Test - public void propertiesDeleteFromDynamicConfigSourceIsDuplicated() { - String expected = uniquify("ran"); - String someProperty = "cse.cse.servicecomb.delete"; - String injectProperty = "servicecomb.cse.servicecomb.delete"; - configurationSource.addProperty(someProperty, expected); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(expected)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(expected)); - - configurationSource.deleteProperty(someProperty); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(null)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(null)); - - expected = uniquify("ran"); - someProperty = "cse.servicecomb.cse.delete"; - injectProperty = "servicecomb.servicecomb.cse.delete"; - configurationSource.addProperty(someProperty, expected); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(expected)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(expected)); - - configurationSource.deleteProperty(someProperty); - - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(someProperty, null).get(), - equalTo(null)); - assertThat(DynamicPropertyFactory.getInstance().getStringProperty(injectProperty, null).get(), - equalTo(null)); - } - - @Test - public void testConvertEnvVariable() { - String someProperty = "cse_service_registry_address"; - AbstractConfiguration config = new DynamicConfiguration(); - config.addProperty(someProperty, "testing"); - AbstractConfiguration result = ConfigUtil.convertEnvVariable(config); - assertThat(result.getString("cse.service.registry.address"), equalTo("testing")); - assertThat(result.getString("cse_service_registry_address"), equalTo("testing")); - } - - @Test - public void testCreateLocalConfigWithExtraConfig() { - Map extraConfig = new ConcurrentHashMapEx<>(1); - String extraConfigKey = "extraConfigKey"; - String extraConfigValue = "value"; - String overriddenConfigKey = "servicecomb.cse.servicecomb.file"; - extraConfig.put(extraConfigKey, extraConfigValue); - final String propertyHigherPriority = "higher_priority"; - String mapedKey1 = "servicecomb.service.mapping.address"; - String mapedKey2 = "servicecomb.service1.mapping.address"; - extraConfig.put(overriddenConfigKey, propertyHigherPriority); - - ConfigUtil.addExtraConfig("testExtraConfig", extraConfig); - - ConcurrentCompositeConfiguration localConfiguration = ConfigUtil.createLocalConfig(); - - Assert.assertEquals(extraConfigValue, localConfiguration.getProperty(extraConfigKey)); - Assert.assertEquals(propertyHigherPriority, localConfiguration.getString(overriddenConfigKey)); - // Test mapping key/value from self mappfing.xml - Assert.assertEquals("https://myhost:8888", localConfiguration.getString(mapedKey1)); - Assert.assertEquals("https://myhost:8888", localConfiguration.getString(mapedKey2)); - } - - @SuppressWarnings("unchecked") - private static void setEnv(String key, String value) throws IllegalAccessException, NoSuchFieldException { - Class[] classes = Collections.class.getDeclaredClasses(); - Map env = System.getenv(); - for (Class cl : classes) { - if ("java.util.Collections$UnmodifiableMap" .equals(cl.getName())) { - Field field = cl.getDeclaredField("m"); - field.setAccessible(true); - Object obj = field.get(env); - Map map = (Map) obj; - map.put(key, value); - } - } - } - - @Test - public void destroyConfigCenterConfigurationSource() { - AtomicInteger count = new AtomicInteger(); - ConfigCenterConfigurationSource source = new MockUp() { - @Mock - void destroy() { - count.incrementAndGet(); - } - }.getMockInstance(); - - new Expectations(SPIServiceUtils.class) { - { - SPIServiceUtils.getAllService(ConfigCenterConfigurationSource.class); - result = Arrays.asList(source, source); - } - }; - - ConfigUtil.destroyConfigCenterConfigurationSource(); - - Assert.assertEquals(2, count.get()); - } -} diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestLastPropertyPlaceholderConfigurer.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestLastPropertyPlaceholderConfigurer.java deleted file mode 100644 index 223820c5b4c..00000000000 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestLastPropertyPlaceholderConfigurer.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.config; - -import java.io.IOException; -import java.util.Properties; - -import org.junit.Assert; -import org.junit.Test; -import org.springframework.context.EmbeddedValueResolverAware; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; -import org.springframework.stereotype.Component; -import org.springframework.util.StringValueResolver; - -public class TestLastPropertyPlaceholderConfigurer { - @Component - static class Bean extends PropertySourcesPlaceholderConfigurer implements EmbeddedValueResolverAware { - StringValueResolver resolver; - - public Bean() { - setIgnoreUnresolvablePlaceholders(true); - } - - @Override - public void setEmbeddedValueResolver(StringValueResolver resolver) { - this.resolver = resolver; - } - - @Override - protected Properties mergeProperties() throws IOException { - Properties properties = super.mergeProperties(); - properties.put("a", "aValue"); - return properties; - } - } - - @Test - public void test() { - AnnotationConfigApplicationContext context = - new AnnotationConfigApplicationContext(this.getClass().getPackage().getName()); - Bean bean = context.getBean(Bean.class); - - Assert.assertEquals("aValue", bean.resolver.resolveStringValue("${a}")); - try { - bean.resolver.resolveStringValue("${b}"); - Assert.fail("must throw exception"); - } catch (IllegalArgumentException e) { - Assert.assertEquals("Could not resolve placeholder 'b' in value \"${b}\"", e.getMessage()); - } - - context.close(); - } -} diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestYAMLUtil.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestYAMLUtil.java index ae63b9a2770..4abafe8765e 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestYAMLUtil.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/TestYAMLUtil.java @@ -19,8 +19,8 @@ import java.util.Map; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestYAMLUtil { public static class Person { @@ -50,28 +50,21 @@ public void setName(String name) { @Test public void testSafeParser() { Person person = YAMLUtil.parserObject("name: hello", Person.class); - Assert.assertEquals("hello", person.getName()); - - person = YAMLUtil.parserObject("!!org.apache.servicecomb.config.TestYAMLUtil$Person\n" - + "name: hello", Person.class); - Assert.assertEquals("hello", person.getName()); - - person = YAMLUtil.parserObject("!!org.apache.servicecomb.config.TestYAMLUtil$UnsafePerson\n" - + "name: hello", Person.class); - Assert.assertEquals("hello", person.getName()); + Assertions.assertEquals("hello", person.getName()); + } - // using Object.class is not safe, do not used in product code. - Object object = YAMLUtil.parserObject("!!org.apache.servicecomb.config.TestYAMLUtil$UnsafePerson\n" - + "name: hello", Object.class); - Assert.assertEquals("hello", ((UnsafePerson) object).getName()); + @Test + public void testYamlConfig() { + RuntimeException runtimeException = Assertions.assertThrows(RuntimeException.class, () -> YAMLUtil.yaml2Properties("servicecomb.service.registry.enabled: {{true}}")); + Assertions.assertEquals("input cannot be convert to map", runtimeException.getMessage()); } @Test @SuppressWarnings("unchecked") public void testListValue() { Map result = YAMLUtil.yaml2Properties("hello: a,b"); - Assert.assertEquals(result.size(), 1); + Assertions.assertEquals(result.size(), 1); String listValue = (String) result.get("hello"); - Assert.assertEquals(listValue, "a,b"); + Assertions.assertEquals(listValue, "a,b"); } } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/archaius/sources/TestYAMLConfigurationSource.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/archaius/sources/TestYAMLConfigurationSource.java deleted file mode 100644 index f04aa7d40be..00000000000 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/archaius/sources/TestYAMLConfigurationSource.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.config.archaius.sources; - -import static org.apache.servicecomb.config.archaius.sources.ConfigSourceMaker.yamlConfigSource; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.net.URL; -import java.util.List; -import java.util.Map; - -import org.apache.commons.configuration.SystemConfiguration; -import org.apache.servicecomb.config.archaius.scheduler.NeverStartPollingScheduler; -import org.junit.Assert; -import org.junit.Test; - -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.ConcurrentMapConfiguration; -import com.netflix.config.DynamicConfiguration; -import com.netflix.config.PollResult; - -/** - * Created by on 2017/1/5. - */ -public class TestYAMLConfigurationSource { - - @Test - public void testPullFromClassPath() throws Exception { - MicroserviceConfigurationSource configSource = yamlConfigSource(); - PollResult result = configSource.poll(true, null); - Map configMap = result.getComplete(); - assertNotNull(configMap); - assertEquals(29, configMap.size()); - assertNotNull(configMap.get("trace.handler.sampler.percent")); - assertEquals(0.5, configMap.get("trace.handler.sampler.percent")); - } - - @Test - public void testPullFroGivenURL() throws Exception { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - URL test1URL = loader.getResource("test1.yaml"); - URL test2URL = loader.getResource("test2.yaml"); - System.setProperty("servicecomb.configurationSource.additionalUrls", test1URL.toString() + "," + test2URL.toString()); - MicroserviceConfigurationSource configSource = yamlConfigSource(); - PollResult result = configSource.poll(true, null); - Map configMap = result.getComplete(); - - assertEquals(3, configSource.getConfigModels().size()); - assertNotNull(configMap); - assertEquals(40, configMap.size()); - assertNotNull(configMap.get("trace.handler.sampler.percent")); - assertEquals(0.5, configMap.get("trace.handler.sampler.percent")); - - System.getProperties().remove("servicecomb.configurationSource.additionalUrls"); - } - - @Test - public void testFullOperation() { - // configuration from system properties - ConcurrentMapConfiguration configFromSystemProperties = - new ConcurrentMapConfiguration(new SystemConfiguration()); - // configuration from yaml file - DynamicConfiguration configFromYamlFile = - new DynamicConfiguration(yamlConfigSource(), new NeverStartPollingScheduler()); - // create a hierarchy of configuration that makes - // 1) dynamic configuration source override system properties - ConcurrentCompositeConfiguration finalConfig = new ConcurrentCompositeConfiguration(); - finalConfig.addConfiguration(configFromYamlFile, "yamlConfig"); - finalConfig.addConfiguration(configFromSystemProperties, "systemEnvConfig"); - Assert.assertEquals(0.5, finalConfig.getDouble("trace.handler.sampler.percent"), 0.5); - - Object o = finalConfig.getProperty("zq"); - @SuppressWarnings("unchecked") - List> listO = (List>) o; - Assert.assertEquals(3, listO.size()); - } -} diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/archaius/sources/TestMicroserviceConfigLoader.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/file/TestMicroserviceConfigLoader.java similarity index 84% rename from foundations/foundation-config/src/test/java/org/apache/servicecomb/config/archaius/sources/TestMicroserviceConfigLoader.java rename to foundations/foundation-config/src/test/java/org/apache/servicecomb/config/file/TestMicroserviceConfigLoader.java index cadfc2244c8..0084976d004 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/archaius/sources/TestMicroserviceConfigLoader.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/file/TestMicroserviceConfigLoader.java @@ -15,9 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.config.archaius.sources; - -import static org.junit.Assert.assertEquals; +package org.apache.servicecomb.config.file; import java.io.FileNotFoundException; import java.io.IOException; @@ -27,8 +25,8 @@ import java.util.List; import java.util.stream.Collectors; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestMicroserviceConfigLoader { @@ -49,7 +47,7 @@ public void configsSortedByInsertionOrder() throws MalformedURLException { loader.sort(); - assertEquals(urls("jar:c", "jar:b", "jar:a"), urlsOf(loader.getConfigModels())); + Assertions.assertEquals(urls("jar:c", "jar:b", "jar:a"), urlsOf(loader.getConfigModels())); } @Test @@ -60,7 +58,7 @@ public void configsSortedBySpecifiedOrder() throws MalformedURLException { loader.sort(); - assertEquals(urls("jar:c", "jar:b", "jar:a"), urlsOf(loader.getConfigModels())); + Assertions.assertEquals(urls("jar:c", "jar:b", "jar:a"), urlsOf(loader.getConfigModels())); } @Test @@ -71,7 +69,7 @@ public void jarsAlwaysHaveHigherPriorityThanFiles() throws MalformedURLException loader.sort(); - assertEquals(urls("jar:j1", "file:f2", "file:f1"), urlsOf(loader.getConfigModels())); + Assertions.assertEquals(urls("jar:j1", "file:f2", "file:f1"), urlsOf(loader.getConfigModels())); } private String urlsOf(List configModels) { @@ -89,7 +87,7 @@ private String urls(String... urls) { @Test public void testLoadEmptyYaml() throws IOException { loader.load("empty.yaml"); - Assert.assertTrue(loader.getConfigModels().get(0).getConfig().isEmpty()); + Assertions.assertTrue(loader.getConfigModels().get(0).getConfig().isEmpty()); } @Test @@ -97,9 +95,9 @@ public void testLoadNotExistYaml() throws IOException { URL url = URI.create("file:/notExist.yaml").toURL(); try { loader.load(url); - Assert.fail("must throw exception"); + Assertions.fail("must throw exception"); } catch (FileNotFoundException e) { - Assert.assertTrue(true); + Assertions.assertTrue(true); } } } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestConfigObjectFactory.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestConfigObjectFactory.java index 8ca76c6fe82..9e5915b0c20 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestConfigObjectFactory.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestConfigObjectFactory.java @@ -17,11 +17,15 @@ package org.apache.servicecomb.config.inject; import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.apache.servicecomb.config.ConfigurationChangedEvent; import org.apache.servicecomb.config.priority.TestPriorityPropertyBase; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.Assert; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestConfigObjectFactory extends TestPriorityPropertyBase { public static class ConfigNoAnnotation { @@ -162,155 +166,186 @@ public void setBooleanValueObj1(Boolean booleanValueObj1) { public void noAnnotation_defaultValue() { ConfigNoAnnotation config = priorityPropertyManager.createConfigObject(ConfigNoAnnotation.class); - Assert.assertNull(config.strValue); - Assert.assertNull(config.getStrValue1()); - - Assert.assertEquals(0, config.intValue); - Assert.assertEquals(0, config.getIntValue1()); - Assert.assertNull(config.intValueObj); - Assert.assertNull(config.getIntValueObj1()); - - Assert.assertEquals(0, config.longValue); - Assert.assertEquals(0, config.getLongValue1()); - Assert.assertNull(config.longValueObj); - Assert.assertNull(config.getLongValueObj1()); - - Assert.assertEquals(0, config.floatValue, 0); - Assert.assertEquals(0, config.getFloatValue1(), 0); - Assert.assertNull(config.floatValueObj); - Assert.assertNull(config.getFloatValueObj1()); - - Assert.assertEquals(0, config.doubleValue, 0); - Assert.assertEquals(0, config.getDoubleValue1(), 0); - Assert.assertNull(config.doubleValueObj); - Assert.assertNull(config.getDoubleValueObj1()); - - Assert.assertFalse(config.booleanValue); - Assert.assertFalse(config.isBooleanValue1()); - Assert.assertNull(config.booleanValueObj); - Assert.assertNull(config.getBooleanValueObj1()); + Assertions.assertNull(config.strValue); + Assertions.assertNull(config.getStrValue1()); + + Assertions.assertEquals(0, config.intValue); + Assertions.assertEquals(0, config.getIntValue1()); + Assertions.assertNull(config.intValueObj); + Assertions.assertNull(config.getIntValueObj1()); + + Assertions.assertEquals(0, config.longValue); + Assertions.assertEquals(0, config.getLongValue1()); + Assertions.assertNull(config.longValueObj); + Assertions.assertNull(config.getLongValueObj1()); + + Assertions.assertEquals(0, config.floatValue, 0); + Assertions.assertEquals(0, config.getFloatValue1(), 0); + Assertions.assertNull(config.floatValueObj); + Assertions.assertNull(config.getFloatValueObj1()); + + Assertions.assertEquals(0, config.doubleValue, 0); + Assertions.assertEquals(0, config.getDoubleValue1(), 0); + Assertions.assertNull(config.doubleValueObj); + Assertions.assertNull(config.getDoubleValueObj1()); + + Assertions.assertFalse(config.booleanValue); + Assertions.assertFalse(config.isBooleanValue1()); + Assertions.assertNull(config.booleanValueObj); + Assertions.assertNull(config.getBooleanValueObj1()); } @Test public void noAnnotation_initValue() { - ArchaiusUtils.setProperty("strValue", "strValue"); - ArchaiusUtils.setProperty("strValue1", "strValue1"); - - ArchaiusUtils.setProperty("intValue", 1); - ArchaiusUtils.setProperty("intValue1", 2); - ArchaiusUtils.setProperty("intValueObj", 3); - ArchaiusUtils.setProperty("intValueObj1", 4); - - ArchaiusUtils.setProperty("longValue", 5); - ArchaiusUtils.setProperty("longValue1", 6); - ArchaiusUtils.setProperty("longValueObj", 7); - ArchaiusUtils.setProperty("longValueObj1", 8); - - ArchaiusUtils.setProperty("floatValue", 9.0); - ArchaiusUtils.setProperty("floatValue1", 10.0); - ArchaiusUtils.setProperty("floatValueObj", 11.0); - ArchaiusUtils.setProperty("floatValueObj1", 12.0); - - ArchaiusUtils.setProperty("doubleValue", 13.0); - ArchaiusUtils.setProperty("doubleValue1", 14.0); - ArchaiusUtils.setProperty("doubleValueObj", 15.0); - ArchaiusUtils.setProperty("doubleValueObj1", 16.0); - - ArchaiusUtils.setProperty("booleanValue", true); - ArchaiusUtils.setProperty("booleanValue1", true); - ArchaiusUtils.setProperty("booleanValueObj", true); - ArchaiusUtils.setProperty("booleanValueObj1", true); + Mockito.when(environment.getProperty("strValue")).thenReturn("strValue"); + Mockito.when(environment.getProperty("strValue1")).thenReturn("strValue1"); + + Mockito.when(environment.getProperty("intValue", Integer.class)).thenReturn(1); + Mockito.when(environment.getProperty("intValue1", Integer.class)).thenReturn(2); + Mockito.when(environment.getProperty("intValueObj", Integer.class)).thenReturn(3); + Mockito.when(environment.getProperty("intValueObj1", Integer.class)).thenReturn(4); + + Mockito.when(environment.getProperty("longValue", Long.class)).thenReturn(5L); + Mockito.when(environment.getProperty("longValue1", Long.class)).thenReturn(6L); + Mockito.when(environment.getProperty("longValueObj", Long.class)).thenReturn(7L); + Mockito.when(environment.getProperty("longValueObj1", Long.class)).thenReturn(8L); + + Mockito.when(environment.getProperty("floatValue", Float.class)).thenReturn(9.0F); + Mockito.when(environment.getProperty("floatValue1", Float.class)).thenReturn(10.0F); + Mockito.when(environment.getProperty("floatValueObj", Float.class)).thenReturn(11.0F); + Mockito.when(environment.getProperty("floatValueObj1", Float.class)).thenReturn(12.0F); + + Mockito.when(environment.getProperty("doubleValue", Double.class)).thenReturn(13.0D); + Mockito.when(environment.getProperty("doubleValue1", Double.class)).thenReturn(14.0D); + Mockito.when(environment.getProperty("doubleValueObj", Double.class)).thenReturn(15.0D); + Mockito.when(environment.getProperty("doubleValueObj1", Double.class)).thenReturn(16.0D); + + Mockito.when(environment.getProperty("booleanValue", Boolean.class)).thenReturn(true); + Mockito.when(environment.getProperty("booleanValue1", Boolean.class)).thenReturn(true); + Mockito.when(environment.getProperty("booleanValueObj", Boolean.class)).thenReturn(true); + Mockito.when(environment.getProperty("booleanValueObj1", Boolean.class)).thenReturn(true); ConfigNoAnnotation config = priorityPropertyManager.createConfigObject(ConfigNoAnnotation.class); - Assert.assertEquals("strValue", config.strValue); - Assert.assertEquals("strValue1", config.getStrValue1()); - - Assert.assertEquals(1, config.intValue); - Assert.assertEquals(2, config.getIntValue1()); - Assert.assertEquals(3, (int) config.intValueObj); - Assert.assertEquals(4, (int) config.getIntValueObj1()); - - Assert.assertEquals(5, config.longValue); - Assert.assertEquals(6, config.getLongValue1()); - Assert.assertEquals(7, (long) config.longValueObj); - Assert.assertEquals(8, (long) config.getLongValueObj1()); - - Assert.assertEquals(9, config.floatValue, 0); - Assert.assertEquals(10, config.getFloatValue1(), 0); - Assert.assertEquals(11, config.floatValueObj, 0); - Assert.assertEquals(12, config.getFloatValueObj1(), 0); - - Assert.assertEquals(13, config.doubleValue, 0); - Assert.assertEquals(14, config.getDoubleValue1(), 0); - Assert.assertEquals(15, config.doubleValueObj, 0); - Assert.assertEquals(16, config.getDoubleValueObj1(), 0); - - Assert.assertTrue(config.booleanValue); - Assert.assertTrue(config.isBooleanValue1()); - Assert.assertTrue(config.booleanValueObj); - Assert.assertTrue(config.getBooleanValueObj1()); + Assertions.assertEquals("strValue", config.strValue); + Assertions.assertEquals("strValue1", config.getStrValue1()); + + Assertions.assertEquals(1, config.intValue); + Assertions.assertEquals(2, config.getIntValue1()); + Assertions.assertEquals(3, (int) config.intValueObj); + Assertions.assertEquals(4, (int) config.getIntValueObj1()); + + Assertions.assertEquals(5, config.longValue); + Assertions.assertEquals(6, config.getLongValue1()); + Assertions.assertEquals(7, (long) config.longValueObj); + Assertions.assertEquals(8, (long) config.getLongValueObj1()); + + Assertions.assertEquals(9, config.floatValue, 0); + Assertions.assertEquals(10, config.getFloatValue1(), 0); + Assertions.assertEquals(11, config.floatValueObj, 0); + Assertions.assertEquals(12, config.getFloatValueObj1(), 0); + + Assertions.assertEquals(13, config.doubleValue, 0); + Assertions.assertEquals(14, config.getDoubleValue1(), 0); + Assertions.assertEquals(15, config.doubleValueObj, 0); + Assertions.assertEquals(16, config.getDoubleValueObj1(), 0); + + Assertions.assertTrue(config.booleanValue); + Assertions.assertTrue(config.isBooleanValue1()); + Assertions.assertTrue(config.booleanValueObj); + Assertions.assertTrue(config.getBooleanValueObj1()); } @Test public void noAnnotation_updateValue() { ConfigNoAnnotation config = priorityPropertyManager.createConfigObject(ConfigNoAnnotation.class); - ArchaiusUtils.setProperty("strValue", "strValue"); - ArchaiusUtils.setProperty("strValue1", "strValue1"); - - ArchaiusUtils.setProperty("intValue", 1); - ArchaiusUtils.setProperty("intValue1", 2); - ArchaiusUtils.setProperty("intValueObj", 3); - ArchaiusUtils.setProperty("intValueObj1", 4); - - ArchaiusUtils.setProperty("longValue", 5); - ArchaiusUtils.setProperty("longValue1", 6); - ArchaiusUtils.setProperty("longValueObj", 7); - ArchaiusUtils.setProperty("longValueObj1", 8); - - ArchaiusUtils.setProperty("floatValue", 9.0); - ArchaiusUtils.setProperty("floatValue1", 10.0); - ArchaiusUtils.setProperty("floatValueObj", 11.0); - ArchaiusUtils.setProperty("floatValueObj1", 12.0); - - ArchaiusUtils.setProperty("doubleValue", 13.0); - ArchaiusUtils.setProperty("doubleValue1", 14.0); - ArchaiusUtils.setProperty("doubleValueObj", 15.0); - ArchaiusUtils.setProperty("doubleValueObj1", 16.0); - - ArchaiusUtils.setProperty("booleanValue", true); - ArchaiusUtils.setProperty("booleanValue1", true); - ArchaiusUtils.setProperty("booleanValueObj", true); - ArchaiusUtils.setProperty("booleanValueObj1", true); - - Assert.assertEquals("strValue", config.strValue); - Assert.assertEquals("strValue1", config.getStrValue1()); - - Assert.assertEquals(1, config.intValue); - Assert.assertEquals(2, config.getIntValue1()); - Assert.assertEquals(3, (int) config.intValueObj); - Assert.assertEquals(4, (int) config.getIntValueObj1()); - - Assert.assertEquals(5, config.longValue); - Assert.assertEquals(6, config.getLongValue1()); - Assert.assertEquals(7, (long) config.longValueObj); - Assert.assertEquals(8, (long) config.getLongValueObj1()); - - Assert.assertEquals(9, config.floatValue, 0); - Assert.assertEquals(10, config.getFloatValue1(), 0); - Assert.assertEquals(11, config.floatValueObj, 0); - Assert.assertEquals(12, config.getFloatValueObj1(), 0); - - Assert.assertEquals(13, config.doubleValue, 0); - Assert.assertEquals(14, config.getDoubleValue1(), 0); - Assert.assertEquals(15, config.doubleValueObj, 0); - Assert.assertEquals(16, config.getDoubleValueObj1(), 0); - - Assert.assertTrue(config.booleanValue); - Assert.assertTrue(config.isBooleanValue1()); - Assert.assertTrue(config.booleanValueObj); - Assert.assertTrue(config.getBooleanValueObj1()); + Mockito.when(environment.getProperty("strValue")).thenReturn("strValue"); + Mockito.when(environment.getProperty("strValue1")).thenReturn("strValue1"); + + Mockito.when(environment.getProperty("intValue", Integer.class)).thenReturn(1); + Mockito.when(environment.getProperty("intValue1", Integer.class)).thenReturn(2); + Mockito.when(environment.getProperty("intValueObj", Integer.class)).thenReturn(3); + Mockito.when(environment.getProperty("intValueObj1", Integer.class)).thenReturn(4); + + Mockito.when(environment.getProperty("longValue", Long.class)).thenReturn(5L); + Mockito.when(environment.getProperty("longValue1", Long.class)).thenReturn(6L); + Mockito.when(environment.getProperty("longValueObj", Long.class)).thenReturn(7L); + Mockito.when(environment.getProperty("longValueObj1", Long.class)).thenReturn(8L); + + Mockito.when(environment.getProperty("floatValue", Float.class)).thenReturn(9.0F); + Mockito.when(environment.getProperty("floatValue1", Float.class)).thenReturn(10.0F); + Mockito.when(environment.getProperty("floatValueObj", Float.class)).thenReturn(11.0F); + Mockito.when(environment.getProperty("floatValueObj1", Float.class)).thenReturn(12.0F); + + Mockito.when(environment.getProperty("doubleValue", Double.class)).thenReturn(13.0D); + Mockito.when(environment.getProperty("doubleValue1", Double.class)).thenReturn(14.0D); + Mockito.when(environment.getProperty("doubleValueObj", Double.class)).thenReturn(15.0D); + Mockito.when(environment.getProperty("doubleValueObj1", Double.class)).thenReturn(16.0D); + + Mockito.when(environment.getProperty("booleanValue", Boolean.class)).thenReturn(true); + Mockito.when(environment.getProperty("booleanValue1", Boolean.class)).thenReturn(true); + Mockito.when(environment.getProperty("booleanValueObj", Boolean.class)).thenReturn(true); + Mockito.when(environment.getProperty("booleanValueObj1", Boolean.class)).thenReturn(true); + + HashMap updated = new HashMap<>(); + updated.put("strValue", "strValue"); + updated.put("strValue1", "strValue1"); + + updated.put("intValue", 0); + updated.put("intValue1", 1); + updated.put("intValueObj", 2); + updated.put("intValueObj1", 3); + + updated.put("longValue", 5L); + updated.put("longValue1", 6L); + updated.put("longValueObj", 7L); + updated.put("longValueObj1", 8L); + + updated.put("floatValue", 9.0F); + updated.put("floatValue1", 10.0F); + updated.put("floatValueObj", 11.0F); + updated.put("floatValueObj1", 12.0F); + + updated.put("doubleValue", 13.0D); + updated.put("doubleValue1", 14.0D); + updated.put("doubleValueObj", 15.0D); + updated.put("doubleValueObj1", 16.0D); + + updated.put("booleanValue", true); + updated.put("booleanValue1", true); + updated.put("booleanValueObj", true); + updated.put("booleanValueObj1", true); + + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + + Assertions.assertEquals("strValue", config.strValue); + Assertions.assertEquals("strValue1", config.getStrValue1()); + + Assertions.assertEquals(1, config.intValue); + Assertions.assertEquals(2, config.getIntValue1()); + Assertions.assertEquals(3, (int) config.intValueObj); + Assertions.assertEquals(4, (int) config.getIntValueObj1()); + + Assertions.assertEquals(5, config.longValue); + Assertions.assertEquals(6, config.getLongValue1()); + Assertions.assertEquals(7, (long) config.longValueObj); + Assertions.assertEquals(8, (long) config.getLongValueObj1()); + + Assertions.assertEquals(9, config.floatValue, 0); + Assertions.assertEquals(10, config.getFloatValue1(), 0); + Assertions.assertEquals(11, config.floatValueObj, 0); + Assertions.assertEquals(12, config.getFloatValueObj1(), 0); + + Assertions.assertEquals(13, config.doubleValue, 0); + Assertions.assertEquals(14, config.getDoubleValue1(), 0); + Assertions.assertEquals(15, config.doubleValueObj, 0); + Assertions.assertEquals(16, config.getDoubleValueObj1(), 0); + + Assertions.assertTrue(config.booleanValue); + Assertions.assertTrue(config.isBooleanValue1()); + Assertions.assertTrue(config.booleanValueObj); + Assertions.assertTrue(config.getBooleanValueObj1()); } @InjectProperties(prefix = "root") @@ -350,12 +385,12 @@ public static class ConfigWithAnnotation { public void annotationDefault() { ConfigWithAnnotation config = priorityPropertyManager.createConfigObject(ConfigWithAnnotation.class); - Assert.assertEquals("abc", config.strDef); - Assert.assertEquals(1, config.intDef); - Assert.assertEquals(2, config.longDef); - Assert.assertEquals(3, config.floatDef, 0); - Assert.assertEquals(4, config.doubleDef, 0); - Assert.assertTrue(config.booleanDef); + Assertions.assertEquals("abc", config.strDef); + Assertions.assertEquals(1, config.intDef); + Assertions.assertEquals(2, config.longDef); + Assertions.assertEquals(3, config.floatDef, 0); + Assertions.assertEquals(4, config.doubleDef, 0); + Assertions.assertTrue(config.booleanDef); } @Test @@ -368,19 +403,32 @@ public void placeholder_multi_list() { // low-2.a.high-1.b // low-2.a.high-2.b - Assert.assertEquals(0, config.longValue); + Assertions.assertEquals(0, config.longValue); - ArchaiusUtils.setProperty("root.low-2.a.high-2.b", Long.MAX_VALUE); - Assert.assertEquals(Long.MAX_VALUE, config.longValue); + Mockito.when(environment.getProperty("root.low-2.a.high-2.b", Long.class)).thenReturn(Long.MAX_VALUE); + HashMap updated = new HashMap<>(); + updated.put("root.low-2.a.high-2.b", Long.MAX_VALUE); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertEquals(Long.MAX_VALUE, config.longValue); - ArchaiusUtils.setProperty("root.low-2.a.high-1.b", Long.MAX_VALUE - 1); - Assert.assertEquals(Long.MAX_VALUE - 1, config.longValue); + Mockito.when(environment.getProperty("root.low-2.a.high-1.b", Long.class)).thenReturn(Long.MAX_VALUE - 1); + updated = new HashMap<>(); + updated.put("root.low-2.a.high-1.b", Long.MAX_VALUE - 1); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); - ArchaiusUtils.setProperty("root.low-1.a.high-2.b", Long.MAX_VALUE - 2); - Assert.assertEquals(Long.MAX_VALUE - 2, config.longValue); + Assertions.assertEquals(Long.MAX_VALUE - 1, config.longValue); - ArchaiusUtils.setProperty("root.low-1.a.high-1.b", Long.MAX_VALUE - 3); - Assert.assertEquals(Long.MAX_VALUE - 3, config.longValue); + Mockito.when(environment.getProperty("root.low-1.a.high-2.b", Long.class)).thenReturn(Long.MAX_VALUE - 2); + updated = new HashMap<>(); + updated.put("root.low-1.a.high-2.b", Long.MAX_VALUE - 2); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertEquals(Long.MAX_VALUE - 2, config.longValue); + + Mockito.when(environment.getProperty("root.low-1.a.high-1.b", Long.class)).thenReturn(Long.MAX_VALUE - 3); + updated = new HashMap<>(); + updated.put("root.low-1.a.high-1.b", Long.MAX_VALUE - 3); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertEquals(Long.MAX_VALUE - 3, config.longValue); } @Test @@ -388,39 +436,97 @@ public void placeholder_full_list() { ConfigWithAnnotation config = priorityPropertyManager.createConfigObject(ConfigWithAnnotation.class, "full-list", Arrays.asList("l1-1", "l1-2")); - Assert.assertEquals(0, config.floatValue, 0); + Assertions.assertEquals(0, config.floatValue, 0); + + Mockito.when(environment.getProperty("root.l1-2", Float.class)).thenReturn(1F); + HashMap updated = new HashMap<>(); + updated.put("root.l1-2", 1F); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + + Assertions.assertEquals(1F, config.floatValue, 0); - ArchaiusUtils.setProperty("root.l1-2", String.valueOf(1f)); - Assert.assertEquals(1f, config.floatValue, 0); + Mockito.when(environment.getProperty("root.l1-1", Float.class)).thenReturn(2F); + updated = new HashMap<>(); + updated.put("root.l1-1", 2F); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); - ArchaiusUtils.setProperty("root.l1-1", String.valueOf(2f)); - Assert.assertEquals(2f, config.floatValue, 0); + Assertions.assertEquals(2F, config.floatValue, 0); } @Test public void placeholder_normal() { ConfigWithAnnotation config = priorityPropertyManager.createConfigObject(ConfigWithAnnotation.class, "key", "k"); - Assert.assertEquals(0, config.intValue); + Assertions.assertEquals(0, config.intValue); - ArchaiusUtils.setProperty("root.k.value", "1"); - Assert.assertEquals(1, config.intValue); + Mockito.when(environment.getProperty("root.k.value", Integer.class)).thenReturn(1); + Map updated = new HashMap<>(); + updated.put("root.k.value", 1); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertEquals(1, config.intValue); } @Test public void overridePrefix() { ConfigWithAnnotation config = priorityPropertyManager.createConfigObject(ConfigWithAnnotation.class); - ArchaiusUtils.setProperty("override.high", "high"); - Assert.assertEquals("high", config.strValue); + Mockito.when(environment.getProperty("override.high")).thenReturn("high"); + HashMap updated = new HashMap<>(); + updated.put("override.high", "high"); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertEquals("high", config.strValue); + + Mockito.when(environment.getProperty("override.high")).thenReturn(null); + updated = new HashMap<>(); + updated.put("override.high", null); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertNull(config.strValue); + + Mockito.when(environment.getProperty("override.low")).thenReturn("low"); + updated = new HashMap<>(); + updated.put("override.low", "low"); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertEquals("low", config.strValue); + + Mockito.when(environment.getProperty("override.low")).thenReturn(null); + updated = new HashMap<>(); + updated.put("override.low", null); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + Assertions.assertNull(config.strValue); + } - ArchaiusUtils.setProperty("override.high", null); - Assert.assertNull(config.strValue); + @InjectProperties(prefix = "root") + public static class ConfigWithPojo { - ArchaiusUtils.setProperty("override.low", "low"); - Assert.assertEquals("low", config.strValue); + @InjectProperties(prefix = "root.model") + public static class Model { + @InjectProperty(defaultValue = "h") + public String name; + } - ArchaiusUtils.setProperty("override.low", null); - Assert.assertNull(config.strValue); + @InjectProperty(defaultValue = "4") + public int index; + + public Model model; + } + + @Test + public void configWithPojoWork() { + ConfigWithPojo config = priorityPropertyManager.createConfigObject(ConfigWithPojo.class); + ConfigWithPojo.Model model = priorityPropertyManager.createConfigObject(ConfigWithPojo.Model.class); + config.model = model; + + Assertions.assertEquals(4, config.index); + Assertions.assertEquals("h", config.model.name); + + Mockito.when(environment.getProperty("root.index", Integer.class)).thenReturn(5); + Mockito.when(environment.getProperty("root.model.name")).thenReturn("w"); + Map updated = new HashMap<>(); + updated.put("root.index", 5); + updated.put("root.model.name", "w"); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + + Assertions.assertEquals(5, config.index); + Assertions.assertEquals("w", config.model.name); } } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestPlaceholderResolver.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestPlaceholderResolver.java index 9e4e941d23a..d6407785f65 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestPlaceholderResolver.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/inject/TestPlaceholderResolver.java @@ -20,18 +20,22 @@ import java.util.HashMap; import java.util.Map; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestPlaceholderResolver { static Map parameters = new HashMap<>(); static PlaceholderResolver resolver = new PlaceholderResolver(); - @BeforeClass - public static void setup() { + @BeforeAll + public static void setupClass() { parameters.put("key", "value"); parameters.put("varOfVar", Arrays.asList("${key}")); @@ -42,51 +46,59 @@ public static void setup() { parameters.put("high-list", Arrays.asList("high-1", "high-2")); } + protected Environment environment; + + @BeforeEach + public void setup() { + environment = Mockito.mock(Environment.class); + LegacyPropertyFactory.setEnvironment(environment); + } + @Test public void unknown() { - Assert.assertThat(resolver.replace("prefix${xxx}suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix${xxx}suffix", parameters), Matchers.contains("prefix${xxx}suffix")); } @Test public void empty() { - Assert.assertThat(resolver.replace("prefix${}suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix${}suffix", parameters), Matchers.contains("prefix${}suffix")); } @Test public void notComplete() { - Assert.assertThat(resolver.replace("prefix${suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix${suffix", parameters), Matchers.contains("prefix${suffix")); } @Test public void normal() { - Assert.assertThat(resolver.replace("prefix.${key}.suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix.${key}.suffix", parameters), Matchers.contains("prefix.value.suffix")); } @Test public void disable() { - Assert.assertThat(resolver.replace("prefix.\\${key}.suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix.\\${key}.suffix", parameters), Matchers.contains("prefix.${key}.suffix")); } @Test public void varOfVar() { - Assert.assertThat(resolver.replace("prefix.${varOfVar}.suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix.${varOfVar}.suffix", parameters), Matchers.contains("prefix.value.suffix")); } @Test public void list() { - Assert.assertThat(resolver.replace("prefix.${low-list}.suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix.${low-list}.suffix", parameters), Matchers.contains("prefix.low-1.suffix", "prefix.low-2.suffix")); } @Test public void multi_list() { - Assert.assertThat(resolver.replace("prefix.${low-list}.${middle-list}.${high-list}.suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix.${low-list}.${middle-list}.${high-list}.suffix", parameters), Matchers.contains( "prefix.low-1.middle-1.high-1.suffix", "prefix.low-1.middle-1.high-2.suffix", @@ -100,13 +112,14 @@ public void multi_list() { @Test public void nested() { - Assert.assertThat(resolver.replace("prefix.${${priority}-list}.suffix", parameters), + MatcherAssert.assertThat(resolver.replace("prefix.${${priority}-list}.suffix", parameters), Matchers.contains("prefix.low-1.suffix", "prefix.low-2.suffix")); } @Test public void mixed() { - Assert.assertThat(resolver.replace("prefix.${${priority}-list}.${key}.${high-list}.suffix ${xxx}", parameters), + MatcherAssert.assertThat( + resolver.replace("prefix.${${priority}-list}.${key}.${high-list}.suffix ${xxx}", parameters), Matchers.contains( "prefix.low-1.value.high-1.suffix ${xxx}", "prefix.low-2.value.high-1.suffix ${xxx}", diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityProperty.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityProperty.java index 9f4db635247..85b3185d251 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityProperty.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityProperty.java @@ -16,15 +16,9 @@ */ package org.apache.servicecomb.config.priority; -import java.util.Collections; - -import org.apache.commons.configuration.MapConfiguration; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; - -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicPropertyFactory; +import org.mockito.Mockito; public class TestPriorityProperty extends TestPriorityPropertyBase { String high = "ms.schema.op"; @@ -38,181 +32,198 @@ public class TestPriorityProperty extends TestPriorityPropertyBase { @Test public void testLong() { PriorityProperty config = propertyFactory.getOrCreate(Long.class, -1L, -2L, keys); - Assert.assertEquals(-2L, (long) config.getValue()); + Assertions.assertEquals(-2L, (long) config.getValue()); - ArchaiusUtils.setProperty(low, 1L); - Assert.assertEquals(1L, (long) config.getValue()); + updateLong(low, 1L, config); + Assertions.assertEquals(1L, (long) config.getValue()); - ArchaiusUtils.setProperty(middle, 2L); - Assert.assertEquals(2L, (long) config.getValue()); + updateLong(middle, 2L, config); + Assertions.assertEquals(2L, (long) config.getValue()); - ArchaiusUtils.setProperty(high, 3L); - Assert.assertEquals(3L, (long) config.getValue()); + updateLong(high, 3L, config); + Assertions.assertEquals(3L, (long) config.getValue()); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(3L, (long) config.getValue()); - ArchaiusUtils.setProperty(middle, 2L); + updateLong(middle, null, config); + Assertions.assertEquals(3L, (long) config.getValue()); - ArchaiusUtils.setProperty(high, null); - Assert.assertEquals(2L, (long) config.getValue()); + updateLong(middle, 2L, config); + updateLong(high, null, config); + Assertions.assertEquals(2L, (long) config.getValue()); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(1L, (long) config.getValue()); + updateLong(middle, null, config); + Assertions.assertEquals(1L, (long) config.getValue()); - ArchaiusUtils.setProperty(low, null); - Assert.assertEquals(-2L, (long) config.getValue()); + updateLong(low, null, config); + Assertions.assertEquals(-2L, (long) config.getValue()); } @Test public void testInt() { PriorityProperty config = propertyFactory.getOrCreate(Integer.class, -1, -2, keys); - Assert.assertEquals(-2L, (int) config.getValue()); + Assertions.assertEquals(-2L, (int) config.getValue()); + + updateInt(low, 1, config); + Assertions.assertEquals(1, (int) config.getValue()); + + updateInt(middle, 2, config); + Assertions.assertEquals(2, (int) config.getValue()); + + updateInt(high, 3, config); + Assertions.assertEquals(3, (int) config.getValue()); - ArchaiusUtils.setProperty(low, 1); - Assert.assertEquals(1, (int) config.getValue()); + updateInt(middle, null, config); + Assertions.assertEquals(3, (int) config.getValue()); + updateInt(middle, 2, config); - ArchaiusUtils.setProperty(middle, 2); - Assert.assertEquals(2, (int) config.getValue()); + updateInt(high, null, config); + Assertions.assertEquals(2, (int) config.getValue()); + + updateInt(middle, null, config); + Assertions.assertEquals(1, (int) config.getValue()); + + updateInt(low, null, config); + Assertions.assertEquals(-2, (int) config.getValue()); + } + + private void updateFloat(String key, Float value, PriorityProperty config) { + Mockito.when(environment.getProperty(key, Float.class)).thenReturn(value); + config.updateValue(); + } - ArchaiusUtils.setProperty(high, 3); - Assert.assertEquals(3, (int) config.getValue()); + private void updateStr(String key, String value, PriorityProperty config) { + Mockito.when(environment.getProperty(key)).thenReturn(value); + config.updateValue(); + } - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(3, (int) config.getValue()); - ArchaiusUtils.setProperty(middle, 2); + private void updateInt(String key, Integer value, PriorityProperty config) { + Mockito.when(environment.getProperty(key, Integer.class)).thenReturn(value); + config.updateValue(); + } - ArchaiusUtils.setProperty(high, null); - Assert.assertEquals(2, (int) config.getValue()); + private void updateLong(String key, Long value, PriorityProperty config) { + Mockito.when(environment.getProperty(key, Long.class)).thenReturn(value); + config.updateValue(); + } - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(1, (int) config.getValue()); + private void updateBoolean(String key, Boolean value, PriorityProperty config) { + Mockito.when(environment.getProperty(key, Boolean.class)).thenReturn(value); + config.updateValue(); + } - ArchaiusUtils.setProperty(low, null); - Assert.assertEquals(-2, (int) config.getValue()); + private void updateDouble(String key, Double value, PriorityProperty config) { + Mockito.when(environment.getProperty(key, Double.class)).thenReturn(value); + config.updateValue(); } @Test public void testString() { PriorityProperty config = propertyFactory.getOrCreate(String.class, null, "def", keys); - Assert.assertEquals("def", config.getValue()); + Assertions.assertEquals("def", config.getValue()); - ArchaiusUtils.setProperty(low, 1); - Assert.assertEquals("1", config.getValue()); + updateStr(low, "1", config); + Assertions.assertEquals("1", config.getValue()); - ArchaiusUtils.setProperty(middle, 2); - Assert.assertEquals("2", config.getValue()); + updateStr(middle, "2", config); + Assertions.assertEquals("2", config.getValue()); - ArchaiusUtils.setProperty(high, 3); - Assert.assertEquals("3", config.getValue()); + updateStr(high, "3", config); + Assertions.assertEquals("3", config.getValue()); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals("3", config.getValue()); - ArchaiusUtils.setProperty(middle, 2); + updateStr(middle, null, config); + Assertions.assertEquals("3", config.getValue()); - ArchaiusUtils.setProperty(high, null); - Assert.assertEquals("2", config.getValue()); + updateStr(middle, "2", config); + updateStr(high, null, config); + Assertions.assertEquals("2", config.getValue()); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals("1", config.getValue()); + updateStr(middle, null, config); + Assertions.assertEquals("1", config.getValue()); - ArchaiusUtils.setProperty(low, null); - Assert.assertEquals("def", config.getValue()); + updateStr(low, null, config); + Assertions.assertEquals("def", config.getValue()); } @Test public void testBoolean() { PriorityProperty config = propertyFactory.getOrCreate(Boolean.class, null, false, keys); - Assert.assertFalse(config.getValue()); + Assertions.assertFalse(config.getValue()); - ArchaiusUtils.setProperty(low, true); - Assert.assertTrue(config.getValue()); + updateBoolean(low, true, config); + Assertions.assertTrue(config.getValue()); - ArchaiusUtils.setProperty(middle, false); - Assert.assertFalse(config.getValue()); + updateBoolean(middle, false, config); + Assertions.assertFalse(config.getValue()); - ArchaiusUtils.setProperty(high, true); - Assert.assertTrue(config.getValue()); + updateBoolean(high, true, config); + Assertions.assertTrue(config.getValue()); - ArchaiusUtils.setProperty(middle, false); - Assert.assertTrue(config.getValue()); - ArchaiusUtils.setProperty(middle, false); + updateBoolean(middle, false, config); + Assertions.assertTrue(config.getValue()); - ArchaiusUtils.setProperty(high, null); - Assert.assertFalse(config.getValue()); + updateBoolean(middle, false, config); + updateBoolean(high, null, config); + Assertions.assertFalse(config.getValue()); - ArchaiusUtils.setProperty(middle, null); - Assert.assertTrue(config.getValue()); + updateBoolean(middle, null, config); + Assertions.assertTrue(config.getValue()); - ArchaiusUtils.setProperty(low, null); - Assert.assertFalse(config.getValue()); + updateBoolean(low, null, config); + Assertions.assertFalse(config.getValue()); } @Test public void testDouble() { PriorityProperty config = propertyFactory.getOrCreate(Double.class, null, -2.0, keys); - Assert.assertEquals(-2, config.getValue(), 0); + Assertions.assertEquals(-2, config.getValue(), 0); - ArchaiusUtils.setProperty(low, 1); - Assert.assertEquals(1, config.getValue(), 0); + updateDouble(low, 1D, config); + Assertions.assertEquals(1, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, 2); - Assert.assertEquals(2, config.getValue(), 0); + updateDouble(middle, 2D, config); + Assertions.assertEquals(2, config.getValue(), 0); - ArchaiusUtils.setProperty(high, 3); - Assert.assertEquals(3, config.getValue(), 0); + updateDouble(high, 3D, config); + Assertions.assertEquals(3, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(3, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, 2); + updateDouble(middle, null, config); + Assertions.assertEquals(3, config.getValue(), 0); - ArchaiusUtils.setProperty(high, null); - Assert.assertEquals(2, config.getValue(), 0); + updateDouble(middle, 2D, config); + updateDouble(high, null, config); + Assertions.assertEquals(2, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(1, config.getValue(), 0); + updateDouble(middle, null, config); + Assertions.assertEquals(1, config.getValue(), 0); - ArchaiusUtils.setProperty(low, null); - Assert.assertEquals(-2, config.getValue(), 0); + updateDouble(low, null, config); + Assertions.assertEquals(-2, config.getValue(), 0); } @Test public void testFloat() { PriorityProperty config = propertyFactory.getOrCreate(Float.class, null, -2.0f, keys); - Assert.assertEquals(-2, config.getValue(), 0); - - ArchaiusUtils.setProperty(low, 1); - Assert.assertEquals(1, config.getValue(), 0); + Assertions.assertEquals(-2, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, 2); - Assert.assertEquals(2, config.getValue(), 0); + updateFloat(low, 1F, config); + Assertions.assertEquals(1, config.getValue(), 0); - ArchaiusUtils.setProperty(high, 3); - Assert.assertEquals(3, config.getValue(), 0); + updateFloat(middle, 2F, config); + Assertions.assertEquals(2, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(3, config.getValue(), 0); - ArchaiusUtils.setProperty(middle, 2); + updateFloat(high, 3F, config); + Assertions.assertEquals(3, config.getValue(), 0); - ArchaiusUtils.setProperty(high, null); - Assert.assertEquals(2, config.getValue(), 0); - - ArchaiusUtils.setProperty(middle, null); - Assert.assertEquals(1, config.getValue(), 0); - - ArchaiusUtils.setProperty(low, null); - Assert.assertEquals(-2, config.getValue(), 0); - } - - @Test - public void globalRefresh() { - PriorityProperty property = propertyFactory.getOrCreate(String.class, null, null, keys); + updateFloat(middle, null, config); + Assertions.assertEquals(3, config.getValue(), 0); - Assert.assertNull(property.getValue()); + updateFloat(middle, 2F, config); + updateFloat(high, null, config); + Assertions.assertEquals(2, config.getValue(), 0); - ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory - .getBackingConfigurationSource(); - config.addConfiguration(new MapConfiguration(Collections.singletonMap(high, "high-value"))); + updateFloat(middle, null, config); + Assertions.assertEquals(1, config.getValue(), 0); - Assert.assertEquals("high-value", property.getValue()); + updateFloat(low, null, config); + Assertions.assertEquals(-2, config.getValue(), 0); } } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyBase.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyBase.java index d590767b04b..375a755ec03 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyBase.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyBase.java @@ -16,38 +16,29 @@ */ package org.apache.servicecomb.config.priority; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; - -import com.netflix.config.DynamicPropertyFactory; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestPriorityPropertyBase { protected PriorityPropertyManager priorityPropertyManager; protected PriorityPropertyFactory propertyFactory; + protected Environment environment; + @BeforeEach public void setup() { - // avoid write too many logs - Logger.getRootLogger().setLevel(Level.OFF); - - ArchaiusUtils.resetConfig(); + environment = Mockito.mock(Environment.class); + LegacyPropertyFactory.setEnvironment(environment); - // make sure create a DynamicPropertyFactory instance - // otherwise will cause wrong order of configurationListeners - DynamicPropertyFactory.getInstance(); - - propertyFactory = new PriorityPropertyFactory(); + propertyFactory = new PriorityPropertyFactory(environment); priorityPropertyManager = new PriorityPropertyManager(new ConfigObjectFactory(propertyFactory)); - - Logger.getRootLogger().setLevel(Level.INFO); } @AfterEach public void teardown() { - ArchaiusUtils.resetConfig(); } } diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyFactory.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyFactory.java index 9024d70ff5e..1e33e3af684 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyFactory.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyFactory.java @@ -39,4 +39,4 @@ void should_create_different_instances_for_different_parameter() { assertThat(p1).isNotSameAs(p2); assertThat(propertyFactory.getProperties().count()).isEqualTo(2); } -} \ No newline at end of file +} diff --git a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyManager.java b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyManager.java index 35402ae6ed8..291d8614562 100644 --- a/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyManager.java +++ b/foundations/foundation-config/src/test/java/org/apache/servicecomb/config/priority/TestPriorityPropertyManager.java @@ -17,15 +17,11 @@ package org.apache.servicecomb.config.priority; -import org.apache.servicecomb.config.ConfigUtil; import org.apache.servicecomb.config.inject.InjectProperties; import org.apache.servicecomb.config.inject.InjectProperty; -import org.apache.servicecomb.config.inject.TestConfigObjectFactory; -import org.junit.Assert; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import com.netflix.config.DynamicProperty; - public class TestPriorityPropertyManager extends TestPriorityPropertyBase { String high = "ms.schema.op"; @@ -37,7 +33,7 @@ public class TestPriorityPropertyManager extends TestPriorityPropertyBase { @InjectProperties(prefix = "root") public static class ConfigWithAnnotation { - @InjectProperty(prefix = "override", keys = {"high", "low"}) + @InjectProperty(prefix = "override", keys = {"high", "low"}, defaultValue = "abc") public String strValue; } @@ -65,21 +61,17 @@ public void testConfigurationsAreGCCollected() { for (int i = 0; i < 100; i++) { for (int j = 0; j < 100; j++) { - TestConfigObjectFactory.ConfigWithAnnotation configConfigObject = priorityPropertyManager.createConfigObject( - TestConfigObjectFactory.ConfigWithAnnotation.class); - Assert.assertEquals("abc", configConfigObject.strDef); + ConfigWithAnnotation configConfigObject = priorityPropertyManager.createConfigObject( + ConfigWithAnnotation.class); + Assertions.assertEquals("abc", configConfigObject.strValue); PriorityProperty configPriorityProperty = propertyFactory.getOrCreate(Long.class, -1L, -2L, keys); - Assert.assertEquals(-2L, (long) configPriorityProperty.getValue()); + Assertions.assertEquals(-2L, (long) configPriorityProperty.getValue()); } } waitKeyForGC(priorityPropertyManager); - Assert.assertTrue(priorityPropertyManager.getConfigObjectMap().isEmpty()); - for (DynamicProperty property : ConfigUtil.getAllDynamicProperties().values()) { - Assert.assertTrue(ConfigUtil.getCallbacks(property).isEmpty()); - } - + Assertions.assertTrue(priorityPropertyManager.getConfigObjectMap().isEmpty()); System.out.println("Token : " + (System.currentTimeMillis() - timeBegin)); } } diff --git a/foundations/foundation-config/src/test/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource b/foundations/foundation-config/src/test/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource deleted file mode 100644 index 54abbb2cacf..00000000000 --- a/foundations/foundation-config/src/test/resources/META-INF/services/org.apache.servicecomb.config.spi.ConfigCenterConfigurationSource +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.config.MapBasedConfigurationSource \ No newline at end of file diff --git a/foundations/foundation-config/src/test/resources/log4j.properties b/foundations/foundation-config/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/foundations/foundation-config/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/foundations/foundation-config/src/test/resources/mapping.yaml b/foundations/foundation-config/src/test/resources/mapping.yaml index b9e0d97a3ef..66d6b0d08e1 100644 --- a/foundations/foundation-config/src/test/resources/mapping.yaml +++ b/foundations/foundation-config/src/test/resources/mapping.yaml @@ -22,4 +22,4 @@ MY_SERVICES_ENDPOINT: - servicecomb.service1.mapping.address SERVICECOMB_ENV: - service_description.environment - - service_description.environment.old \ No newline at end of file + - service_description.environment.old diff --git a/foundations/foundation-config/src/test/resources/microservice.yaml b/foundations/foundation-config/src/test/resources/microservice.yaml index d820050cfe0..43a9078fba0 100644 --- a/foundations/foundation-config/src/test/resources/microservice.yaml +++ b/foundations/foundation-config/src/test/resources/microservice.yaml @@ -60,16 +60,10 @@ cse: service_description: name: testDemo - -servicecomb: - cse: - servicecomb: - file: value # this is a config for TestConfigUtil.testCreateLocalConfigWithExtraConfig() - holder: b,c,d test: commonSeparatedString: a,b,c commonSeparatedStringHolder: ${holder} stringArray: - m - - n \ No newline at end of file + - n diff --git a/foundations/foundation-config/src/test/resources/test1.yaml b/foundations/foundation-config/src/test/resources/test1.yaml index 708d0e82f8b..e171487901f 100644 --- a/foundations/foundation-config/src/test/resources/test1.yaml +++ b/foundations/foundation-config/src/test/resources/test1.yaml @@ -38,11 +38,11 @@ shutDownHandler: enabled: true timeLimit: 30000 -hsa: +has: manager: url: 127.0.0.1 - serializer: - default: protostuff + serializer: + default: protostuff provider: service: name: ${spring.application.name} @@ -52,7 +52,7 @@ hsa: rpc: serviceLevel: interface dsf: -# ip: "10.57.65.225" +# ip: "10.57.65.225" port: 7450 eureka: diff --git a/foundations/foundation-metrics/pom.xml b/foundations/foundation-metrics/pom.xml index 0e6aafb39f9..d893011c4d4 100644 --- a/foundations/foundation-metrics/pom.xml +++ b/foundations/foundation-metrics/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb foundations - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT foundation-metrics Java Chassis::Foundations::Metrics @@ -32,16 +32,22 @@ foundation-common - com.netflix.archaius - archaius-core + io.micrometer + micrometer-core - com.netflix.spectator - spectator-reg-servo + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core + test - org.slf4j - slf4j-log4j12 + org.jmockit + jmockit test diff --git a/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java b/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java deleted file mode 100644 index cccc7107f43..00000000000 --- a/foundations/foundation-metrics/src/main/java/com/netflix/spectator/api/SpectatorUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 com.netflix.spectator.api; - -public final class SpectatorUtils { - private SpectatorUtils() { - } - - public static Id createDefaultId(String name) { - return new DefaultId(name); - } - - public static void removeExpiredMeters(Registry registry) { - if (registry instanceof AbstractRegistry) { - ((AbstractRegistry) registry).removeExpiredMeters(); - } - } - - public static void registerMeter(Registry registry, Meter meter) { - if (!(registry instanceof AbstractRegistry)) { - throw new IllegalStateException("registry must be a AbstractRegistry, class=" + registry.getClass().getName()); - } - ((AbstractRegistry) registry).getOrCreate(meter.id(), Meter.class, null, _id -> meter); - } -} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java index 1ce656eb47e..86529a36e41 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrap.java @@ -16,41 +16,58 @@ */ package org.apache.servicecomb.foundation.metrics; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry; +import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import com.google.common.eventbus.EventBus; import com.google.common.util.concurrent.ThreadFactoryBuilder; +import io.micrometer.core.instrument.MeterRegistry; + public class MetricsBootstrap { private static final Logger LOGGER = LoggerFactory.getLogger(MetricsBootstrap.class); - private GlobalRegistry globalRegistry; + private final MetricsBootstrapConfig config; - private EventBus eventBus; + private MeterRegistry meterRegistry; - private MetricsBootstrapConfig config = new MetricsBootstrapConfig(); + private EventBus eventBus; private ScheduledExecutorService executorService; - public void start(GlobalRegistry globalRegistry, EventBus eventBus) { - this.globalRegistry = globalRegistry; + private List metricsInitializers; + + @Autowired + public MetricsBootstrap(MetricsBootstrapConfig config) { + this.config = config; + } + + @Autowired + public void setMetricsInitializers(List metricsInitializers) { + this.metricsInitializers = metricsInitializers; + } + + @Autowired + public void setMeterRegistry(MeterRegistry meterRegistry) { + this.meterRegistry = meterRegistry; + } + + public void start(EventBus eventBus) { this.eventBus = eventBus; this.executorService = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder() - .setNameFormat("spectator-poller-%d") + .setNameFormat("metrics-poller-%d") .build()); - loadMetricsInitializers(); + metricsInitializers.forEach(initializer -> initializer.init(this.meterRegistry, eventBus, config)); startPoll(); } @@ -59,27 +76,25 @@ public void shutdown() { executorService.shutdown(); } - List initializers = new ArrayList<>(SPIServiceUtils.getSortedService(MetricsInitializer.class)); - Collections.reverse(initializers); - initializers.forEach(initializer -> initializer.destroy()); - } - - protected void loadMetricsInitializers() { - SPIServiceUtils.getSortedService(MetricsInitializer.class) - .forEach(initializer -> initializer.init(globalRegistry, eventBus, config)); + Collections.reverse(metricsInitializers); + metricsInitializers.forEach(MetricsInitializer::destroy); } protected void startPoll() { executorService.scheduleAtFixedRate(this::pollMeters, - 0, + config.getMsPollInterval(), config.getMsPollInterval(), TimeUnit.MILLISECONDS); } public synchronized void pollMeters() { + metricsInitializers.forEach(initializer -> { + if (initializer instanceof PeriodMeter) { + ((PeriodMeter) initializer).poll(System.currentTimeMillis(), config.getMsPollInterval()); + } + }); try { - long secondInterval = TimeUnit.MILLISECONDS.toSeconds(config.getMsPollInterval()); - PolledEvent polledEvent = globalRegistry.poll(secondInterval); + PolledEvent polledEvent = new PolledEvent(meterRegistry.getMeters()); eventBus.post(polledEvent); } catch (Throwable e) { LOGGER.error("poll meters error. ", e); diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java index 09322ca3462..53ab9a6d6ff 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsBootstrapConfig.java @@ -16,24 +16,52 @@ */ package org.apache.servicecomb.foundation.metrics; -import com.netflix.config.DynamicPropertyFactory; +import org.springframework.core.env.Environment; public class MetricsBootstrapConfig { public static final String METRICS_WINDOW_TIME = "servicecomb.metrics.window_time"; - public static final int DEFAULT_METRICS_WINDOW_TIME = 60000; + public static final String CONFIG_LATENCY_DISTRIBUTION = "servicecomb.metrics.invocation.latencyDistribution"; + + public static final String CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN = + "servicecomb.metrics.publisher.defaultLog.invocation.latencyDistribution.minScopeLength"; + + public static final int DEFAULT_METRICS_WINDOW_TIME = 300_000; private long msPollInterval; - public MetricsBootstrapConfig() { + private String latencyDistribution; + + private int minScopeLength; + + private Environment environment; + + public MetricsBootstrapConfig(Environment environment) { + this.environment = environment; msPollInterval = - DynamicPropertyFactory.getInstance().getIntProperty(METRICS_WINDOW_TIME, DEFAULT_METRICS_WINDOW_TIME).get(); + environment.getProperty(METRICS_WINDOW_TIME, int.class, DEFAULT_METRICS_WINDOW_TIME); if (msPollInterval < 1000) { msPollInterval = 1000; } + + latencyDistribution = environment.getProperty(CONFIG_LATENCY_DISTRIBUTION, String.class); + minScopeLength = environment.getProperty( + CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7); + } + + public Environment getEnvironment() { + return environment; } public long getMsPollInterval() { return msPollInterval; } + + public String getLatencyDistribution() { + return latencyDistribution; + } + + public int getMinScopeLength() { + return minScopeLength; + } } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java index 88201dcb2cc..3cb0b8f95f0 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/MetricsInitializer.java @@ -16,19 +16,16 @@ */ package org.apache.servicecomb.foundation.metrics; -import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry; - import com.google.common.eventbus.EventBus; +import io.micrometer.core.instrument.MeterRegistry; + public interface MetricsInitializer { default int getOrder() { return 0; } - /** - * if create new registry, must add to globalRegistry - */ - void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config); + void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config); default void destroy() { diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java index 6b7c3018c68..0814f96149f 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/PolledEvent.java @@ -18,17 +18,14 @@ import java.util.List; -import com.netflix.spectator.api.Measurement; -import com.netflix.spectator.api.Meter; +import io.micrometer.core.instrument.Meter; + public class PolledEvent { private List meters; - private List measurements; - - public PolledEvent(List meters, List measurements) { + public PolledEvent(List meters) { this.meters = meters; - this.measurements = measurements; } public List getMeters() { @@ -38,12 +35,4 @@ public List getMeters() { public void setMeters(List meters) { this.meters = meters; } - - public List getMeasurements() { - return measurements; - } - - public void setMeasurements(List measurements) { - this.measurements = measurements; - } } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckResult.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckResult.java index fc147fbd643..930288aa5f3 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckResult.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/health/HealthCheckResult.java @@ -22,7 +22,6 @@ public class HealthCheckResult { private String information; - //unsupport object or generic type,so string.. private String extraData; private long timestamp; diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java deleted file mode 100644 index d9e2f46d583..00000000000 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/AbstractPeriodMeter.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.foundation.metrics.meter; - -import java.util.Collections; -import java.util.List; - -import com.netflix.spectator.api.Id; -import com.netflix.spectator.api.Measurement; - -public abstract class AbstractPeriodMeter implements PeriodMeter { - protected Id id; - - protected List allMeasurements = Collections.emptyList(); - - public Id id() { - return id; - } - - @Override - public Iterable measure() { - return allMeasurements; - } - - public boolean hasExpired() { - return false; - } -} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java index aded5ba6525..d464697024f 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionConfig.java @@ -24,9 +24,11 @@ import org.slf4j.LoggerFactory; public class LatencyDistributionConfig { + public static final Long MAX_LATENCY = 60 * 60 * 1000L; + private static final Logger LOGGER = LoggerFactory.getLogger(LatencyDistributionConfig.class); - private List scopeConfigs = new ArrayList<>(); + private final List scopeConfigs = new ArrayList<>(); /** * @@ -36,7 +38,7 @@ public LatencyDistributionConfig(String config) { if (StringUtils.isEmpty(config)) { return; } - config = config.trim() + "," + Long.MAX_VALUE; + config = config.trim() + "," + MAX_LATENCY; String[] array = config.split("\\s*,+\\s*"); try { for (int idx = 0; idx < array.length - 1; idx++) { diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java deleted file mode 100644 index cd15f0ed3b4..00000000000 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyDistributionMeter.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.foundation.metrics.meter; - -import java.util.ArrayList; -import java.util.List; - -import com.netflix.spectator.api.Id; -import com.netflix.spectator.api.Measurement; - -public class LatencyDistributionMeter extends AbstractPeriodMeter { - private List latencyScopeMeters = new ArrayList<>(); - - public LatencyDistributionMeter(Id id, String config) { - this.id = id; - - LatencyDistributionConfig latencyDistributionConfig = new LatencyDistributionConfig(config); - for (LatencyScopeConfig scopeConfig : latencyDistributionConfig.getScopeConfigs()) { - latencyScopeMeters.add(new LatencyScopeMeter(id, scopeConfig)); - } - } - - public void record(long nanoLatency) { - if (nanoLatency < 0) { - return; - } - - for (LatencyScopeMeter latencyScopeMeter : latencyScopeMeters) { - if (latencyScopeMeter.update(nanoLatency)) { - return; - } - } - } - - @Override - public void calcMeasurements(long msNow, long secondInterval) { - List measurements = new ArrayList<>(); - calcMeasurements(measurements, msNow, secondInterval); - allMeasurements = measurements; - } - - @Override - public void calcMeasurements(List measurements, long msNow, long secondInterval) { - latencyScopeMeters.forEach(latencyScopeMeter -> measurements.add(latencyScopeMeter.createMeasurement(msNow))); - } -} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeConfig.java index db0d61c2924..0beeb7cfee9 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeConfig.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeConfig.java @@ -20,9 +20,9 @@ public class LatencyScopeConfig { // [min, max) // even max equals Long.MAX_VALUE, still not include it // because it will never happened in real cases - private long msMin; + private final long msMin; - private long msMax; + private final long msMax; public LatencyScopeConfig(long msMin, long msMax) { this.msMin = msMin; diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java deleted file mode 100644 index 6793926a8e2..00000000000 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/LatencyScopeMeter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.foundation.metrics.meter; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.LongAdder; - -import com.netflix.spectator.api.Id; -import com.netflix.spectator.api.Measurement; - -public class LatencyScopeMeter { - private Id scopeId; - - private LongAdder times = new LongAdder(); - - private long lastTimes = 0L; - - private long nanoMin; - - private long nanoMax; - - public LatencyScopeMeter(Id latencyDistributionId, LatencyScopeConfig config) { - nanoMin = TimeUnit.MILLISECONDS.toNanos(config.getMsMin()); - nanoMax = TimeUnit.MILLISECONDS.toNanos(config.getMsMax()); - scopeId = latencyDistributionId.withTag("scope", - String.format("[%d,%s)", config.getMsMin(), config.getMsMax() == Long.MAX_VALUE ? "" : config.getMsMax())); - } - - public boolean update(long nanoLatency) { - if (nanoMin <= nanoLatency && nanoMax > nanoLatency) { - times.increment(); - return true; - } - - return false; - } - - public Measurement createMeasurement(long msNow) { - long currentTimes = times.longValue(); - long deltaTimes = currentTimes - lastTimes; - this.lastTimes = currentTimes; - - return new Measurement(scopeId, msNow, deltaTimes); - } -} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java index f91d781e17a..a846d08179d 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/PeriodMeter.java @@ -16,13 +16,6 @@ */ package org.apache.servicecomb.foundation.metrics.meter; -import java.util.List; - -import com.netflix.spectator.api.Measurement; -import com.netflix.spectator.api.Meter; - -public interface PeriodMeter extends Meter { - void calcMeasurements(long msNow, long secondInterval); - - void calcMeasurements(List measurements, long msNow, long secondInterval); +public interface PeriodMeter { + void poll(long msNow, long secondInterval); } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java deleted file mode 100644 index 09803a4718d..00000000000 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/meter/SimpleTimer.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.foundation.metrics.meter; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.LongAdder; - -import com.netflix.spectator.api.Id; -import com.netflix.spectator.api.Measurement; -import com.netflix.spectator.api.Statistic; -import com.netflix.spectator.impl.AtomicDouble; - -/** - * ServoTimer is too slow - * this is a faster timer - */ -public class SimpleTimer extends AbstractPeriodMeter { - private static final double CNV_SECONDS = 1.0 / TimeUnit.SECONDS.toNanos(1L); - - private final Id idCount; - - private final Id idTotalTime; - - private final Id idMax; - - private final LongAdder count = new LongAdder(); - - private final LongAdder totalTime = new LongAdder(); - - private final AtomicDouble max = new AtomicDouble(); - - private long lastCount = 0; - - private long lastTotalTime = 0; - - public SimpleTimer(Id id) { - this.id = id; - this.idCount = id.withTag(Statistic.count); - this.idTotalTime = id.withTag(Statistic.totalTime); - this.idMax = id.withTag(Statistic.max); - } - - public void record(long nanoAmount) { - if (nanoAmount >= 0) { - totalTime.add(nanoAmount); - count.increment(); - max.max(nanoAmount); - } - } - - private Measurement newMeasurement(Id id, long msNow, Number n) { - return new Measurement(id, msNow, n.doubleValue()); - } - - @Override - public void calcMeasurements(long msNow, long secondInterval) { - List measurements = new ArrayList<>(3); - calcMeasurements(measurements, msNow, secondInterval); - allMeasurements = measurements; - } - - @Override - public void calcMeasurements(List measurements, long msNow, long secondInterval) { - long currentCount = count.longValue(); - long currentTotalTime = totalTime.longValue(); - - measurements.add(newMeasurement(idCount, msNow, (double) (currentCount - lastCount) / secondInterval)); - measurements - .add(newMeasurement(idTotalTime, msNow, (currentTotalTime - lastTotalTime) / secondInterval * CNV_SECONDS)); - measurements.add(newMeasurement(idMax, msNow, max.get() * CNV_SECONDS)); - - lastCount = currentCount; - lastTotalTime = currentTotalTime; - // maybe lost some max value, but not so important? - max.set(0); - } -} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/DefaultTagFinder.java similarity index 88% rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/DefaultTagFinder.java index dc731a84637..f29227c6a72 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/DefaultTagFinder.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/DefaultTagFinder.java @@ -14,12 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.servicecomb.foundation.metrics.publish.spectator; +package org.apache.servicecomb.foundation.metrics.publish; -import com.netflix.spectator.api.Tag; + +import io.micrometer.core.instrument.Tag; public class DefaultTagFinder implements TagFinder { - private String tagKey; + private final String tagKey; private boolean skipOnNull; @@ -45,7 +46,7 @@ public String getTagKey() { @Override public Tag find(Iterable tags) { for (Tag tag : tags) { - if (tag.key().equals(tagKey)) { + if (tag.getKey().equals(tagKey)) { return tag; } } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementGroupConfig.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementGroupConfig.java similarity index 89% rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementGroupConfig.java rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementGroupConfig.java index 48075fc8a4a..cec6db25eb4 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementGroupConfig.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementGroupConfig.java @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.servicecomb.foundation.metrics.publish.spectator; +package org.apache.servicecomb.foundation.metrics.publish; import java.util.Arrays; import java.util.HashMap; @@ -24,7 +24,7 @@ public class MeasurementGroupConfig { // key is measurement id name - private Map> groups = new HashMap<>(); + private final Map> groups = new HashMap<>(); public MeasurementGroupConfig() { } @@ -38,7 +38,7 @@ public void addGroup(String idName, Object... tagNameOrFinders) { Arrays .asList(tagNameOrFinders) .stream() - .map(r -> TagFinder.build(r)) + .map(TagFinder::build) .collect(Collectors.toList())); } diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementNode.java similarity index 75% rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementNode.java index 4aed5748045..8ff19a15345 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementNode.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementNode.java @@ -14,29 +14,37 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.servicecomb.foundation.metrics.publish.spectator; +package org.apache.servicecomb.foundation.metrics.publish; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import com.netflix.spectator.api.Measurement; +import io.micrometer.core.instrument.Measurement; +import io.micrometer.core.instrument.Meter.Id; public class MeasurementNode implements Comparable { - private String name; + private final String name; - private List measurements = new ArrayList<>(); + private final Id id; + + private final List measurements = new ArrayList<>(); private Map children; - public MeasurementNode(String name, Map children) { + public MeasurementNode(String name, Id id, Map children) { this.name = name; + this.id = id; this.children = children; } public String getName() { - return name; + return this.name; + } + + public Id getId() { + return id; } public Map getChildren() { @@ -62,13 +70,16 @@ public MeasurementNode findChild(String... childNames) { return node; } - public MeasurementNode addChild(String childName, Measurement measurement) { + public MeasurementNode addChild(String childName, Id id, Measurement measurement) { if (children == null) { children = new LinkedHashMap<>(); } - MeasurementNode node = children.computeIfAbsent(childName, name -> new MeasurementNode(name, null)); - node.addMeasurement(measurement); + MeasurementNode node = children.computeIfAbsent(childName, name -> new MeasurementNode(name, id, null)); + + if (measurement != null) { + node.addMeasurement(measurement); + } return node; } @@ -84,7 +95,7 @@ public void addMeasurement(Measurement measurement) { public double summary() { double result = 0; for (Measurement measurement : measurements) { - result += measurement.value(); + result += measurement.getValue(); } return result; diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java new file mode 100644 index 00000000000..a03c4739ef7 --- /dev/null +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/MeasurementTree.java @@ -0,0 +1,92 @@ +/* + * 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.foundation.metrics.publish; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import io.micrometer.core.instrument.DistributionSummary; +import io.micrometer.core.instrument.Measurement; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.Meter.Id; +import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.distribution.CountAtBucket; +import io.micrometer.core.instrument.distribution.HistogramSnapshot; + +// like select * from meters group by ...... +// but output a tree not a table +public class MeasurementTree extends MeasurementNode { + public MeasurementTree() { + super(null, null, null); + } + + // groupConfig: + // key: id name + // value: id tag keys + // only id name exists in groupConfig will accept, others will be ignored + public void from(Iterator meters, MeasurementGroupConfig groupConfig) { + meters.forEachRemaining(meter -> { + // This code snip is not very good design. But DistributionSummary is quite special. + if (meter instanceof DistributionSummary distributionSummary) { + HistogramSnapshot snapshot = distributionSummary.takeSnapshot(); + CountAtBucket[] countAtBuckets = snapshot.histogramCounts(); + List distributions = new ArrayList<>(countAtBuckets.length); + for (CountAtBucket countAtBucket : countAtBuckets) { + final double value = countAtBucket.count(); + distributions.add(new Measurement(() -> value, + Statistic.COUNT)); + } + + from(meter.getId(), distributions, groupConfig); + return; + } + + Iterable measurements = meter.measure(); + from(meter.getId(), measurements, groupConfig); + }); + } + + public void from(Id id, Iterable measurements, MeasurementGroupConfig groupConfig) { + for (Measurement measurement : measurements) { + MeasurementNode node = addChild(id.getName(), id, measurement); + + List tagFinders = groupConfig.findTagFinders(id.getName()); + if (tagFinders == null) { + continue; + } + + for (TagFinder tagFinder : tagFinders) { + Tag tag = tagFinder.find(id.getTags()); + if (tag == null) { + if (tagFinder.skipOnNull()) { + break; + } + throw new IllegalStateException( + String.format("tag key \"%s\" not exist in %s", + tagFinder.getTagKey(), + id)); + } + + node = node.addChild(tag.getValue(), id, measurement); + } + + node.addChild(measurement.getStatistic().name(), id, measurement); + } + } +} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/TagFinder.java similarity index 92% rename from foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java rename to foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/TagFinder.java index 0762afb8de4..e1f3c8b402c 100644 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TagFinder.java +++ b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/TagFinder.java @@ -14,9 +14,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.servicecomb.foundation.metrics.publish.spectator; +package org.apache.servicecomb.foundation.metrics.publish; -import com.netflix.spectator.api.Tag; +import io.micrometer.core.instrument.Tag; public interface TagFinder { static TagFinder build(Object obj) { diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java deleted file mode 100644 index 79101fa166e..00000000000 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/publish/spectator/MeasurementTree.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.foundation.metrics.publish.spectator; - -import java.util.Iterator; -import java.util.List; - -import com.netflix.spectator.api.Id; -import com.netflix.spectator.api.Measurement; -import com.netflix.spectator.api.Meter; -import com.netflix.spectator.api.Tag; - -// like select * from meters group by ...... -// but output a tree not a table -public class MeasurementTree extends MeasurementNode { - public MeasurementTree() { - super(null, null); - } - - // groupConfig: - // key: id name - // value: id tag keys - // only id name exists in groupConfig will accept, others will be ignored - public void from(Iterator meters, MeasurementGroupConfig groupConfig) { - meters.forEachRemaining(meter -> { - Iterable measurements = meter.measure(); - from(measurements, groupConfig); - }); - } - - public void from(Iterable measurements, MeasurementGroupConfig groupConfig) { - for (Measurement measurement : measurements) { - Id id = measurement.id(); - MeasurementNode node = addChild(id.name(), measurement); - - List tagFinders = groupConfig.findTagFinders(id.name()); - if (tagFinders == null) { - continue; - } - - for (TagFinder tagFinder : tagFinders) { - Tag tag = tagFinder.find(id.tags()); - if (tag == null) { - if (tagFinder.skipOnNull()) { - break; - } - throw new IllegalStateException( - String.format("tag key \"%s\" not exist in %s", - tagFinder.getTagKey(), - measurement)); - } - - node = node.addChild(tag.value(), measurement); - } - } - } -} diff --git a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java b/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java deleted file mode 100644 index 9af39d02d1b..00000000000 --- a/foundations/foundation-metrics/src/main/java/org/apache/servicecomb/foundation/metrics/registry/GlobalRegistry.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.foundation.metrics.registry; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -import org.apache.servicecomb.foundation.metrics.PolledEvent; -import org.apache.servicecomb.foundation.metrics.meter.PeriodMeter; - -import com.netflix.spectator.api.Clock; -import com.netflix.spectator.api.Measurement; -import com.netflix.spectator.api.Meter; -import com.netflix.spectator.api.Registry; -import com.netflix.spectator.api.SpectatorUtils; - -public class GlobalRegistry { - private Clock clock; - - private List registries = new CopyOnWriteArrayList<>(); - - private Registry defaultRegistry; - - public GlobalRegistry() { - this(Clock.SYSTEM); - } - - public GlobalRegistry(Clock clock) { - this.clock = clock; - } - - public Clock getClock() { - return clock; - } - - public List getRegistries() { - return registries; - } - - public Registry getDefaultRegistry() { - return defaultRegistry; - } - - public synchronized void add(Registry registry) { - if (registries.isEmpty()) { - defaultRegistry = registry; - } - registries.add(registry); - } - - public synchronized void remove(Registry registry) { - registries.remove(registry); - if (registry != defaultRegistry) { - return; - } - - if (registries.isEmpty()) { - defaultRegistry = null; - return; - } - - defaultRegistry = registries.get(0); - } - - public synchronized void removeAll() { - registries.clear(); - defaultRegistry = null; - } - - @SuppressWarnings("unchecked") - public T find(Class cls) { - for (Registry registry : registries) { - if (cls.isAssignableFrom(registry.getClass())) { - return (T) registry; - } - } - return null; - } - - public PolledEvent poll(long secondInterval) { - long msNow = clock.wallTime(); - List meters = new ArrayList<>(); - List measurements = new ArrayList<>(); - for (Registry registry : registries) { - SpectatorUtils.removeExpiredMeters(registry); - - for (Meter meter : registry) { - if (meter instanceof PeriodMeter) { - ((PeriodMeter) meter).calcMeasurements(msNow, secondInterval); - } - - meters.add(meter); - meter.measure().forEach(measurements::add); - } - } - - return new PolledEvent(meters, measurements); - } -} diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java index 748774578a9..231b0099ed4 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/TestMetricsBootstrap.java @@ -16,92 +16,69 @@ */ package org.apache.servicecomb.foundation.metrics; +import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN; +import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.DEFAULT_METRICS_WINDOW_TIME; +import static org.apache.servicecomb.foundation.metrics.MetricsBootstrapConfig.METRICS_WINDOW_TIME; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.metrics.registry.GlobalRegistry; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; -import com.netflix.spectator.api.Measurement; -import com.netflix.spectator.api.Meter; -import com.netflix.spectator.api.Registry; +import io.micrometer.core.instrument.MeterRegistry; import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mocked; public class TestMetricsBootstrap { - MetricsBootstrap bootstrap = new MetricsBootstrap(); - - GlobalRegistry globalRegistry = new GlobalRegistry(); + MetricsBootstrap bootstrap; EventBus eventBus = new EventBus(); + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach + public void setUp() { + Mockito.when(environment.getProperty(METRICS_WINDOW_TIME, int.class, DEFAULT_METRICS_WINDOW_TIME)) + .thenReturn(DEFAULT_METRICS_WINDOW_TIME); + Mockito.when(environment.getProperty( + CONFIG_LATENCY_DISTRIBUTION_MIN_SCOPE_LEN, int.class, 7)) + .thenReturn(7); + + MetricsBootstrapConfig config = new MetricsBootstrapConfig(environment); + bootstrap = new MetricsBootstrap(config); + bootstrap.setMetricsInitializers(List.of()); + } + @Test public void loadMetricsInitializers() { List initList = new ArrayList<>(); MetricsInitializer metricsInitializer = new MetricsInitializer() { @Override - public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) { + public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) { initList.add(this); } }; - new Expectations(SPIServiceUtils.class) { - { - SPIServiceUtils.getSortedService(MetricsInitializer.class); - result = Arrays.asList(metricsInitializer, metricsInitializer); - } - }; - - bootstrap.start(globalRegistry, eventBus); - bootstrap.shutdown(); - Assert.assertThat(initList, Matchers.contains(metricsInitializer, metricsInitializer)); - } - - @Test - public void pollMeters(@Mocked Registry registry, @Mocked Meter meter, @Mocked Measurement measurement, - @Mocked ScheduledExecutorService executor) { - List meters = Arrays.asList(meter); - globalRegistry.add(registry); - new Expectations(Executors.class) { - { - Executors.newScheduledThreadPool(1, (ThreadFactory) any); - result = executor; - registry.iterator(); - result = meters.iterator(); - meter.measure(); - result = Arrays.asList(measurement); - } - }; - bootstrap.start(globalRegistry, eventBus); - - PolledEvent result = new PolledEvent(null, null); - eventBus.register(new Object() { - @Subscribe - public void onEvent(PolledEvent event) { - result.setMeters(event.getMeters()); - result.setMeasurements(event.getMeasurements()); - } - }); + bootstrap.setMetricsInitializers(Arrays.asList(metricsInitializer, metricsInitializer)); - bootstrap.pollMeters(); + bootstrap.start(eventBus); bootstrap.shutdown(); - Assert.assertEquals(meters, result.getMeters()); - Assert.assertThat(result.getMeasurements(), Matchers.contains(measurement)); + + MatcherAssert.assertThat(initList, Matchers.contains(metricsInitializer, metricsInitializer)); } @Test - public void shutdown(@Mocked ScheduledExecutorService scheduledExecutorService) { + public void shutdown() { + ScheduledExecutorService scheduledExecutorService = Mockito.mock(ScheduledExecutorService.class); List destroyList = new ArrayList<>(); MetricsInitializer initializer1 = new MetricsInitializer() { @Override @@ -110,7 +87,7 @@ public int getOrder() { } @Override - public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) { + public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) { } @Override @@ -126,7 +103,7 @@ public int getOrder() { } @Override - public void init(GlobalRegistry globalRegistry, EventBus eventBus, MetricsBootstrapConfig config) { + public void init(MeterRegistry meterRegistry, EventBus eventBus, MetricsBootstrapConfig config) { } @Override @@ -134,23 +111,17 @@ public void destroy() { destroyList.add(this); } }; - - new Expectations(SPIServiceUtils.class) { - { - SPIServiceUtils.getSortedService(MetricsInitializer.class); - result = Arrays.asList(initializer1, initializer2); - } - }; + bootstrap.setMetricsInitializers(Arrays.asList(initializer1, initializer2)); Deencapsulation.setField(bootstrap, "executorService", scheduledExecutorService); bootstrap.shutdown(); - Assert.assertThat(destroyList, Matchers.contains(initializer2, initializer1)); + MatcherAssert.assertThat(destroyList, Matchers.contains(initializer2, initializer1)); } @Test public void shutdown_notStart() { - Assert.assertNull(Deencapsulation.getField(bootstrap, "executorService")); + Assertions.assertNull(Deencapsulation.getField(bootstrap, "executorService")); // should not throw exception bootstrap.shutdown(); diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java index d353660bbc5..fad079aaed5 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/health/TestHealthCheckerManager.java @@ -19,13 +19,13 @@ import java.util.Map; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; public class TestHealthCheckerManager { - private HealthChecker good = new HealthChecker() { + private final HealthChecker good = new HealthChecker() { @Override public String getName() { return "testBad"; @@ -37,7 +37,7 @@ public HealthCheckResult check() { } }; - private HealthChecker bad = new HealthChecker() { + private final HealthChecker bad = new HealthChecker() { @Override public String getName() { return "testGood"; @@ -49,7 +49,7 @@ public HealthCheckResult check() { } }; - @Before + @BeforeEach public void reset() { HealthCheckerManager.getInstance().unregister(good.getName()); HealthCheckerManager.getInstance().unregister(bad.getName()); @@ -58,14 +58,14 @@ public void reset() { @Test public void checkResultCount_None() { Map results = HealthCheckerManager.getInstance().check(); - Assert.assertEquals(0, results.size()); + Assertions.assertEquals(0, results.size()); } @Test public void checkResultCount_One() { HealthCheckerManager.getInstance().register(good); Map results = HealthCheckerManager.getInstance().check(); - Assert.assertEquals(1, results.size()); + Assertions.assertEquals(1, results.size()); } @Test @@ -73,7 +73,7 @@ public void checkResultCount_Both() { HealthCheckerManager.getInstance().register(good); HealthCheckerManager.getInstance().register(bad); Map results = HealthCheckerManager.getInstance().check(); - Assert.assertEquals(2, results.size()); + Assertions.assertEquals(2, results.size()); } @Test @@ -81,9 +81,9 @@ public void checkGoodResult() { HealthCheckerManager.getInstance().register(good); HealthCheckerManager.getInstance().register(bad); HealthCheckResult result = HealthCheckerManager.getInstance().check().get("testGood"); - Assert.assertEquals(true, result.isHealthy()); - Assert.assertEquals("good", result.getInformation()); - Assert.assertEquals("good component", result.getExtraData()); + Assertions.assertTrue(result.isHealthy()); + Assertions.assertEquals("good", result.getInformation()); + Assertions.assertEquals("good component", result.getExtraData()); } @Test @@ -91,8 +91,8 @@ public void checkBadResult() { HealthCheckerManager.getInstance().register(good); HealthCheckerManager.getInstance().register(bad); HealthCheckResult result = HealthCheckerManager.getInstance().check().get("testBad"); - Assert.assertEquals(false, result.isHealthy()); - Assert.assertEquals("bad", result.getInformation()); - Assert.assertEquals("bad component", result.getExtraData()); + Assertions.assertFalse(result.isHealthy()); + Assertions.assertEquals("bad", result.getInformation()); + Assertions.assertEquals("bad component", result.getExtraData()); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionConfig.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionConfig.java index 46c7452e1a1..5144896e015 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionConfig.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionConfig.java @@ -16,14 +16,10 @@ */ package org.apache.servicecomb.foundation.metrics.meter; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestLatencyDistributionConfig { - @Rule - public ExpectedException expectedException = ExpectedException.none(); @Test public void testValidProperty() { @@ -35,24 +31,26 @@ public void testValidProperty() { LatencyDistributionConfig config2 = new LatencyDistributionConfig(validProperty2); LatencyDistributionConfig config3 = new LatencyDistributionConfig(validProperty3); - Assert.assertEquals(4, config1.getScopeConfigs().size()); - Assert.assertEquals(4, config2.getScopeConfigs().size()); - Assert.assertEquals(4, config3.getScopeConfigs().size()); + Assertions.assertEquals(4, config1.getScopeConfigs().size()); + Assertions.assertEquals(4, config2.getScopeConfigs().size()); + Assertions.assertEquals(4, config3.getScopeConfigs().size()); } @Test public void testInValidProperty1() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("invalid latency scope, min=2, max=1."); - LatencyDistributionConfig latencyDistributionConfig = new LatencyDistributionConfig("2,1,10"); - Assert.assertEquals(0, latencyDistributionConfig.getScopeConfigs().size()); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + LatencyDistributionConfig latencyDistributionConfig = new LatencyDistributionConfig("2,1,10"); + Assertions.assertEquals(0, latencyDistributionConfig.getScopeConfigs().size()); + }); + Assertions.assertEquals("invalid latency scope, min=2, max=1.", exception.getMessage()); } @Test public void testInValidProperty2() { - expectedException.expect(NumberFormatException.class); - expectedException.expectMessage("For input string: \"a\""); - LatencyDistributionConfig latencyDistributionConfig = new LatencyDistributionConfig("a,1,10"); - Assert.assertEquals(0, latencyDistributionConfig.getScopeConfigs().size()); + NumberFormatException exception = Assertions.assertThrows(NumberFormatException.class, () -> { + LatencyDistributionConfig latencyDistributionConfig = new LatencyDistributionConfig("a,1,10"); + Assertions.assertEquals(0, latencyDistributionConfig.getScopeConfigs().size()); + }); + Assertions.assertEquals("For input string: \"a\"", exception.getMessage()); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java deleted file mode 100644 index d58c5c4580f..00000000000 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestLatencyDistributionMeter.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.foundation.metrics.meter; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.netflix.spectator.api.Id; -import com.netflix.spectator.api.Measurement; - -import mockit.Mocked; - -public class TestLatencyDistributionMeter { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void testMeasure(@Mocked Id id) { - LatencyDistributionMeter latencyDistributionMeter = new LatencyDistributionMeter(id, "0,1,3,10"); - latencyDistributionMeter.record(TimeUnit.MILLISECONDS.toNanos(1L)); - latencyDistributionMeter.record(TimeUnit.MILLISECONDS.toNanos(5L)); - latencyDistributionMeter.record(TimeUnit.MILLISECONDS.toNanos(2L)); - List measurements = new ArrayList<>(); - latencyDistributionMeter.calcMeasurements(measurements, 0L, 0L); - Assert.assertEquals(4, measurements.size()); - Assert.assertEquals(0, ((int) (measurements.get(0).value()))); - Assert.assertEquals(2, ((int) (measurements.get(1).value()))); - Assert.assertEquals(1, ((int) (measurements.get(2).value()))); - Assert.assertEquals(0, ((int) (measurements.get(3).value()))); - } -} diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java deleted file mode 100644 index 1d344973ea7..00000000000 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/meter/TestSimpleTimer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.foundation.metrics.meter; - -import org.junit.Assert; -import org.junit.Test; - -import com.netflix.spectator.api.SpectatorUtils; - -public class TestSimpleTimer { - SimpleTimer timer = new SimpleTimer(SpectatorUtils.createDefaultId("name")); - - @Test - public void measure() { - timer.record(2); - timer.record(4); - - Assert.assertFalse(timer.measure().iterator().hasNext()); - - timer.calcMeasurements(1, 2); - Assert.assertEquals( - "[Measurement(name:statistic=count,1,1.0), Measurement(name:statistic=totalTime,1,3.0000000000000004E-9), Measurement(name:statistic=max,1,4.0E-9)]", - timer.measure().toString()); - Assert.assertFalse(timer.hasExpired()); - Assert.assertEquals("name", timer.id().name()); - } -} diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java index 84a288a014c..46220069b97 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestDefaultTagFinder.java @@ -19,33 +19,34 @@ import java.util.Arrays; import java.util.List; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder; +import org.apache.servicecomb.foundation.metrics.publish.TagFinder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -import com.netflix.spectator.api.BasicTag; -import com.netflix.spectator.api.Tag; +import io.micrometer.core.instrument.Tag; public class TestDefaultTagFinder { TagFinder finder = new DefaultTagFinder("key"); @Test public void getTagKey() { - Assert.assertEquals("key", finder.getTagKey()); + Assertions.assertEquals("key", finder.getTagKey()); } @Test public void readSucc() { - Tag tag = new BasicTag("key", "value"); - List tags = Arrays.asList(new BasicTag("t1", "t1v"), + Tag tag = Tag.of("key", "value"); + List tags = Arrays.asList(Tag.of("t1", "t1v"), tag); - Assert.assertSame(tag, finder.find(tags)); + Assertions.assertSame(tag, finder.find(tags)); } @Test public void readFail() { - List tags = Arrays.asList(new BasicTag("t1", "t1v")); + List tags = Arrays.asList(Tag.of("t1", "t1v")); - Assert.assertNull(finder.find(tags)); + Assertions.assertNull(finder.find(tags)); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java index 51b6a56ab0f..60d77b4c75a 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementGroupConfig.java @@ -19,11 +19,14 @@ import java.util.List; import java.util.Map; +import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig; +import org.apache.servicecomb.foundation.metrics.publish.TagFinder; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; import mockit.Deencapsulation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestMeasurementGroupConfig { MeasurementGroupConfig config = new MeasurementGroupConfig(); @@ -32,7 +35,7 @@ public class TestMeasurementGroupConfig { @Test public void defaultConstruct() { - Assert.assertTrue(groups.isEmpty()); + Assertions.assertTrue(groups.isEmpty()); } @Test @@ -40,10 +43,9 @@ public void constructAddGroup() { config = new MeasurementGroupConfig("id", "tag1"); groups = Deencapsulation.getField(config, "groups"); - Assert.assertThat(groups.keySet(), Matchers.contains("id")); - Assert.assertThat(groups.get("id").stream().map(e -> { - return e.getTagKey(); - }).toArray(), Matchers.arrayContaining("tag1")); + MatcherAssert.assertThat(groups.keySet(), Matchers.contains("id")); + MatcherAssert.assertThat(groups.get("id").stream().map(TagFinder::getTagKey).toArray(), + Matchers.arrayContaining("tag1")); } @Test @@ -51,13 +53,9 @@ public void addGroup() { config.addGroup("id1", "tag1.1", "tag1.2"); config.addGroup("id2", "tag2.1", "tag2.2"); - Assert.assertThat(groups.keySet(), Matchers.contains("id2", "id1")); - Assert.assertThat(groups.get("id1").stream().map(e -> { - return e.getTagKey(); - }).toArray(), Matchers.arrayContaining("tag1.1", "tag1.2")); - Assert.assertThat(groups.get("id2").stream().map(e -> { - return e.getTagKey(); - }).toArray(), Matchers.arrayContaining("tag2.1", "tag2.2")); + MatcherAssert.assertThat(groups.keySet(), Matchers.containsInAnyOrder("id2", "id1")); + MatcherAssert.assertThat(groups.get("id1").stream().map(TagFinder::getTagKey).toArray(), Matchers.arrayContaining("tag1.1", "tag1.2")); + MatcherAssert.assertThat(groups.get("id2").stream().map(TagFinder::getTagKey).toArray(), Matchers.arrayContaining("tag2.1", "tag2.2")); } @Test @@ -65,8 +63,7 @@ public void findTagReaders() { config.addGroup("id1", "tag1.1", "tag1.2"); config.addGroup("id2", "tag2.1", "tag2.2"); - Assert.assertThat(config.findTagFinders("id2").stream().map(e -> { - return e.getTagKey(); - }).toArray(), Matchers.arrayContaining("tag2.1", "tag2.2")); + MatcherAssert.assertThat(config.findTagFinders("id2").stream().map(TagFinder::getTagKey).toArray(), + Matchers.arrayContaining("tag2.1", "tag2.2")); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java index 585fd9aeceb..be7681ae5cd 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementNode.java @@ -19,79 +19,85 @@ import java.util.HashMap; import java.util.Map; +import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Test; +import org.junit.jupiter.api.Assertions; -import com.netflix.spectator.api.Measurement; - +import io.micrometer.core.instrument.Measurement; +import io.micrometer.core.instrument.Meter.Id; +import io.micrometer.core.instrument.Meter.Type; +import io.micrometer.core.instrument.Tags; import mockit.Expectations; import mockit.Mocked; public class TestMeasurementNode { - MeasurementNode node = new MeasurementNode("name", null); + Id id = new Id("name", Tags.empty(), null, null, Type.OTHER); + + MeasurementNode node = new MeasurementNode("name", id, null); @Test public void getName() { - Assert.assertEquals("name", node.getName()); + Assertions.assertEquals("name", node.getName()); } @Test public void getChildren() { Map children = new HashMap<>(); - node = new MeasurementNode("name", children); + node = new MeasurementNode("name", id, children); - Assert.assertSame(children, node.getChildren()); + Assertions.assertSame(children, node.getChildren()); } @Test public void findChild_noChildren() { - Assert.assertNull(node.findChild("child")); + Assertions.assertNull(node.findChild("child")); } @Test public void findChild_multiLevel_noMiddleChildren(@Mocked Measurement measurement) { - MeasurementNode c1 = node.addChild("c1", measurement); - c1.addChild("c2", measurement); + MeasurementNode c1 = node.addChild("c1", id, measurement); + c1.addChild("c2", id, measurement); - Assert.assertNull(node.findChild("c1_notExist", "c2")); + Assertions.assertNull(node.findChild("c1_notExist", "c2")); } @Test public void findChild_multiLevel_ok(@Mocked Measurement measurement) { - MeasurementNode c1 = node.addChild("c1", measurement); - MeasurementNode c2 = c1.addChild("c2", measurement); + MeasurementNode c1 = node.addChild("c1", id, measurement); + MeasurementNode c2 = c1.addChild("c2", id, measurement); - Assert.assertSame(c2, node.findChild("c1", "c2")); + Assertions.assertSame(c2, node.findChild("c1", "c2")); } @Test public void addChild(@Mocked Measurement measurement) { - MeasurementNode c1 = node.addChild("c1", measurement); - MeasurementNode c2 = node.addChild("c2", measurement); + MeasurementNode c1 = node.addChild("c1", id, measurement); + MeasurementNode c2 = node.addChild("c2", id, measurement); - Assert.assertSame(c1, node.findChild("c1")); - Assert.assertSame(c2, node.findChild("c2")); + Assertions.assertSame(c1, node.findChild("c1")); + Assertions.assertSame(c2, node.findChild("c2")); } @Test public void getMeasurements(@Mocked Measurement measurement) { node.addMeasurement(measurement); - Assert.assertThat(node.getMeasurements(), Matchers.contains(measurement)); + MatcherAssert.assertThat(node.getMeasurements(), Matchers.contains(measurement)); } @Test public void summary(@Mocked Measurement measurement) { new Expectations() { { - measurement.value(); + measurement.getValue(); result = 10; } }; node.addMeasurement(measurement); node.addMeasurement(measurement); - Assert.assertEquals(20, node.summary(), 0); + Assertions.assertEquals(20, node.summary(), 0); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java index 21936960300..d21354be5b2 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestMeasurementTree.java @@ -18,31 +18,26 @@ import java.util.concurrent.TimeUnit; -import org.hamcrest.Matchers; -import org.junit.Assert; +import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder; +import org.apache.servicecomb.foundation.metrics.publish.MeasurementGroupConfig; +import org.apache.servicecomb.foundation.metrics.publish.MeasurementNode; +import org.apache.servicecomb.foundation.metrics.publish.MeasurementTree; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; -import com.netflix.spectator.api.DefaultRegistry; -import com.netflix.spectator.api.ManualClock; -import com.netflix.spectator.api.Registry; -import com.netflix.spectator.api.Statistic; -import com.netflix.spectator.api.Timer; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Statistic; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; public class TestMeasurementTree { MeasurementTree tree = new MeasurementTree(); - ManualClock clock = new ManualClock(); - - Registry registry = new DefaultRegistry(clock); + MeterRegistry registry = new SimpleMeterRegistry(); Timer timer; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before public void setup() { timer = registry.timer("id", @@ -59,37 +54,40 @@ public void setup() { @Test public void from() { - timer.record(10, TimeUnit.NANOSECONDS); - timer.record(2, TimeUnit.NANOSECONDS); + timer.record(10, TimeUnit.SECONDS); + timer.record(2, TimeUnit.SECONDS); - MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2", Statistic.count.key()); - tree.from(registry.iterator(), config); + MeasurementGroupConfig config = new MeasurementGroupConfig("id", "g1", "g2"); + tree.from(registry.getMeters().iterator(), config); - Assert.assertEquals(2, tree.getChildren().size()); + Assertions.assertEquals(2, tree.getChildren().size()); MeasurementNode node = tree.findChild("id", "g1v", "g2v"); - Assert.assertEquals(2d, node.findChild(Statistic.count.value()).getMeasurements().get(0).value(), 0); - Assert.assertEquals(12d, node.findChild(Statistic.totalTime.value()).getMeasurements().get(0).value(), 0); - Assert.assertEquals(0d, tree.findChild("id_notCare").summary(), 0); + Assertions.assertEquals(2d, + node.findChild(Statistic.COUNT.name()).getMeasurements().get(0).getValue(), 0); + Assertions.assertEquals(12d, + node.findChild(Statistic.TOTAL_TIME.name()).getMeasurements().get(0).getValue(), 0); + Assertions.assertEquals(0d, tree.findChild("id_notCare").summary(), 0); } @Test public void from_withSkipOnNull() { try { MeasurementGroupConfig config = new MeasurementGroupConfig("id", new DefaultTagFinder("notExist", true)); - tree.from(registry.iterator(), config); + tree.from(registry.getMeters().iterator(), config); } catch (Exception e) { - Assert.fail("should not throw exception"); + Assertions.fail("should not throw exception"); } } @Test public void from_failed() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("tag key \"notExist\" not exist in Measurement(id:g1=g1v:g2=g2v:statistic=count:t3=t3v:t4=t4v,0,0.0)")); - - MeasurementGroupConfig config = new MeasurementGroupConfig("id", "notExist"); - tree.from(registry.iterator(), config); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + MeasurementGroupConfig config = new MeasurementGroupConfig("id", "notExist"); + tree.from(registry.getMeters().iterator(), config); + }); + Assertions.assertEquals( + "tag key \"notExist\" not exist in MeterId{name='id', tags=[tag(g1=g1v),tag(g2=g2v),tag(t3=t3v),tag(t4=t4v)]}", + exception.getMessage()); } } diff --git a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java index 1f5551b04a8..2a0d960637a 100644 --- a/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java +++ b/foundations/foundation-metrics/src/test/java/org/apache/servicecomb/foundation/metrics/publish/spectator/TestTagFinder.java @@ -16,48 +16,39 @@ */ package org.apache.servicecomb.foundation.metrics.publish.spectator; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.apache.servicecomb.foundation.metrics.publish.DefaultTagFinder; +import org.apache.servicecomb.foundation.metrics.publish.TagFinder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestTagFinder { - @Rule - public ExpectedException expectedException = ExpectedException.none(); @Test public void buildFromString() { String name = "key"; TagFinder finder = TagFinder.build(name); - Assert.assertEquals(name, finder.getTagKey()); - Assert.assertEquals(DefaultTagFinder.class, finder.getClass()); + Assertions.assertEquals(name, finder.getTagKey()); + Assertions.assertEquals(DefaultTagFinder.class, finder.getClass()); } @Test public void buildFromTagFinder() { TagFinder finder = new DefaultTagFinder("key"); - Assert.assertSame(finder, TagFinder.build(finder)); + Assertions.assertSame(finder, TagFinder.build(finder)); DefaultTagFinder tagFinder = new DefaultTagFinder("key", true); - Assert.assertSame(tagFinder, TagFinder.build(tagFinder)); + Assertions.assertSame(tagFinder, TagFinder.build(tagFinder)); } @Test public void buildFromInvalidType() { - expectedException.expect(IllegalArgumentException.class); - expectedException - .expectMessage(Matchers.is("only support String or TagFinder, but got " + Integer.class.getName())); - - TagFinder.build(1); + IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> TagFinder.build(1)); + Assertions.assertEquals("only support String or TagFinder, but got " + Integer.class.getName(), exception.getMessage()); } @Test public void buildFromNull() { - expectedException.expect(IllegalArgumentException.class); - expectedException - .expectMessage(Matchers.is("only support String or TagFinder, but got null")); - - TagFinder.build(null); + IllegalArgumentException exception = Assertions.assertThrows(IllegalArgumentException.class, () -> TagFinder.build(null)); + Assertions.assertEquals("only support String or TagFinder, but got null", exception.getMessage()); } } diff --git a/foundations/foundation-metrics/src/test/resources/log4j.properties b/foundations/foundation-metrics/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/foundations/foundation-metrics/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/foundations/foundation-protobuf/README.md b/foundations/foundation-protobuf/README.md index 8f3526373c7..c225e89dc87 100644 --- a/foundations/foundation-protobuf/README.md +++ b/foundations/foundation-protobuf/README.md @@ -1,9 +1,9 @@ # Overview -There are many existing protobuf codecs, but all of them are not suit for us. -ServiceComb data model is just POJO, not bind to any codec mechanism, so we had to create new one: +There are many existing protobuf codecs, but all of them are not suit for us. +ServiceComb data model is just POJO, not bind to any codec mechanism, so we had to create new one: -| | ServiceComb | protobuf | protostuff | jackson | -| -------------------------------------------------------- | :-----------: | :------: | :------------: | :-----: | +| | ServiceComb | protobuf | protostuff | jackson | +| -------------------------------------------------------- | :-----------: | :------: | :------------: | :-----: | | generate code | no need
just POJO | must
100+ lines IDL, generate 10000+ java code | no need
POJO with Annotation(eg:@Tag) | no need | | support null element in repeated field | no | no | not compatible | no | | support "oneOf" | no | yes | no | no | @@ -21,25 +21,25 @@ ServiceComb data model is just POJO, not bind to any codec mechanism, so we had | serialize not repeated number field ignore default value | yes | yes | no | no | | serialize from map model | yes | no | no | no | | deserialize to map model | yes | no | no | no | - + # Usage -## Create factory - one factory instance globally is enough +## Create factory + one factory instance globally is enough ```java ProtoMapperFactory factory = new ProtoMapperFactory(); ``` ## Load proto definition - create mapper instance for each proto definition -- load from classpath + create mapper instance for each proto definition +- load from classpath ```java ProtoMapper protoMapper = factory.createFromName("protobuf.proto"); ``` -- load from proto content +- load from proto content ```java ProtoMapper protoMapper = factory.createFromContent(protoContent); ``` ## Serialize -serializer is reusable and thread safe +serializer is reusable and thread safe Assuming you have a proto definition ```proto message User { @@ -50,10 +50,9 @@ and a POJO class ```java public class User { private String name; - // getter and setter + // getter and setter } ``` -```java RootSerializer serializer = protoMapper.createRootSerializer("User", User.class); User user = new User(); @@ -63,11 +62,13 @@ byte[] pojoBytes= serializer.serialize(user); Map map = new HashMap<>(); map.put("name", "userName"); byte[] mapBytes = serializer.serialize(map); +```java + // pojoBytes equals mapBytes ``` ## Deserialize -deserializer is reusable and thread safe +deserializer is reusable and thread safe ```java RootDeserializer pojoDeserializer = protoMapper.createRootDeserializer("User", User.class); RootDeserializer> mapDeserializer = protoMapper.createRootDeserializer("User", Map.class); @@ -86,67 +87,67 @@ Map map = mapDeserializer.deserialize(bytes); 2.protoStuff some scenes, there is no field but have getter or setter, so we can not use unsafe to access field so we disable protoStuff unsafe feature - + for repeated fields, protoStuff have better performance, but not compatible to protobuf - + 3.jackson not support map/any/recursive, ignore related fields 4.serialize result size ScbStrong/ScbWeak/Protobuf have the same and smaller size, because skip all default/null value -Empty: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 519 515 240 288 1242 -ser len : 36 0 0 0 56 -deser time(ms): 161 69 10 516 486 -deser->ser len: 36 0 0 0 56 -ser+deser(ms) : 680 584 250 804 1728 - -Scalars: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 557 529 328 262 1357 -ser len : 56 24 24 24 76 -deser time(ms): 181 141 115 527 504 -deser->ser len: 56 24 24 24 76 -ser+deser(ms) : 738 670 443 789 1861 - -Pojo: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 571 574 276 309 1304 -ser len : 46 10 10 10 66 -deser time(ms): 230 69 112 668 537 -deser->ser len: 46 10 10 10 66 -ser+deser(ms) : 801 643 388 977 1841 - -SimpleList: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 590 609 296 637 1320 -ser len : 68 32 32 32 88 -deser time(ms): 233 105 122 2226 541 -deser->ser len: 68 32 32 32 88 -ser+deser(ms) : 823 714 418 2863 1861 - -PojoList: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 609 632 319 2777 1407 -ser len : 56 20 20 20 76 -deser time(ms): 244 134 173 2287 679 -deser->ser len: 56 20 20 20 76 -ser+deser(ms) : 853 766 492 5064 2086 - -Map: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 746 772 491 1079 1298 -ser len : 92 54 54 54 56 -deser time(ms): 522 427 468 1031 422 -deser->ser len: 92 54 54 54 56 -ser+deser(ms) : 1268 1199 959 2110 1720 - -Mixed: - Protostuff ScbStrong ScbWeak Protobuf Jackson -ser time(ms) : 1686 1999 2034 2112 2537 -ser len : 479 505 505 505 489 -deser time(ms): 1969 2154 2923 2984 3316 -deser->ser len: 479 505 505 505 489 -ser+deser(ms) : 3655 4153 4957 5096 5853 -``` \ No newline at end of file +Empty: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 519 515 240 288 1242 +serialize len : 36 0 0 0 56 +deserialize time(ms): 161 69 10 516 486 +deserialize->serialize len: 36 0 0 0 56 +serialize+deserialize(ms) : 680 584 250 804 1728 + +Scalars: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 557 529 328 262 1357 +serialize len : 56 24 24 24 76 +deserialize time(ms): 181 141 115 527 504 +deserialize->serialize len: 56 24 24 24 76 +serialize+deserialize(ms) : 738 670 443 789 1861 + +Pojo: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 571 574 276 309 1304 +serialize len : 46 10 10 10 66 +deserialize time(ms): 230 69 112 668 537 +deserialize->serialize len: 46 10 10 10 66 +serialize+deserialize(ms) : 801 643 388 977 1841 + +SimpleList: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 590 609 296 637 1320 +serialize len : 68 32 32 32 88 +deserialize time(ms): 233 105 122 2226 541 +deserialize->serialize len: 68 32 32 32 88 +serialize+deserialize(ms) : 823 714 418 2863 1861 + +PojoList: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 609 632 319 2777 1407 +serialize len : 56 20 20 20 76 +deserialize time(ms): 244 134 173 2287 679 +deserialize->serialize len: 56 20 20 20 76 +serialize+deserialize(ms) : 853 766 492 5064 2086 + +Map: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 746 772 491 1079 1298 +serialize len : 92 54 54 54 56 +deserialize time(ms): 522 427 468 1031 422 +deserialize->serialize len: 92 54 54 54 56 +serialize+deserialize(ms) : 1268 1199 959 2110 1720 + +Mixed: + Protostuff ScbStrong ScbWeak Protobuf Jackson +serialize time(ms) : 1686 1999 2034 2112 2537 +serialize len : 479 505 505 505 489 +deserialize time(ms): 1969 2154 2923 2984 3316 +deserialize->serialize len: 479 505 505 505 489 +serialize+deserialize(ms) : 3655 4153 4957 5096 5853 +``` diff --git a/foundations/foundation-protobuf/pom.xml b/foundations/foundation-protobuf/pom.xml index bb7253e1622..cb8662c7bfb 100644 --- a/foundations/foundation-protobuf/pom.xml +++ b/foundations/foundation-protobuf/pom.xml @@ -21,7 +21,7 @@ foundations org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -50,10 +50,11 @@ jsr305 - + com.google.protobuf protobuf-java + test @@ -67,4 +68,35 @@ - \ No newline at end of file + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + ${protobuf-maven-plugin.version} + + com.google.protobuf:protoc:${protoc3-maven-plugin.version}:exe:${os.detected.classifier} + true + grpc-java + io.grpc:protoc-gen-grpc-java:${protoc-gen-grpc-java-plugin.version}:exe:${os.detected.classifier} + src/test/resources + + **/jacksonRoot.proto + **/method.proto + **/model.proto + + + + + generate-test-sources + + test-compile + + + + + + + + diff --git a/foundations/foundation-protobuf/src/main/java/io/protostuff/ByteArrayInputEx.java b/foundations/foundation-protobuf/src/main/java/io/protostuff/ByteArrayInputEx.java index 98a121173c6..f496a709426 100644 --- a/foundations/foundation-protobuf/src/main/java/io/protostuff/ByteArrayInputEx.java +++ b/foundations/foundation-protobuf/src/main/java/io/protostuff/ByteArrayInputEx.java @@ -3,7 +3,7 @@ //------------------------------------------------------------------------ //Licensed 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 +//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, diff --git a/foundations/foundation-protobuf/src/main/java/io/protostuff/OutputEx.java b/foundations/foundation-protobuf/src/main/java/io/protostuff/OutputEx.java index 2d201c85f31..aefd1bfcc7d 100644 --- a/foundations/foundation-protobuf/src/main/java/io/protostuff/OutputEx.java +++ b/foundations/foundation-protobuf/src/main/java/io/protostuff/OutputEx.java @@ -154,7 +154,7 @@ default void writePackedInt64(long value) throws IOException { void writeScalarUInt64(int tag, int tagSize, long value) throws IOException; - void writePackedSInt32(final int value) throws IOException; + void writePackedSInt32(int value) throws IOException; void writeScalarSInt32(int tag, int tagSize, int value) throws IOException; diff --git a/foundations/foundation-protobuf/src/main/java/io/protostuff/ProtobufOutputEx.java b/foundations/foundation-protobuf/src/main/java/io/protostuff/ProtobufOutputEx.java index f4a82d3fa6b..8c47ab44271 100644 --- a/foundations/foundation-protobuf/src/main/java/io/protostuff/ProtobufOutputEx.java +++ b/foundations/foundation-protobuf/src/main/java/io/protostuff/ProtobufOutputEx.java @@ -54,7 +54,7 @@ public ProtobufOutputEx clear() { } @Override - public final void writeInt32(int tag, int tagSize, int value) { + public void writeInt32(int tag, int tagSize, int value) { if (value < 0) { tail = writeTagAndRawVarInt64(tag, tagSize, value, this, tail); return; @@ -64,72 +64,72 @@ public final void writeInt32(int tag, int tagSize, int value) { } @Override - public final void writeUInt32(int tag, int tagSize, int value) { + public void writeUInt32(int tag, int tagSize, int value) { tail = writeTagAndRawVarInt32(tag, tagSize, value, this, tail); } @Override - public final void writeSInt32(int tag, int tagSize, int value) { + public void writeSInt32(int tag, int tagSize, int value) { tail = writeTagAndRawVarInt32(tag, tagSize, encodeZigZag32(value), this, tail); } @Override - public final void writeFixed32(int tag, int tagSize, int value) { + public void writeFixed32(int tag, int tagSize, int value) { tail = writeTagAndRawLittleEndian32(tag, tagSize, value, this, tail); } @Override - public final void writeSFixed32(int tag, int tagSize, int value) { + public void writeSFixed32(int tag, int tagSize, int value) { tail = writeTagAndRawLittleEndian32(tag, tagSize, value, this, tail); } @Override - public final void writeInt64(int tag, int tagSize, long value) { + public void writeInt64(int tag, int tagSize, long value) { tail = writeTagAndRawVarInt64(tag, tagSize, value, this, tail); } @Override - public final void writeUInt64(int tag, int tagSize, long value) { + public void writeUInt64(int tag, int tagSize, long value) { tail = writeTagAndRawVarInt64(tag, tagSize, value, this, tail); } @Override - public final void writeSInt64(int tag, int tagSize, long value) { + public void writeSInt64(int tag, int tagSize, long value) { tail = writeTagAndRawVarInt64(tag, tagSize, encodeZigZag64(value), this, tail); } @Override - public final void writeFixed64(int tag, int tagSize, long value) { + public void writeFixed64(int tag, int tagSize, long value) { tail = writeTagAndRawLittleEndian64(tag, tagSize, value, this, tail); } @Override - public final void writeSFixed64(int tag, int tagSize, long value) { + public void writeSFixed64(int tag, int tagSize, long value) { tail = writeTagAndRawLittleEndian64(tag, tagSize, value, this, tail); } @Override - public final void writeFloat(int tag, int tagSize, float value) { + public void writeFloat(int tag, int tagSize, float value) { tail = writeTagAndRawLittleEndian32(tag, tagSize, Float.floatToRawIntBits(value), this, tail); } @Override - public final void writeDouble(int tag, int tagSize, double value) { + public void writeDouble(int tag, int tagSize, double value) { tail = writeTagAndRawLittleEndian64(tag, tagSize, Double.doubleToRawLongBits(value), this, tail); } @Override - public final void writeBool(int tag, int tagSize, boolean value) { + public void writeBool(int tag, int tagSize, boolean value) { tail = writeTagAndRawVarInt32(tag, tagSize, value ? 1 : 0, this, tail); } @Override - public final void writeEnum(int tag, int tagSize, int number) { + public void writeEnum(int tag, int tagSize, int number) { writeInt32(tag, tagSize, number); } @Override - public final void writeString(int tag, int tagSize, String value) { + public void writeString(int tag, int tagSize, String value) { tail = writeUTF8VarDelimited( value, this, @@ -137,12 +137,12 @@ public final void writeString(int tag, int tagSize, String value) { } @Override - public final void writeBytes(int tag, int tagSize, ByteString value) { + public void writeBytes(int tag, int tagSize, ByteString value) { writeByteArray(tag, tagSize, value.getBytes()); } @Override - public final void writeByteArray(int tag, int tagSize, byte[] bytes) { + public void writeByteArray(int tag, int tagSize, byte[] bytes) { tail = writeTagAndByteArray( tag, tagSize, bytes, 0, bytes.length, @@ -151,7 +151,7 @@ public final void writeByteArray(int tag, int tagSize, byte[] bytes) { } @Override - public final void writeByteRange(boolean utf8String, int tag, int tagSize, byte[] value, int offset, int length) { + public void writeByteRange(boolean utf8String, int tag, int tagSize, byte[] value, int offset, int length) { tail = writeTagAndByteArray( tag, tagSize, value, offset, length, @@ -160,7 +160,7 @@ public final void writeByteRange(boolean utf8String, int tag, int tagSize, byte[ } @Override - public final void writeObject(final int tag, int tagSize, final T value, final SchemaWriter schemaWriter) + public void writeObject(final int tag, int tagSize, final T value, final SchemaWriter schemaWriter) throws IOException { final LinkedBuffer lastBuffer; @@ -642,7 +642,7 @@ public static long encodeZigZag64(final long n) { * Writes a ByteBuffer field. */ @Override - public final void writeBytes(int tag, int tagSize, ByteBuffer value) { + public void writeBytes(int tag, int tagSize, ByteBuffer value) { writeByteRange(false, tag, tagSize, value.array(), value.arrayOffset() + value.position(), value.remaining()); } @@ -651,7 +651,7 @@ public void toOutputStream(OutputStream outputStream) throws IOException { } @Override - public final void writePackedInt32(int value) { + public void writePackedInt32(int value) { if (value >= 0) { tail = writeRawVarInt32(value, this, tail); return; @@ -661,33 +661,33 @@ public final void writePackedInt32(int value) { } @Override - public final void writeScalarInt32(int tag, int tagSize, int value) { + public void writeScalarInt32(int tag, int tagSize, int value) { if (value != 0) { writeInt32(tag, tagSize, value); } } @Override - public final void writeScalarInt64(int tag, int tagSize, long value) { + public void writeScalarInt64(int tag, int tagSize, long value) { if (value != 0) { writeInt64(tag, tagSize, value); } } @Override - public final void writePackedUInt32(int value) { + public void writePackedUInt32(int value) { tail = writeRawVarInt32(value, this, tail); } @Override - public final void writeScalarUInt32(int tag, int tagSize, int value) { + public void writeScalarUInt32(int tag, int tagSize, int value) { if (value != 0) { writeUInt32(tag, tagSize, value); } } @Override - public final void writePackedUInt64(long value) { + public void writePackedUInt64(long value) { final int size = computeRawVarint64Size(value); if (tail.offset + size > tail.buffer.length) { @@ -711,33 +711,33 @@ public final void writePackedUInt64(long value) { } @Override - public final void writeScalarUInt64(int tag, int tagSize, long value) { + public void writeScalarUInt64(int tag, int tagSize, long value) { if (value != 0) { writeUInt64(tag, tagSize, value); } } @Override - public final void writePackedSInt32(int value) { + public void writePackedSInt32(int value) { tail = writeRawVarInt32(encodeZigZag32(value), this, tail); } @Override - public final void writeScalarSInt32(int tag, int tagSize, int value) { + public void writeScalarSInt32(int tag, int tagSize, int value) { if (value != 0) { writeSInt32(tag, tagSize, value); } } @Override - public final void writeScalarSInt64(int tag, int tagSize, long value) { + public void writeScalarSInt64(int tag, int tagSize, long value) { if (value != 0) { writeSInt64(tag, tagSize, value); } } @Override - public final void writePackedFixed32(int value) { + public void writePackedFixed32(int value) { final int size = LITTLE_ENDIAN_32_SIZE; if (tail.offset + size > tail.buffer.length) { @@ -756,14 +756,14 @@ public final void writePackedFixed32(int value) { } @Override - public final void writeScalarFixed32(int tag, int tagSize, int value) { + public void writeScalarFixed32(int tag, int tagSize, int value) { if (value != 0) { writeFixed32(tag, tagSize, value); } } @Override - public final void writePackedFixed64(long value) { + public void writePackedFixed64(long value) { final int size = LITTLE_ENDIAN_64_SIZE; if (tail.offset + size > tail.buffer.length) { @@ -786,42 +786,42 @@ public final void writePackedFixed64(long value) { } @Override - public final void writeScalarFixed64(int tag, int tagSize, long value) { + public void writeScalarFixed64(int tag, int tagSize, long value) { if (value != 0) { writeFixed64(tag, tagSize, value); } } @Override - public final void writeScalarSFixed32(int tag, int tagSize, int value) { + public void writeScalarSFixed32(int tag, int tagSize, int value) { if (value != 0) { writeSFixed32(tag, tagSize, value); } } @Override - public final void writeScalarSFixed64(int tag, int tagSize, long value) { + public void writeScalarSFixed64(int tag, int tagSize, long value) { if (value != 0) { writeSFixed64(tag, tagSize, value); } } @Override - public final void writeScalarFloat(int tag, int tagSize, float value) { + public void writeScalarFloat(int tag, int tagSize, float value) { if (value != 0) { writeFloat(tag, tagSize, value); } } @Override - public final void writeScalarDouble(int tag, int tagSize, double value) { + public void writeScalarDouble(int tag, int tagSize, double value) { if (value != 0) { writeDouble(tag, tagSize, value); } } @Override - public final void writePackedBool(boolean value) { + public void writePackedBool(boolean value) { final int size = 1; if (tail.offset + size > tail.buffer.length) { @@ -837,18 +837,18 @@ public final void writePackedBool(boolean value) { } @Override - public final void writeScalarBool(int tag, int tagSize, boolean value) { + public void writeScalarBool(int tag, int tagSize, boolean value) { if (value) { writeBool(tag, tagSize, value); } } @Override - public final void writeScalarEnum(int tag, int tagSize, int value) { + public void writeScalarEnum(int tag, int tagSize, int value) { writeScalarInt32(tag, tagSize, value); } - public final void writeScalarString(int tag, int tagSize, String value) { + public void writeScalarString(int tag, int tagSize, String value) { writeString(tag, tagSize, value); } } diff --git a/foundations/foundation-protobuf/src/main/java/io/protostuff/package-info.java b/foundations/foundation-protobuf/src/main/java/io/protostuff/package-info.java index a518c0c53b2..fad90514b8d 100644 --- a/foundations/foundation-protobuf/src/main/java/io/protostuff/package-info.java +++ b/foundations/foundation-protobuf/src/main/java/io/protostuff/package-info.java @@ -33,4 +33,4 @@ *
*/ -package io.protostuff; \ No newline at end of file +package io.protostuff; diff --git a/foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/HashFieldMapEx.java b/foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/HashFieldMapEx.java index 5e1f71e206d..d810233ed05 100644 --- a/foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/HashFieldMapEx.java +++ b/foundations/foundation-protobuf/src/main/java/io/protostuff/runtime/HashFieldMapEx.java @@ -60,7 +60,7 @@ public HashFieldMapEx(Collection> fields) { List> fieldList = new ArrayList<>(fields.size()); fieldList.addAll(fields); - Collections.sort(fieldList, Comparator.comparingInt(FieldSchema::getFieldNumber)); + fieldList.sort(Comparator.comparingInt(FieldSchema::getFieldNumber)); this.fields = Collections.unmodifiableList(fieldList); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapperFactory.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapperFactory.java index 15cf9940766..3081ffe4c5e 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapperFactory.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/ProtoMapperFactory.java @@ -28,11 +28,11 @@ public class ProtoMapperFactory { // 1.to support "any" type // 2.to find bean properties - private ObjectMapper jsonMapper = new ObjectMapper(); + private final ObjectMapper jsonMapper = new ObjectMapper(); - private BeanDescriptorManager beanDescriptorManager; + private final BeanDescriptorManager beanDescriptorManager; - private ProtoParser protoParser = new ProtoParser(); + private final ProtoParser protoParser = new ProtoParser(); public ProtoMapperFactory() { jsonMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/RootSerializer.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/RootSerializer.java index 0593cf12c99..f4fd245576a 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/RootSerializer.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/RootSerializer.java @@ -23,7 +23,7 @@ import io.protostuff.SchemaEx; public class RootSerializer { - private SchemaEx schema; + private final SchemaEx schema; public RootSerializer(SchemaEx schema) { this.schema = schema; diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java index cc2c0ba0b0e..117d82d1300 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/ProtoConst.java @@ -31,31 +31,31 @@ public final class ProtoConst { private ProtoConst() { } - public static String ANNOTATION_WRAP_ARGUMENTS = "@WrapArguments"; + public static final String ANNOTATION_WRAP_ARGUMENTS = "@WrapArguments"; - public static String ANNOTATION_WRAP_PROPERTY = "@WrapProperty"; + public static final String ANNOTATION_WRAP_PROPERTY = "@WrapProperty"; public static String ANNOTATION_RPC = "@Rpc"; - public static String PACK_SCHEMA = "type.googleapis.com/"; + public static final String PACK_SCHEMA = "type.googleapis.com/"; - public static String JSON_SCHEMA = "json/"; + public static final String JSON_SCHEMA = "json/"; - public static String JSON_ID_NAME = "@type"; + public static final String JSON_ID_NAME = "@type"; - public static JavaType MAP_TYPE = TypeFactory.defaultInstance().constructType(LinkedHashMap.class); + public static final JavaType MAP_TYPE = TypeFactory.defaultInstance().constructType(LinkedHashMap.class); - public static JavaType LIST_TYPE = TypeFactory.defaultInstance().constructType(ArrayList.class); + public static final JavaType LIST_TYPE = TypeFactory.defaultInstance().constructType(ArrayList.class); - public static JavaType OBJECT_TYPE = TypeFactory.defaultInstance().constructType(Object.class); + public static final JavaType OBJECT_TYPE = TypeFactory.defaultInstance().constructType(Object.class); - public static Proto ANY_PROTO; + public static final Proto ANY_PROTO; - public static Message ANY; + public static final Message ANY; - public static Proto EMPTY_PROTO; + public static final Proto EMPTY_PROTO; - public static Message EMPTY; + public static final Message EMPTY; static { ProtoParser protoParser = new ProtoParser(); diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/ArgumentsBeanDescriptor.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/ArgumentsBeanDescriptor.java deleted file mode 100644 index bb93036187f..00000000000 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/ArgumentsBeanDescriptor.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.foundation.protobuf.internal.bean; - -import com.fasterxml.jackson.databind.type.SimpleType; - -public class ArgumentsBeanDescriptor extends SimpleType { - private static final long serialVersionUID = 1L; - - private BeanDescriptor beanDescriptor; - - public ArgumentsBeanDescriptor(BeanDescriptor beanDescriptor) { - super(ArgumentsBeanDescriptor.class); - this.beanDescriptor = beanDescriptor; - } - - public BeanDescriptor getBeanDescriptor() { - return beanDescriptor; - } - - @Override - public boolean equals(Object o) { - throw new IllegalStateException("DO NOT invoke this method"); - } -} diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptor.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptor.java index 752d9c17584..f6e15e03363 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptor.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptor.java @@ -33,7 +33,7 @@ public class BeanDescriptor { private JavaType javaType; - private Map propertyDescriptors = new HashMap<>(); + private final Map propertyDescriptors = new HashMap<>(); public JavaType getJavaType() { return javaType; diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptorManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptorManager.java index 58945b00766..11a1aa221ec 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptorManager.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/bean/BeanDescriptorManager.java @@ -26,9 +26,9 @@ import com.fasterxml.jackson.databind.type.TypeFactory; public class BeanDescriptorManager { - private SerializationConfig serializationConfig; + private final SerializationConfig serializationConfig; - private Map beanDescriptors = new ConcurrentHashMapEx<>(); + private final Map beanDescriptors = new ConcurrentHashMapEx<>(); public BeanDescriptorManager(SerializationConfig serializationConfig) { this.serializationConfig = serializationConfig; diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ContentFileReader.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ContentFileReader.java index e330d10b98a..89bf2b43282 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ContentFileReader.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ContentFileReader.java @@ -16,29 +16,27 @@ */ package org.apache.servicecomb.foundation.protobuf.internal.parser; -import javax.annotation.Nullable; - import org.antlr.v4.runtime.CharStream; import org.antlr.v4.runtime.CharStreams; import io.protostuff.compiler.parser.FileReader; public class ContentFileReader implements FileReader { - private FileReader importReader; - private String content; + private final FileReader importReader; + + private final String content; - private boolean contentReaded; + private boolean contentRead; public ContentFileReader(FileReader importReader, String content) { this.importReader = importReader; this.content = content; } - @Nullable @Override public CharStream read(String contentOrName) { - if (!contentReaded) { - contentReaded = true; + if (!contentRead) { + contentRead = true; return CharStreams.fromString(this.content); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ProtoParser.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ProtoParser.java index d574bf9c585..e25e9b3f0aa 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ProtoParser.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/parser/ProtoParser.java @@ -34,13 +34,13 @@ public class ProtoParser { private static final String DEFAULT_PROTO_NAME = "default.proto"; - private Injector injector = Guice.createInjector(new ParserModule()); + private final Injector injector = Guice.createInjector(new ParserModule()); - private FileReaderFactory fileReaderFactory = injector.getInstance(FileReaderFactory.class); + private final FileReaderFactory fileReaderFactory = injector.getInstance(FileReaderFactory.class); - private FileReader defaultReader = fileReaderFactory.create(Collections.emptyList()); + private final FileReader defaultReader = fileReaderFactory.create(Collections.emptyList()); - private FileDescriptorLoader loader = injector.getInstance(FileDescriptorLoader.class); + private final FileDescriptorLoader loader = injector.getInstance(FileDescriptorLoader.class); public Proto parseFromContent(String content) { // io.protostuff.compiler.parser.ClasspathFileReader will use ContextClassLoader load resource, but in some environment, diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/ArgumentsWrapperMessageSchema.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/ArgumentsWrapperMessageSchema.java deleted file mode 100644 index f2222ca77aa..00000000000 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/ArgumentsWrapperMessageSchema.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.foundation.protobuf.internal.schema; - -public class ArgumentsWrapperMessageSchema { -// private FieldSchema[] fields; -// -// public ArgumentsWrapperMessageSchema(ProtoMapper protoMapper, Message message, JavaType javaType) { -// super(protoMapper, message, javaType); -// } -// -// @Override -// public void initSerializer(SchemaCreateContext context) { -// super.initSerializer(context); -// -// List> list = getFields(); -// this.fields = list.toArray(new FieldSchema[list.size()]); -// } -// -// @Override -// public void writeTo(OutputEx output, Object message) throws IOException { -// Object[] arguments = (Object[]) message; -// int fieldCount = fields.length; -// if (fieldCount > arguments.length) { -// fieldCount = arguments.length; -// } -// for (int fieldIdx = 0; fieldIdx < fieldCount; fieldIdx++) { -// FieldSchema field = fields[fieldIdx]; -// Object value = arguments[fieldIdx]; -// -// field.writeTo(output, value); -// } -// } -} diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/EnumMeta.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/EnumMeta.java index d25cc8833d2..79a842a68c5 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/EnumMeta.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/EnumMeta.java @@ -26,11 +26,11 @@ import io.protostuff.compiler.model.Field; public class EnumMeta { - private Map enumNameToValueMap = new HashMap<>(); + private final Map enumNameToValueMap = new HashMap<>(); // key is idl defined enum value // value is Enum or null - private Map> enumValues = new HashMap<>(); + private final Map> enumValues = new HashMap<>(); public EnumMeta(Field protoField, JavaType javaType) { io.protostuff.compiler.model.Enum enumType = (io.protostuff.compiler.model.Enum) protoField.getType(); diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java index ca7b0e2fbcb..5d583954ca0 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/SchemaManager.java @@ -53,17 +53,16 @@ public abstract class SchemaManager { protected final Proto proto; // key is canonical message name + ":" + canonical type name - protected Map> canonicalSchemas = new ConcurrentHashMapEx<>(); + protected final Map> canonicalSchemas = new ConcurrentHashMapEx<>(); + + // key is canonical message name + ":" + canonical type name + protected final Map> canonicalSchemasCreated = new ConcurrentHashMapEx<>(); public SchemaManager(ProtoMapper protoMapper) { this.protoMapper = protoMapper; this.proto = protoMapper.getProto(); } - public Map> getCanonicalSchemas() { - return canonicalSchemas; - } - protected String generateCacheKey(Message message, JavaType javaType) { return message.getCanonicalName() + ":" + javaType.toCanonical(); } @@ -72,44 +71,25 @@ protected String generateCacheKey(Message message, JavaType javaType) { protected abstract SchemaEx newMessageSchema(Message message, Map types); - /** - * - * @param protoField - * @param propertyDescriptor provide getter/setter/javaType - * @return - */ protected abstract FieldSchema createScalarField(Field protoField, PropertyDescriptor propertyDescriptor); @SuppressWarnings("unchecked") protected SchemaEx getOrCreateMessageSchema(Message message, Map types) { String cacheKey = generateCacheKey(message, ProtoConst.MAP_TYPE); - SchemaEx messageSchema = (SchemaEx) canonicalSchemas.get(cacheKey); - if (messageSchema == null) { - // messageSchema already put into canonicalSchemas inside createMessageSchema - messageSchema = createMessageSchema(message, types); - } - return messageSchema; + return (SchemaEx) canonicalSchemasCreated.computeIfAbsent(cacheKey, key -> createMessageSchema(message, types)); } @SuppressWarnings("unchecked") protected SchemaEx getOrCreateMessageSchema(Message message, JavaType javaType) { String cacheKey = generateCacheKey(message, javaType); - SchemaEx messageSchema = (SchemaEx) canonicalSchemas.get(cacheKey); - if (messageSchema == null) { - // messageSchema already put into canonicalSchemas inside createMessageSchema - messageSchema = createMessageSchema(message, javaType); - } - return messageSchema; + return (SchemaEx) canonicalSchemasCreated.computeIfAbsent(cacheKey, + key -> createMessageSchema(message, javaType)); } @SuppressWarnings("unchecked") - protected SchemaEx findSchema(String key) { - return (SchemaEx) canonicalSchemas.get(key); - } - protected SchemaEx createMessageSchema(Message message, Map types) { String cacheKey = generateCacheKey(message, ProtoConst.MAP_TYPE); - SchemaEx schema = findSchema(cacheKey); + SchemaEx schema = (SchemaEx) canonicalSchemas.get(cacheKey); if (schema != null) { return schema; } @@ -121,9 +101,10 @@ protected SchemaEx createMessageSchema(Message message, Map return schema; } + @SuppressWarnings("unchecked") protected SchemaEx createMessageSchema(Message message, JavaType javaType) { String cacheKey = generateCacheKey(message, javaType); - SchemaEx schema = findSchema(cacheKey); + SchemaEx schema = (SchemaEx) canonicalSchemas.get(cacheKey); if (schema != null) { return schema; } @@ -144,7 +125,7 @@ protected FieldSchema createMapFieldSchema(Field protoField, PropertyDesc JavaType entryType = TypeFactory.defaultInstance().constructParametricType(MapEntry.class, javaType.getKeyType(), javaType.getContentType()); - SchemaEx> entrySchema = getOrCreateMessageSchema((Message) protoField.getType(), + SchemaEx> entrySchema = createMessageSchema((Message) protoField.getType(), entryType); return new MapSchema<>(protoField, propertyDescriptor, entrySchema); } @@ -185,14 +166,14 @@ public FieldMapEx> createMapFields(Message message, Map types, String perameterName) { + private JavaType getParameterType(Map types, String parameterName) { - if (types.get(perameterName) != null) { - return TypeFactory.defaultInstance().constructType(types.get(perameterName)); + if (types.get(parameterName) != null) { + return TypeFactory.defaultInstance().constructType(types.get(parameterName)); } throw new IllegalArgumentException( - String.format("not found type info for parameter name [%s]", perameterName)); + String.format("not found type info for parameter name [%s]", parameterName)); } public FieldSchema createSchemaField(Field protoField, PropertyDescriptor propertyDescriptor) { @@ -215,7 +196,7 @@ public FieldSchema createSchemaField(Field protoField, PropertyDescriptor // message if (protoField.getType().isMessage()) { - SchemaEx messageSchema = getOrCreateMessageSchema((Message) protoField.getType(), + SchemaEx messageSchema = createMessageSchema((Message) protoField.getType(), propertyDescriptor.getJavaType()); if (isWrapProperty((Message) protoField.getType())) { return new PropertyWrapperAsFieldSchema<>(protoField, propertyDescriptor, messageSchema); diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java index bcc6559e047..4fc8fd5e58a 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/any/AnyEntrySchema.java @@ -50,7 +50,7 @@ public class AnyEntrySchema implements SchemaEx { private final int valueTag = WireFormat.makeTag(2, WireFormat.WIRETYPE_LENGTH_DELIMITED); - private Type anyTargetType; + private final Type anyTargetType; public AnyEntrySchema(ProtoMapper protoMapper, Type type) { this.protoMapper = protoMapper; @@ -189,9 +189,7 @@ private SchemaWriter createEntryWriter(String actualTypeName, Object _va // standard pack RootSerializer valueSerializer = protoMapper.createRootSerializer(message, _value.getClass()); String valueCanonicalName = message.getCanonicalName(); - return (output, value) -> { - standardPack(output, value, valueCanonicalName, valueSerializer); - }; + return (output, value) -> standardPack(output, value, valueCanonicalName, valueSerializer); } protected void standardPack(OutputEx output, Object message, String canonicalName, RootSerializer valueSerializer) diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java index cf47f8f54da..23b9d85a01d 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/DeserializerSchemaManager.java @@ -234,6 +234,8 @@ protected FieldSchema createRepeatedSchema(Field protoField, PropertyDesc return StringRepeatedReadSchemas.create(protoField, propertyDescriptor); case BYTES: return BytesRepeatedReadSchemas.create(protoField, propertyDescriptor); + default: + ProtoUtils.throwNotSupportMerge(protoField, propertyDescriptor.getJavaType()); } } @@ -247,7 +249,7 @@ protected FieldSchema createRepeatedSchema(Field protoField, PropertyDesc if (contentType == null) { contentType = ProtoConst.OBJECT_TYPE; } - SchemaEx contentSchema = getOrCreateMessageSchema((Message) protoField.getType(), contentType); + SchemaEx contentSchema = createMessageSchema((Message) protoField.getType(), contentType); if (isWrapProperty((Message) protoField.getType())) { return PropertyWrapperRepeatedReadSchemas.create(protoField, propertyDescriptor, contentSchema); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/MessageReadSchema.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/MessageReadSchema.java index b8d16cfd686..68990c29865 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/MessageReadSchema.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/MessageReadSchema.java @@ -52,13 +52,13 @@ public class MessageReadSchema implements SchemaEx { private static final Logger LOGGER = LoggerFactory.getLogger(MessageReadSchema.class); - protected ProtoMapper protoMapper; + protected final ProtoMapper protoMapper; - protected Message message; + protected final Message message; private FieldMapEx fieldMap; - private Instantiator instantiator; + private final Instantiator instantiator; private JavaType javaType; @@ -166,7 +166,7 @@ public void mergeFrom(InputEx input, T message) throws IOException { } catch (Throwable e) { if (fieldSchema != null) { Field protoField = fieldSchema.getProtoField(); - LOGGER.error("Failed to mergeFrom, field={}:{}, type={}", + LOGGER.error("Failed to mergeFrom, field={}:{}, type={}, error {}", protoField.getType().getCanonicalName(), protoField.getName(), protoField.getTypeName(), diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/PrimitiveArrayBuilderWrapper.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/PrimitiveArrayBuilderWrapper.java index cb2bafeac5a..1478e152268 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/PrimitiveArrayBuilderWrapper.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/PrimitiveArrayBuilderWrapper.java @@ -19,7 +19,7 @@ import com.fasterxml.jackson.databind.util.PrimitiveArrayBuilder; public class PrimitiveArrayBuilderWrapper { - private PrimitiveArrayBuilder builder; + private final PrimitiveArrayBuilder builder; private T array; diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/RepeatedReadSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/RepeatedReadSchemas.java index 771bafdbce4..e03a7efd579 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/RepeatedReadSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/repeated/RepeatedReadSchemas.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; import org.apache.servicecomb.foundation.common.utils.bean.Getter; import org.apache.servicecomb.foundation.common.utils.bean.Setter; @@ -75,7 +77,11 @@ public CollectionRepeatedSchema(Field protoField, PropertyDescriptor propertyDes public final int mergeFrom(InputEx input, T message) throws IOException { Collection collection = getter.get(message); if (collection == null) { - collection = new ArrayList<>(); + if (Set.class.equals(javaType.getRawClass())) { + collection = new HashSet<>(); + } else { + collection = new ArrayList<>(); + } setter.set(message, collection); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/AbstractScalarReadSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/AbstractScalarReadSchemas.java index a1f8e06bb27..345fd477df2 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/AbstractScalarReadSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/AbstractScalarReadSchemas.java @@ -23,7 +23,7 @@ import io.protostuff.runtime.FieldSchema; public class AbstractScalarReadSchemas { - static abstract class AbstractIntSchema extends FieldSchema { + abstract static class AbstractIntSchema extends FieldSchema { protected final Setter setter; public AbstractIntSchema(Field protoField, PropertyDescriptor propertyDescriptor) { @@ -32,7 +32,7 @@ public AbstractIntSchema(Field protoField, PropertyDescriptor propertyDescriptor } } - static abstract class AbstractLongSchema extends FieldSchema { + abstract static class AbstractLongSchema extends FieldSchema { protected final Setter setter; public AbstractLongSchema(Field protoField, PropertyDescriptor propertyDescriptor) { diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/SInt32ReadSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/SInt32ReadSchemas.java index 36621024b4c..8252e2a96ca 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/SInt32ReadSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/SInt32ReadSchemas.java @@ -18,7 +18,9 @@ import java.io.IOException; +import org.apache.servicecomb.foundation.common.utils.bean.ByteSetter; import org.apache.servicecomb.foundation.common.utils.bean.IntSetter; +import org.apache.servicecomb.foundation.common.utils.bean.ShortSetter; import org.apache.servicecomb.foundation.protobuf.internal.ProtoUtils; import org.apache.servicecomb.foundation.protobuf.internal.bean.PropertyDescriptor; import org.apache.servicecomb.foundation.protobuf.internal.schema.deserializer.scalar.AbstractScalarReadSchemas.AbstractIntSchema; @@ -36,7 +38,18 @@ public static FieldSchema create(Field protoField, PropertyDescriptor pro return new SInt32PrimitiveSchema<>(protoField, propertyDescriptor); } - if (Integer.class.equals(javaType.getRawClass()) || javaType.isJavaLangObject()) { + if (short.class.equals(javaType.getRawClass())) { + return new ShortFieldSInt32PrimitiveSchema<>(protoField, propertyDescriptor); + } + + if (byte.class.equals(javaType.getRawClass())) { + return new ByteFieldSInt32PrimitiveSchema<>(protoField, propertyDescriptor); + } + + if (Integer.class.equals(javaType.getRawClass()) + || Byte.class.equals(javaType.getRawClass()) + || Short.class.equals(javaType.getRawClass()) + || javaType.isJavaLangObject()) { return new SInt32Schema<>(protoField, propertyDescriptor); } @@ -52,7 +65,13 @@ public SInt32Schema(Field protoField, PropertyDescriptor propertyDescriptor) { @Override public int mergeFrom(InputEx input, T message) throws IOException { int value = input.readSInt32(); - setter.set(message, value); + if (Byte.class.equals(javaType.getRawClass())) { + setter.set(message, (byte) value); + } else if (Short.class.equals(javaType.getRawClass())) { + setter.set(message, (short) value); + } else { + setter.set(message, value); + } return input.readFieldNumber(); } } @@ -72,4 +91,36 @@ public int mergeFrom(InputEx input, T message) throws IOException { return input.readFieldNumber(); } } + + private static class ShortFieldSInt32PrimitiveSchema extends FieldSchema { + protected final ShortSetter setter; + + public ShortFieldSInt32PrimitiveSchema(Field protoField, PropertyDescriptor propertyDescriptor) { + super(protoField, propertyDescriptor.getJavaType()); + this.setter = propertyDescriptor.getSetter(); + } + + @Override + public int mergeFrom(InputEx input, T message) throws IOException { + int value = input.readSInt32(); + setter.set(message, (short) value); + return input.readFieldNumber(); + } + } + + private static class ByteFieldSInt32PrimitiveSchema extends FieldSchema { + protected final ByteSetter setter; + + public ByteFieldSInt32PrimitiveSchema(Field protoField, PropertyDescriptor propertyDescriptor) { + super(protoField, propertyDescriptor.getJavaType()); + this.setter = propertyDescriptor.getSetter(); + } + + @Override + public int mergeFrom(InputEx input, T message) throws IOException { + int value = input.readSInt32(); + setter.set(message, (byte) value); + return input.readFieldNumber(); + } + } } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/StringReadSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/StringReadSchemas.java index 0edaa827bee..7b1f0a441b0 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/StringReadSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/deserializer/scalar/StringReadSchemas.java @@ -17,6 +17,8 @@ package org.apache.servicecomb.foundation.protobuf.internal.schema.deserializer.scalar; import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; import org.apache.servicecomb.foundation.common.utils.bean.CharSetter; import org.apache.servicecomb.foundation.common.utils.bean.Setter; @@ -42,6 +44,14 @@ public static FieldSchema create(Field protoField, PropertyDescriptor pro return new StringSchema<>(protoField, propertyDescriptor); } + if (BigDecimal.class.equals(javaType.getRawClass())) { + return new BigDecimalSchema<>(protoField, propertyDescriptor); + } + + if (BigInteger.class.equals(javaType.getRawClass())) { + return new BigIntegerSchema<>(protoField, propertyDescriptor); + } + ProtoUtils.throwNotSupportMerge(protoField, propertyDescriptor.getJavaType()); return null; } @@ -82,4 +92,36 @@ public int mergeFrom(InputEx input, T message) throws IOException { return input.readFieldNumber(); } } + + private static class BigDecimalSchema extends FieldSchema { + private final Setter setter; + + public BigDecimalSchema(Field protoField, PropertyDescriptor propertyDescriptor) { + super(protoField, propertyDescriptor.getJavaType()); + this.setter = propertyDescriptor.getSetter(); + } + + @Override + public int mergeFrom(InputEx input, T message) throws IOException { + String value = input.readString(); + setter.set(message, new BigDecimal(value)); + return input.readFieldNumber(); + } + } + + private static class BigIntegerSchema extends FieldSchema { + private final Setter setter; + + public BigIntegerSchema(Field protoField, PropertyDescriptor propertyDescriptor) { + super(protoField, propertyDescriptor.getJavaType()); + this.setter = propertyDescriptor.getSetter(); + } + + @Override + public int mergeFrom(InputEx input, T message) throws IOException { + String value = input.readString(); + setter.set(message, new BigInteger(value)); + return input.readFieldNumber(); + } + } } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/MessageWriteSchema.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/MessageWriteSchema.java index 24717a2e0cc..ccab4d81f82 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/MessageWriteSchema.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/MessageWriteSchema.java @@ -49,11 +49,11 @@ * */ public class MessageWriteSchema implements SchemaEx { - protected ProtoMapper protoMapper; + protected final ProtoMapper protoMapper; - protected Message message; + protected final Message message; - private JavaType javaType; + private final JavaType javaType; // mostly, one message only relate to one pojo private final Class mainPojoCls; @@ -101,6 +101,8 @@ public FieldMapEx getMainPojoFieldMaps() { @Override public void init() { + this.mapFieldMaps = protoMapper.getSerializerSchemaManager().createMapFields(message); + if (ProtoUtils.isWrapProperty(message)) { this.mainPojoFieldMaps = createPropertyWrapperFields(javaType); return; @@ -178,10 +180,6 @@ private void writeDynamicPojo(OutputEx output, Object dynamicValue) throws I } protected final void writeFromMap(OutputEx output, Map map) throws IOException { - if (mapFieldMaps == null) { - mapFieldMaps = protoMapper.getSerializerSchemaManager().createMapFields(message); - } - for (Entry entry : map.entrySet()) { if (entry.getValue() == null) { continue; diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java index 15734bf593e..d63944e3423 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/SerializerSchemaManager.java @@ -211,6 +211,8 @@ protected FieldSchema createRepeatedSchema(Field protoField, PropertyDesc return StringsRepeatedWriteSchemas.create(protoField, propertyDescriptor); case BYTES: return BytesRepeatedWriteSchemas.create(protoField, propertyDescriptor); + default: + ProtoUtils.throwNotSupportWrite(protoField, propertyDescriptor.getJavaType().getRawClass()); } } @@ -224,7 +226,7 @@ protected FieldSchema createRepeatedSchema(Field protoField, PropertyDesc if (contentType == null) { contentType = ProtoConst.OBJECT_TYPE; } - SchemaEx contentSchema = getOrCreateMessageSchema((Message) protoField.getType(), contentType); + SchemaEx contentSchema = createMessageSchema((Message) protoField.getType(), contentType); if (isWrapProperty((Message) protoField.getType())) { return PropertyWrapperRepeatedWriteSchemas.create(protoField, propertyDescriptor, contentSchema); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/AbstractWriters.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/AbstractWriters.java index b448a5def71..bb784ff7632 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/AbstractWriters.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/AbstractWriters.java @@ -84,4 +84,4 @@ public void dynamicWriteTo(OutputEx output, Object value) throws IOException { ProtoUtils.throwNotSupportWrite(protoField, value); } -} \ No newline at end of file +} diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SFixed32PackedWriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SFixed32PackedWriteSchemas.java index 661a99d44a2..7e0272e5ae6 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SFixed32PackedWriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SFixed32PackedWriteSchemas.java @@ -56,8 +56,7 @@ public SFixed32PackedWriters(Field protoField) { }); }; - collectionWriter = (o, value) -> - { + collectionWriter = (o, value) -> { if (value.isEmpty()) { return; } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SInt32PackedWriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SInt32PackedWriteSchemas.java index c1d4482fa3f..202ae2f0068 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SInt32PackedWriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/SInt32PackedWriteSchemas.java @@ -56,8 +56,7 @@ public SInt32PackedWriters(Field protoField) { }); }; - collectionWriter = (o, value) -> - { + collectionWriter = (o, value) -> { if (value.isEmpty()) { return; } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/UInt32PackedWriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/UInt32PackedWriteSchemas.java index 30e9dd4adf8..61be0eed41e 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/UInt32PackedWriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/repeated/impl/ints/UInt32PackedWriteSchemas.java @@ -40,8 +40,7 @@ public UInt32PackedWriters(Field protoField) { }); }; - arrayWriter = (o, value) -> - { + arrayWriter = (o, value) -> { if (value.length == 0) { return; } @@ -57,8 +56,7 @@ public UInt32PackedWriters(Field protoField) { }); }; - collectionWriter = (o, value) -> - { + collectionWriter = (o, value) -> { if (value.isEmpty()) { return; } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/EnumWriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/EnumWriteSchemas.java index 071c68ef1bb..8b4f82f858d 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/EnumWriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/EnumWriteSchemas.java @@ -39,7 +39,7 @@ public static FieldSchema create(Field protoField, PropertyDescriptor pro } private static class EnumDynamicSchema extends FieldSchema { - private EnumMeta enumMeta; + private final EnumMeta enumMeta; public EnumDynamicSchema(Field protoField, PropertyDescriptor propertyDescriptor) { super(protoField, propertyDescriptor.getJavaType()); diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int32WriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int32WriteSchemas.java index 724321b0f8d..9172823efe9 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int32WriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int32WriteSchemas.java @@ -108,7 +108,7 @@ public IntFieldInt32PrimitiveSchema(Field protoField, PropertyDescriptor propert } @Override - public final void getAndWriteTo(OutputEx output, T message) throws IOException { + public void getAndWriteTo(OutputEx output, T message) throws IOException { int value = primitiveGetter.get(message); output.writeScalarInt32(tag, tagSize, value); } @@ -124,7 +124,7 @@ public ShortFieldInt32PrimitiveSchema(Field protoField, PropertyDescriptor prope } @Override - public final void getAndWriteTo(OutputEx output, T message) throws IOException { + public void getAndWriteTo(OutputEx output, T message) throws IOException { short value = primitiveGetter.get(message); output.writeScalarInt32(tag, tagSize, value); } @@ -140,7 +140,7 @@ public ByteFieldInt32PrimitiveSchema(Field protoField, PropertyDescriptor proper } @Override - public final void getAndWriteTo(OutputEx output, T message) throws IOException { + public void getAndWriteTo(OutputEx output, T message) throws IOException { byte value = primitiveGetter.get(message); output.writeScalarInt32(tag, tagSize, value); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int64WriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int64WriteSchemas.java index 1d0cf4d9289..d85810524e8 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int64WriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/Int64WriteSchemas.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.temporal.ChronoField; import java.util.Date; @@ -53,35 +54,42 @@ public final void writeTo(OutputEx output, Object value) throws IOException { return; } - if (value instanceof String[]) { - if (((String[]) value).length == 0) { - return; - } - long parsedValue = Long.parseLong(((String[]) value)[0], 10); + if (value instanceof Date) { + long parsedValue = ((Date) value).getTime(); output.writeScalarInt64(tag, tagSize, parsedValue); return; } - if (value instanceof String) { - long parsedValue = Long.parseLong((String) value, 10); + if (value instanceof LocalDate) { + long parsedValue = ((LocalDate) value).getLong(ChronoField.EPOCH_DAY); output.writeScalarInt64(tag, tagSize, parsedValue); return; } - if (value instanceof Date) { - long parsedValue = ((Date) value).getTime(); + if (value instanceof LocalDateTime) { + long parsedValue = ((LocalDateTime) value).toInstant(ZoneOffset.UTC).toEpochMilli(); output.writeScalarInt64(tag, tagSize, parsedValue); return; } - if (value instanceof LocalDate) { - long parsedValue = ((LocalDate) value).getLong(ChronoField.EPOCH_DAY); + if (value instanceof String) { + long parsedValue; + if (((String) value).contains(":")) { + // from edge, ISO8601 date time, e.g. 2022-05-31T09:16:38.941Z + OffsetDateTime offsetDateTime = OffsetDateTime.parse((String) value); + parsedValue = offsetDateTime.toInstant().toEpochMilli(); + } else { + parsedValue = Long.parseLong((String) value, 10); + } output.writeScalarInt64(tag, tagSize, parsedValue); return; } - if (value instanceof LocalDateTime) { - long parsedValue = ((LocalDateTime) value).toInstant(ZoneOffset.UTC).toEpochMilli(); + if (value instanceof String[]) { + if (((String[]) value).length == 0) { + return; + } + long parsedValue = Long.parseLong(((String[]) value)[0], 10); output.writeScalarInt64(tag, tagSize, parsedValue); return; } @@ -118,7 +126,7 @@ public Int64PrimitiveSchema(Field protoField, PropertyDescriptor propertyDescrip } @Override - public final void getAndWriteTo(OutputEx output, T message) throws IOException { + public void getAndWriteTo(OutputEx output, T message) throws IOException { long value = primitiveGetter.get(message); output.writeScalarInt64(tag, tagSize, value); } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/StringWriteSchemas.java b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/StringWriteSchemas.java index 34c8647ca10..7df329b849b 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/StringWriteSchemas.java +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/internal/schema/serializer/scalar/StringWriteSchemas.java @@ -17,6 +17,8 @@ package org.apache.servicecomb.foundation.protobuf.internal.schema.serializer.scalar; import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; import org.apache.servicecomb.foundation.common.utils.bean.CharGetter; import org.apache.servicecomb.foundation.common.utils.bean.Getter; @@ -65,6 +67,11 @@ public final void writeTo(OutputEx output, Object value) throws IOException { return; } + if (value instanceof BigDecimal || value instanceof BigInteger) { + output.writeScalarString(tag, tagSize, value.toString()); + return; + } + ProtoUtils.throwNotSupportWrite(protoField, value); } } diff --git a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/notice.txt b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/notice.txt index 870ad1c79bb..0b6783a90c6 100644 --- a/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/notice.txt +++ b/foundations/foundation-protobuf/src/main/java/org/apache/servicecomb/foundation/protobuf/notice.txt @@ -15,4 +15,4 @@ 1.数组编码规则从protoStuff变成标准的protobuf 不确定: - 1.List/List/Map>/Map规则应该也有变化,是否有变化,从protoStuff变成标准protobuf \ No newline at end of file + 1.List/List/Map>/Map规则应该也有变化,是否有变化,从protoStuff变成标准protobuf diff --git a/foundations/foundation-protobuf/src/main/resources/google/protobuf/any.proto b/foundations/foundation-protobuf/src/main/resources/google/protobuf/any.proto new file mode 100644 index 00000000000..c89243178af --- /dev/null +++ b/foundations/foundation-protobuf/src/main/resources/google/protobuf/any.proto @@ -0,0 +1,161 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/known/anypb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "AnyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; + +// `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// // or ... +// if (any.isSameTypeAs(Foo.getDefaultInstance())) { +// foo = any.unpack(Foo.getDefaultInstance()); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } +// ... +// foo := &pb.Foo{} +// if err := any.UnmarshalTo(foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +// +message Any { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + // + string type_url = 1; + + // Must be a valid serialized protocol buffer of the above specified type. + bytes value = 2; +} diff --git a/foundations/foundation-protobuf/src/main/resources/google/protobuf/empty.proto b/foundations/foundation-protobuf/src/main/resources/google/protobuf/empty.proto new file mode 100644 index 00000000000..b87c89dcfce --- /dev/null +++ b/foundations/foundation-protobuf/src/main/resources/google/protobuf/empty.proto @@ -0,0 +1,51 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +syntax = "proto3"; + +package google.protobuf; + +option go_package = "google.golang.org/protobuf/types/known/emptypb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "EmptyProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +// +message Empty {} diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/TestISODateTimeParsing.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/TestISODateTimeParsing.java new file mode 100644 index 00000000000..8fa797724b9 --- /dev/null +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/TestISODateTimeParsing.java @@ -0,0 +1,43 @@ +/* + * 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.foundation.protobuf; + +import java.text.SimpleDateFormat; +import java.time.OffsetDateTime; +import java.util.Date; +import java.util.TimeZone; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class TestISODateTimeParsing { + @Test + public void testParseStringToDate() { + SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD'T'hh:mm:ssZ"); + sdf.setTimeZone(TimeZone.getTimeZone("EST")); + + OffsetDateTime offsetDateTime = OffsetDateTime.parse("2022-05-31T09:16:38.941Z"); + Date d = Date.from(offsetDateTime.toInstant()); + String date = sdf.format(d); + Assertions.assertEquals("2022-05-151T04:16:38-0500", date); + + offsetDateTime = OffsetDateTime.parse("2022-05-31T09:16:38.941+00:00"); + d = Date.from(offsetDateTime.toInstant()); + date = sdf.format(d); + Assertions.assertEquals("2022-05-151T04:16:38-0500", date); + } +} diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/compatibility/TestCompatibilityOfImplementations.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/compatibility/TestCompatibilityOfImplementations.java index e5fb65259db..62fedeaf68e 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/compatibility/TestCompatibilityOfImplementations.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/compatibility/TestCompatibilityOfImplementations.java @@ -26,43 +26,42 @@ import org.apache.servicecomb.foundation.protobuf.performance.ProtubufCodecEngine; import org.apache.servicecomb.foundation.protobuf.performance.engine.Protobuf; import org.apache.servicecomb.foundation.protobuf.performance.engine.ScbWeak; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestCompatibilityOfImplementations { - static ProtubufCodecEngine scbWeak = new ScbWeak(); + static final ProtubufCodecEngine scbWeak = new ScbWeak(); - static ProtubufCodecEngine protobuf = new Protobuf(); + static final ProtubufCodecEngine protobuf = new Protobuf(); @Test @SuppressWarnings("unchecked") public void testEmptyCollection() throws Exception { ProtobufRoot.Root.Builder builder = ProtobufRoot.Root.newBuilder(); byte[] values = protobuf.serialize(builder); - Assert.assertEquals(values.length, 0); + Assertions.assertEquals(values.length, 0); ProtobufRoot.Root.Builder o = (ProtobufRoot.Root.Builder) protobuf.deserialize(values); - Assert.assertTrue(o.getFixed32SNotPackedList().isEmpty()); + Assertions.assertTrue(o.getFixed32SNotPackedList().isEmpty()); builder = ProtobufRoot.Root.newBuilder().addFixed32SNotPacked(30); values = protobuf.serialize(builder); - Assert.assertArrayEquals(new byte[] {(byte) -123, (byte) 6, (byte) 30, (byte) 0, (byte) 0, (byte) 0}, values); + Assertions.assertArrayEquals(new byte[] {(byte) -123, (byte) 6, (byte) 30, (byte) 0, (byte) 0, (byte) 0}, values); o = (ProtobufRoot.Root.Builder) protobuf.deserialize(values); - Assert.assertEquals(30, (int) o.getFixed32SNotPackedList().get(0)); + Assertions.assertEquals(30, (int) o.getFixed32SNotPackedList().get(0)); Root root = new Root(); root.setFixed32sNotPacked(new ArrayList<>()); values = scbWeak.serialize(root); - Assert.assertEquals(values.length, 0); + Assertions.assertEquals(values.length, 0); Map newRootMap = (Map) scbWeak.deserialize(values); - Assert.assertEquals(null, - newRootMap.get("fixed32sNotPacked")); // This is different , because depends on default model initializer + Assertions.assertNull(newRootMap.get("fixed32sNotPacked")); // This is different , because depends on default model initializer List iValues = new ArrayList<>(); iValues.add(30); root.setFixed32sNotPacked(iValues); values = scbWeak.serialize(root); - Assert.assertArrayEquals(new byte[] {(byte) -123, (byte) 6, (byte) 30, (byte) 0, (byte) 0, (byte) 0}, values); + Assertions.assertArrayEquals(new byte[] {(byte) -123, (byte) 6, (byte) 30, (byte) 0, (byte) 0, (byte) 0}, values); newRootMap = (Map) scbWeak.deserialize(values); - Assert.assertEquals(30, (int) ((List) newRootMap.get("fixed32sNotPacked")).get(0)); + Assertions.assertEquals(30, (int) ((List) newRootMap.get("fixed32sNotPacked")).get(0)); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java index 26d447cd3a0..fd19fd8f033 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestModelWrap.java @@ -26,10 +26,10 @@ import org.apache.servicecomb.foundation.protobuf.ProtoMapperFactory; import org.apache.servicecomb.foundation.protobuf.RootDeserializer; import org.apache.servicecomb.foundation.protobuf.RootSerializer; -import org.junit.Assert; -import org.junit.Test; import io.vertx.core.json.Json; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestModelWrap { protected static ProtoMapperFactory factory = new ProtoMapperFactory(); @@ -278,20 +278,20 @@ public void pojoModel() throws IOException { // serialize byte[] bytes = protoSerializer.serialize(protoModel); - Assert.assertArrayEquals(bytes, protoSerializer.serialize(mapFromProtoModel)); - Assert.assertArrayEquals(bytes, pojoSerializer.serialize(pojoModel)); - Assert.assertArrayEquals(bytes, pojoSerializer.serialize(mapFromPojoModel)); + Assertions.assertArrayEquals(bytes, protoSerializer.serialize(mapFromProtoModel)); + Assertions.assertArrayEquals(bytes, pojoSerializer.serialize(pojoModel)); + Assertions.assertArrayEquals(bytes, pojoSerializer.serialize(mapFromPojoModel)); // deserialize pojoModel PojoModel newPojoModel = pojoModelDeserializer.deserialize(bytes); - Assert.assertEquals(jsonPojoModel, Json.encode(newPojoModel)); + Assertions.assertEquals(jsonPojoModel, Json.encode(newPojoModel)); Map mapFromNewPojoModel = pojoMapDeserializer.deserialize(bytes); - Assert.assertEquals(jsonPojoModel, Json.encode(mapFromNewPojoModel)); + Assertions.assertEquals(jsonPojoModel, Json.encode(mapFromNewPojoModel)); // deserialize protoModel ProtoModel newProtoModel = protoModelDeserializer.deserialize(bytes); - Assert.assertEquals(jsonProtoModel, Json.encode(newProtoModel)); + Assertions.assertEquals(jsonProtoModel, Json.encode(newProtoModel)); Map mapFromNewProtoModel = protoMapDeserializer.deserialize(bytes); - Assert.assertEquals(jsonProtoModel, Json.encode(mapFromNewProtoModel)); + Assertions.assertEquals(jsonProtoModel, Json.encode(mapFromNewProtoModel)); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestSchemaBase.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestSchemaBase.java index 2743aa149bf..6353815df6d 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestSchemaBase.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/TestSchemaBase.java @@ -28,11 +28,9 @@ import org.apache.servicecomb.foundation.protobuf.internal.model.PrimitiveWrapperArrays; import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot; import org.apache.servicecomb.foundation.protobuf.internal.model.Root; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.rules.ExpectedException; import io.protostuff.compiler.model.Field; +import org.junit.jupiter.api.Assertions; public class TestSchemaBase { protected static ProtoMapperFactory factory = new ProtoMapperFactory(); @@ -58,9 +56,6 @@ public class TestSchemaBase { protected static RootDeserializer> mapRootDeserializer = protoMapper .createRootDeserializer("Root", Map.class); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - protected Object scbRoot; protected byte[] scbRootBytes; @@ -120,19 +115,19 @@ protected void checkRepeatedWithPrimitive() throws Exception { scbMap.clear(); scbMap.put(primitiveFieldName, strings); scbMapBytes = primitiveArraysSerializer.serialize(scbMap); - Assert.assertArrayEquals(protobufBytes, scbMapBytes); + Assertions.assertArrayEquals(protobufBytes, scbMapBytes); // dynamic primitive array scbMap.clear(); scbMap.put(primitiveFieldName, primitiveArray); scbMapBytes = primitiveArraysSerializer.serialize(scbMap); - Assert.assertArrayEquals(protobufBytes, scbMapBytes); + Assertions.assertArrayEquals(protobufBytes, scbMapBytes); // dynamic array scbMap.clear(); scbMap.put(primitiveFieldName, array); scbMapBytes = primitiveArraysSerializer.serialize(scbMap); - Assert.assertArrayEquals(protobufBytes, scbMapBytes); + Assertions.assertArrayEquals(protobufBytes, scbMapBytes); } protected void check() throws IOException { @@ -165,7 +160,7 @@ protected void check(RootDeserializer deserializer, RootDeserializer) propertyDescriptor.getSetter()).set(model, 1); - Assert.assertEquals(1, ((IntGetter) propertyDescriptor.getGetter()).get(model)); - Assert.assertEquals(1, model.getBoth()); + Assertions.assertEquals(1, ((IntGetter) propertyDescriptor.getGetter()).get(model)); + Assertions.assertEquals(1, model.getBoth()); } @SuppressWarnings("unchecked") @Test public void onlyGet() { PropertyDescriptor propertyDescriptor = beanDescriptor.getPropertyDescriptors().get("onlyGet"); - Assert.assertNull(propertyDescriptor.getSetter()); + Assertions.assertNull(propertyDescriptor.getSetter()); model.onlyGet(1); - Assert.assertEquals(1, ((IntGetter) propertyDescriptor.getGetter()).get(model)); - Assert.assertEquals(1, model.getOnlyGet()); + Assertions.assertEquals(1, ((IntGetter) propertyDescriptor.getGetter()).get(model)); + Assertions.assertEquals(1, model.getOnlyGet()); } @SuppressWarnings("unchecked") @Test public void onlySet() { PropertyDescriptor propertyDescriptor = beanDescriptor.getPropertyDescriptors().get("onlySet"); - Assert.assertNull(propertyDescriptor.getGetter()); + Assertions.assertNull(propertyDescriptor.getGetter()); ((IntSetter) propertyDescriptor.getSetter()).set(model, 1); - Assert.assertEquals(1, model.onlySet()); + Assertions.assertEquals(1, model.onlySet()); } @SuppressWarnings("unchecked") @@ -139,7 +139,7 @@ public void onlySet() { public void direct() { PropertyDescriptor propertyDescriptor = beanDescriptor.getPropertyDescriptors().get("direct"); ((Setter) propertyDescriptor.getSetter()).set(model, 1); - Assert.assertEquals(1, (int) ((Getter) propertyDescriptor.getGetter()).get(model)); - Assert.assertEquals(1, model.direct); + Assertions.assertEquals(1, (int) ((Getter) propertyDescriptor.getGetter()).get(model)); + Assertions.assertEquals(1, model.direct); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/CustomGeneric.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/CustomGeneric.java index 5cbb1ef788f..c57579ed18e 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/CustomGeneric.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/CustomGeneric.java @@ -18,4 +18,4 @@ public class CustomGeneric { public T user; -} \ No newline at end of file +} diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/ProtobufRoot.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/ProtobufRoot.java deleted file mode 100644 index 108cd2851fc..00000000000 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/model/ProtobufRoot.java +++ /dev/null @@ -1,10698 +0,0 @@ -// Generated by the protocol buffer compiler. DO NOT EDIT! -// source: protobufRoot.proto - -package org.apache.servicecomb.foundation.protobuf.internal.model; - -@SuppressWarnings({"all", "cast"}) -public final class ProtobufRoot { - private ProtobufRoot() {} - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistryLite registry) { - } - - public static void registerAllExtensions( - com.google.protobuf.ExtensionRegistry registry) { - registerAllExtensions( - (com.google.protobuf.ExtensionRegistryLite) registry); - } - /** - * Protobuf enum {@code org.apache.servicecomb.foundation.protobuf.internal.model.Color} - */ - public enum Color - implements com.google.protobuf.ProtocolMessageEnum { - /** - * RED = 0; - */ - RED(0), - /** - * YELLOW = 1; - */ - YELLOW(1), - /** - * BLUE = 2; - */ - BLUE(2), - UNRECOGNIZED(-1), - ; - - /** - * RED = 0; - */ - public static final int RED_VALUE = 0; - /** - * YELLOW = 1; - */ - public static final int YELLOW_VALUE = 1; - /** - * BLUE = 2; - */ - public static final int BLUE_VALUE = 2; - - - public final int getNumber() { - if (this == UNRECOGNIZED) { - throw new java.lang.IllegalArgumentException( - "Can't get the number of an unknown enum value."); - } - return value; - } - - /** - * @deprecated Use {@link #forNumber(int)} instead. - */ - @java.lang.Deprecated - public static Color valueOf(int value) { - return forNumber(value); - } - - public static Color forNumber(int value) { - switch (value) { - case 0: return RED; - case 1: return YELLOW; - case 2: return BLUE; - default: return null; - } - } - - public static com.google.protobuf.Internal.EnumLiteMap - internalGetValueMap() { - return internalValueMap; - } - private static final com.google.protobuf.Internal.EnumLiteMap< - Color> internalValueMap = - new com.google.protobuf.Internal.EnumLiteMap() { - public Color findValueByNumber(int number) { - return Color.forNumber(number); - } - }; - - public final com.google.protobuf.Descriptors.EnumValueDescriptor - getValueDescriptor() { - return getDescriptor().getValues().get(ordinal()); - } - public final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptorForType() { - return getDescriptor(); - } - public static final com.google.protobuf.Descriptors.EnumDescriptor - getDescriptor() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.getDescriptor().getEnumTypes().get(0); - } - - private static final Color[] VALUES = values(); - - public static Color valueOf( - com.google.protobuf.Descriptors.EnumValueDescriptor desc) { - if (desc.getType() != getDescriptor()) { - throw new java.lang.IllegalArgumentException( - "EnumValueDescriptor is not for this type."); - } - if (desc.getIndex() == -1) { - return UNRECOGNIZED; - } - return VALUES[desc.getIndex()]; - } - - private final int value; - - private Color(int value) { - this.value = value; - } - - // @@protoc_insertion_point(enum_scope:org.apache.servicecomb.foundation.protobuf.internal.model.Color) - } - - public interface RootOrBuilder extends - // @@protoc_insertion_point(interface_extends:org.apache.servicecomb.foundation.protobuf.internal.model.Root) - com.google.protobuf.MessageOrBuilder { - - /** - * int32 int32 = 1; - */ - int getInt32(); - - /** - * int64 int64 = 2; - */ - long getInt64(); - - /** - * uint32 uint32 = 3; - */ - int getUint32(); - - /** - * uint64 uint64 = 4; - */ - long getUint64(); - - /** - * sint32 sint32 = 5; - */ - int getSint32(); - - /** - * sint64 sint64 = 6; - */ - long getSint64(); - - /** - * fixed32 fixed32 = 7; - */ - int getFixed32(); - - /** - * fixed64 fixed64 = 8; - */ - long getFixed64(); - - /** - * sfixed32 sfixed32 = 9; - */ - int getSfixed32(); - - /** - * sfixed64 sfixed64 = 10; - */ - long getSfixed64(); - - /** - * float floatValue = 11; - */ - float getFloatValue(); - - /** - * double doubleValue = 12; - */ - double getDoubleValue(); - - /** - * bool bool = 13; - */ - boolean getBool(); - - /** - * int32 objInt32 = 20; - */ - int getObjInt32(); - - /** - * int64 objInt64 = 21; - */ - long getObjInt64(); - - /** - * uint32 objUint32 = 22; - */ - int getObjUint32(); - - /** - * uint64 objUint64 = 23; - */ - long getObjUint64(); - - /** - * sint32 objSint32 = 24; - */ - int getObjSint32(); - - /** - * sint64 objSint64 = 25; - */ - long getObjSint64(); - - /** - * fixed32 objFixed32 = 26; - */ - int getObjFixed32(); - - /** - * fixed64 objFixed64 = 27; - */ - long getObjFixed64(); - - /** - * sfixed32 objSfixed32 = 28; - */ - int getObjSfixed32(); - - /** - * sfixed64 objSfixed64 = 29; - */ - long getObjSfixed64(); - - /** - * float objFloatValue = 30; - */ - float getObjFloatValue(); - - /** - * double objDoubleValue = 31; - */ - double getObjDoubleValue(); - - /** - * bool objBool = 32; - */ - boolean getObjBool(); - - /** - * string string = 40; - */ - java.lang.String getString(); - /** - * string string = 40; - */ - com.google.protobuf.ByteString - getStringBytes(); - - /** - * bytes bytes = 41; - */ - com.google.protobuf.ByteString getBytes(); - - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - int getColorValue(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColor(); - - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - boolean hasUser(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getUser(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder getUserOrBuilder(); - - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - boolean hasTypeRecursive(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getTypeRecursive(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder getTypeRecursiveOrBuilder(); - - /** - * .google.protobuf.Any any = 50; - */ - boolean hasAny(); - /** - * .google.protobuf.Any any = 50; - */ - com.google.protobuf.Any getAny(); - /** - * .google.protobuf.Any any = 50; - */ - com.google.protobuf.AnyOrBuilder getAnyOrBuilder(); - - /** - * repeated .google.protobuf.Any anys = 51; - */ - java.util.List - getAnysList(); - /** - * repeated .google.protobuf.Any anys = 51; - */ - com.google.protobuf.Any getAnys(int index); - /** - * repeated .google.protobuf.Any anys = 51; - */ - int getAnysCount(); - /** - * repeated .google.protobuf.Any anys = 51; - */ - java.util.List - getAnysOrBuilderList(); - /** - * repeated .google.protobuf.Any anys = 51; - */ - com.google.protobuf.AnyOrBuilder getAnysOrBuilder( - int index); - - /** - * map<string, string> ssMap = 60; - */ - int getSsMapCount(); - /** - * map<string, string> ssMap = 60; - */ - boolean containsSsMap( - java.lang.String key); - /** - * Use {@link #getSsMapMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getSsMap(); - /** - * map<string, string> ssMap = 60; - */ - java.util.Map - getSsMapMap(); - /** - * map<string, string> ssMap = 60; - */ - - java.lang.String getSsMapOrDefault( - java.lang.String key, - java.lang.String defaultValue); - /** - * map<string, string> ssMap = 60; - */ - - java.lang.String getSsMapOrThrow( - java.lang.String key); - - /** - * map<string, int32> sint32Map = 61; - */ - int getSint32MapCount(); - /** - * map<string, int32> sint32Map = 61; - */ - boolean containsSint32Map( - java.lang.String key); - /** - * Use {@link #getSint32MapMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getSint32Map(); - /** - * map<string, int32> sint32Map = 61; - */ - java.util.Map - getSint32MapMap(); - /** - * map<string, int32> sint32Map = 61; - */ - - int getSint32MapOrDefault( - java.lang.String key, - int defaultValue); - /** - * map<string, int32> sint32Map = 61; - */ - - int getSint32MapOrThrow( - java.lang.String key); - - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - int getSpMapCount(); - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - boolean containsSpMap( - java.lang.String key); - /** - * Use {@link #getSpMapMap()} instead. - */ - @java.lang.Deprecated - java.util.Map - getSpMap(); - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - java.util.Map - getSpMapMap(); - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getSpMapOrDefault( - java.lang.String key, - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User defaultValue); - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getSpMapOrThrow( - java.lang.String key); - - /** - * repeated int32 int32sPacked = 70; - */ - java.util.List getInt32SPackedList(); - /** - * repeated int32 int32sPacked = 70; - */ - int getInt32SPackedCount(); - /** - * repeated int32 int32sPacked = 70; - */ - int getInt32SPacked(int index); - - /** - * repeated int64 int64sPacked = 71; - */ - java.util.List getInt64SPackedList(); - /** - * repeated int64 int64sPacked = 71; - */ - int getInt64SPackedCount(); - /** - * repeated int64 int64sPacked = 71; - */ - long getInt64SPacked(int index); - - /** - * repeated uint32 uint32sPacked = 72; - */ - java.util.List getUint32SPackedList(); - /** - * repeated uint32 uint32sPacked = 72; - */ - int getUint32SPackedCount(); - /** - * repeated uint32 uint32sPacked = 72; - */ - int getUint32SPacked(int index); - - /** - * repeated uint64 uint64sPacked = 73; - */ - java.util.List getUint64SPackedList(); - /** - * repeated uint64 uint64sPacked = 73; - */ - int getUint64SPackedCount(); - /** - * repeated uint64 uint64sPacked = 73; - */ - long getUint64SPacked(int index); - - /** - * repeated sint32 sint32sPacked = 74; - */ - java.util.List getSint32SPackedList(); - /** - * repeated sint32 sint32sPacked = 74; - */ - int getSint32SPackedCount(); - /** - * repeated sint32 sint32sPacked = 74; - */ - int getSint32SPacked(int index); - - /** - * repeated sint64 sint64sPacked = 75; - */ - java.util.List getSint64SPackedList(); - /** - * repeated sint64 sint64sPacked = 75; - */ - int getSint64SPackedCount(); - /** - * repeated sint64 sint64sPacked = 75; - */ - long getSint64SPacked(int index); - - /** - * repeated fixed32 fixed32sPacked = 76; - */ - java.util.List getFixed32SPackedList(); - /** - * repeated fixed32 fixed32sPacked = 76; - */ - int getFixed32SPackedCount(); - /** - * repeated fixed32 fixed32sPacked = 76; - */ - int getFixed32SPacked(int index); - - /** - * repeated fixed64 fixed64sPacked = 77; - */ - java.util.List getFixed64SPackedList(); - /** - * repeated fixed64 fixed64sPacked = 77; - */ - int getFixed64SPackedCount(); - /** - * repeated fixed64 fixed64sPacked = 77; - */ - long getFixed64SPacked(int index); - - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - java.util.List getSfixed32SPackedList(); - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - int getSfixed32SPackedCount(); - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - int getSfixed32SPacked(int index); - - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - java.util.List getSfixed64SPackedList(); - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - int getSfixed64SPackedCount(); - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - long getSfixed64SPacked(int index); - - /** - * repeated float floatsPacked = 80; - */ - java.util.List getFloatsPackedList(); - /** - * repeated float floatsPacked = 80; - */ - int getFloatsPackedCount(); - /** - * repeated float floatsPacked = 80; - */ - float getFloatsPacked(int index); - - /** - * repeated double doublesPacked = 81; - */ - java.util.List getDoublesPackedList(); - /** - * repeated double doublesPacked = 81; - */ - int getDoublesPackedCount(); - /** - * repeated double doublesPacked = 81; - */ - double getDoublesPacked(int index); - - /** - * repeated bool boolsPacked = 82; - */ - java.util.List getBoolsPackedList(); - /** - * repeated bool boolsPacked = 82; - */ - int getBoolsPackedCount(); - /** - * repeated bool boolsPacked = 82; - */ - boolean getBoolsPacked(int index); - - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - java.util.List getColorsPackedList(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - int getColorsPackedCount(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColorsPacked(int index); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - java.util.List - getColorsPackedValueList(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - int getColorsPackedValue(int index); - - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - java.util.List getInt32SNotPackedList(); - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - int getInt32SNotPackedCount(); - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - int getInt32SNotPacked(int index); - - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - java.util.List getInt64SNotPackedList(); - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - int getInt64SNotPackedCount(); - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - long getInt64SNotPacked(int index); - - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - java.util.List getUint32SNotPackedList(); - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - int getUint32SNotPackedCount(); - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - int getUint32SNotPacked(int index); - - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - java.util.List getUint64SNotPackedList(); - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - int getUint64SNotPackedCount(); - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - long getUint64SNotPacked(int index); - - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - java.util.List getSint32SNotPackedList(); - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - int getSint32SNotPackedCount(); - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - int getSint32SNotPacked(int index); - - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - java.util.List getSint64SNotPackedList(); - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - int getSint64SNotPackedCount(); - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - long getSint64SNotPacked(int index); - - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - java.util.List getFixed32SNotPackedList(); - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - int getFixed32SNotPackedCount(); - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - int getFixed32SNotPacked(int index); - - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - java.util.List getFixed64SNotPackedList(); - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - int getFixed64SNotPackedCount(); - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - long getFixed64SNotPacked(int index); - - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - java.util.List getSfixed32SNotPackedList(); - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - int getSfixed32SNotPackedCount(); - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - int getSfixed32SNotPacked(int index); - - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - java.util.List getSfixed64SNotPackedList(); - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - int getSfixed64SNotPackedCount(); - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - long getSfixed64SNotPacked(int index); - - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - java.util.List getFloatsNotPackedList(); - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - int getFloatsNotPackedCount(); - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - float getFloatsNotPacked(int index); - - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - java.util.List getDoublesNotPackedList(); - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - int getDoublesNotPackedCount(); - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - double getDoublesNotPacked(int index); - - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - java.util.List getBoolsNotPackedList(); - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - int getBoolsNotPackedCount(); - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - boolean getBoolsNotPacked(int index); - - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - java.util.List getColorsNotPackedList(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - int getColorsNotPackedCount(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColorsNotPacked(int index); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - java.util.List - getColorsNotPackedValueList(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - int getColorsNotPackedValue(int index); - - /** - * repeated string strings = 110; - */ - java.util.List - getStringsList(); - /** - * repeated string strings = 110; - */ - int getStringsCount(); - /** - * repeated string strings = 110; - */ - java.lang.String getStrings(int index); - /** - * repeated string strings = 110; - */ - com.google.protobuf.ByteString - getStringsBytes(int index); - - /** - * repeated bytes bytess = 111; - */ - java.util.List getBytessList(); - /** - * repeated bytes bytess = 111; - */ - int getBytessCount(); - /** - * repeated bytes bytess = 111; - */ - com.google.protobuf.ByteString getBytess(int index); - - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - java.util.List - getUsersList(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getUsers(int index); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - int getUsersCount(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - java.util.List - getUsersOrBuilderList(); - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder getUsersOrBuilder( - int index); - } - /** - * Protobuf type {@code org.apache.servicecomb.foundation.protobuf.internal.model.Root} - */ - public static final class Root extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:org.apache.servicecomb.foundation.protobuf.internal.model.Root) - RootOrBuilder { - private static final long serialVersionUID = 0L; - // Use Root.newBuilder() to construct. - private Root(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - private Root() { - int32_ = 0; - int64_ = 0L; - uint32_ = 0; - uint64_ = 0L; - sint32_ = 0; - sint64_ = 0L; - fixed32_ = 0; - fixed64_ = 0L; - sfixed32_ = 0; - sfixed64_ = 0L; - floatValue_ = 0F; - doubleValue_ = 0D; - bool_ = false; - objInt32_ = 0; - objInt64_ = 0L; - objUint32_ = 0; - objUint64_ = 0L; - objSint32_ = 0; - objSint64_ = 0L; - objFixed32_ = 0; - objFixed64_ = 0L; - objSfixed32_ = 0; - objSfixed64_ = 0L; - objFloatValue_ = 0F; - objDoubleValue_ = 0D; - objBool_ = false; - string_ = ""; - bytes_ = com.google.protobuf.ByteString.EMPTY; - color_ = 0; - anys_ = java.util.Collections.emptyList(); - int32SPacked_ = java.util.Collections.emptyList(); - int64SPacked_ = java.util.Collections.emptyList(); - uint32SPacked_ = java.util.Collections.emptyList(); - uint64SPacked_ = java.util.Collections.emptyList(); - sint32SPacked_ = java.util.Collections.emptyList(); - sint64SPacked_ = java.util.Collections.emptyList(); - fixed32SPacked_ = java.util.Collections.emptyList(); - fixed64SPacked_ = java.util.Collections.emptyList(); - sfixed32SPacked_ = java.util.Collections.emptyList(); - sfixed64SPacked_ = java.util.Collections.emptyList(); - floatsPacked_ = java.util.Collections.emptyList(); - doublesPacked_ = java.util.Collections.emptyList(); - boolsPacked_ = java.util.Collections.emptyList(); - colorsPacked_ = java.util.Collections.emptyList(); - int32SNotPacked_ = java.util.Collections.emptyList(); - int64SNotPacked_ = java.util.Collections.emptyList(); - uint32SNotPacked_ = java.util.Collections.emptyList(); - uint64SNotPacked_ = java.util.Collections.emptyList(); - sint32SNotPacked_ = java.util.Collections.emptyList(); - sint64SNotPacked_ = java.util.Collections.emptyList(); - fixed32SNotPacked_ = java.util.Collections.emptyList(); - fixed64SNotPacked_ = java.util.Collections.emptyList(); - sfixed32SNotPacked_ = java.util.Collections.emptyList(); - sfixed64SNotPacked_ = java.util.Collections.emptyList(); - floatsNotPacked_ = java.util.Collections.emptyList(); - doublesNotPacked_ = java.util.Collections.emptyList(); - boolsNotPacked_ = java.util.Collections.emptyList(); - colorsNotPacked_ = java.util.Collections.emptyList(); - strings_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bytess_ = java.util.Collections.emptyList(); - users_ = java.util.Collections.emptyList(); - } - - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private Root( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - int mutable_bitField0_ = 0; - int mutable_bitField1_ = 0; - int mutable_bitField2_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 8: { - - int32_ = input.readInt32(); - break; - } - case 16: { - - int64_ = input.readInt64(); - break; - } - case 24: { - - uint32_ = input.readUInt32(); - break; - } - case 32: { - - uint64_ = input.readUInt64(); - break; - } - case 40: { - - sint32_ = input.readSInt32(); - break; - } - case 48: { - - sint64_ = input.readSInt64(); - break; - } - case 61: { - - fixed32_ = input.readFixed32(); - break; - } - case 65: { - - fixed64_ = input.readFixed64(); - break; - } - case 77: { - - sfixed32_ = input.readSFixed32(); - break; - } - case 81: { - - sfixed64_ = input.readSFixed64(); - break; - } - case 93: { - - floatValue_ = input.readFloat(); - break; - } - case 97: { - - doubleValue_ = input.readDouble(); - break; - } - case 104: { - - bool_ = input.readBool(); - break; - } - case 160: { - - objInt32_ = input.readInt32(); - break; - } - case 168: { - - objInt64_ = input.readInt64(); - break; - } - case 176: { - - objUint32_ = input.readUInt32(); - break; - } - case 184: { - - objUint64_ = input.readUInt64(); - break; - } - case 192: { - - objSint32_ = input.readSInt32(); - break; - } - case 200: { - - objSint64_ = input.readSInt64(); - break; - } - case 213: { - - objFixed32_ = input.readFixed32(); - break; - } - case 217: { - - objFixed64_ = input.readFixed64(); - break; - } - case 229: { - - objSfixed32_ = input.readSFixed32(); - break; - } - case 233: { - - objSfixed64_ = input.readSFixed64(); - break; - } - case 245: { - - objFloatValue_ = input.readFloat(); - break; - } - case 249: { - - objDoubleValue_ = input.readDouble(); - break; - } - case 256: { - - objBool_ = input.readBool(); - break; - } - case 322: { - java.lang.String s = input.readStringRequireUtf8(); - - string_ = s; - break; - } - case 330: { - - bytes_ = input.readBytes(); - break; - } - case 336: { - int rawValue = input.readEnum(); - - color_ = rawValue; - break; - } - case 346: { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder subBuilder = null; - if (user_ != null) { - subBuilder = user_.toBuilder(); - } - user_ = input.readMessage(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.parser(), extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(user_); - user_ = subBuilder.buildPartial(); - } - - break; - } - case 354: { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder subBuilder = null; - if (typeRecursive_ != null) { - subBuilder = typeRecursive_.toBuilder(); - } - typeRecursive_ = input.readMessage(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.parser(), extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(typeRecursive_); - typeRecursive_ = subBuilder.buildPartial(); - } - - break; - } - case 402: { - com.google.protobuf.Any.Builder subBuilder = null; - if (any_ != null) { - subBuilder = any_.toBuilder(); - } - any_ = input.readMessage(com.google.protobuf.Any.parser(), extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(any_); - any_ = subBuilder.buildPartial(); - } - - break; - } - case 410: { - if (!((mutable_bitField1_ & 0x00000001) == 0x00000001)) { - anys_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000001; - } - anys_.add( - input.readMessage(com.google.protobuf.Any.parser(), extensionRegistry)); - break; - } - case 482: { - if (!((mutable_bitField1_ & 0x00000002) == 0x00000002)) { - ssMap_ = com.google.protobuf.MapField.newMapField( - SsMapDefaultEntryHolder.defaultEntry); - mutable_bitField1_ |= 0x00000002; - } - com.google.protobuf.MapEntry - ssMap__ = input.readMessage( - SsMapDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - ssMap_.getMutableMap().put( - ssMap__.getKey(), ssMap__.getValue()); - break; - } - case 490: { - if (!((mutable_bitField1_ & 0x00000004) == 0x00000004)) { - sint32Map_ = com.google.protobuf.MapField.newMapField( - Sint32MapDefaultEntryHolder.defaultEntry); - mutable_bitField1_ |= 0x00000004; - } - com.google.protobuf.MapEntry - sint32Map__ = input.readMessage( - Sint32MapDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - sint32Map_.getMutableMap().put( - sint32Map__.getKey(), sint32Map__.getValue()); - break; - } - case 498: { - if (!((mutable_bitField1_ & 0x00000008) == 0x00000008)) { - spMap_ = com.google.protobuf.MapField.newMapField( - SpMapDefaultEntryHolder.defaultEntry); - mutable_bitField1_ |= 0x00000008; - } - com.google.protobuf.MapEntry - spMap__ = input.readMessage( - SpMapDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry); - spMap_.getMutableMap().put( - spMap__.getKey(), spMap__.getValue()); - break; - } - case 560: { - if (!((mutable_bitField1_ & 0x00000010) == 0x00000010)) { - int32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000010; - } - int32SPacked_.add(input.readInt32()); - break; - } - case 562: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000010) == 0x00000010) && input.getBytesUntilLimit() > 0) { - int32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000010; - } - while (input.getBytesUntilLimit() > 0) { - int32SPacked_.add(input.readInt32()); - } - input.popLimit(limit); - break; - } - case 568: { - if (!((mutable_bitField1_ & 0x00000020) == 0x00000020)) { - int64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000020; - } - int64SPacked_.add(input.readInt64()); - break; - } - case 570: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000020) == 0x00000020) && input.getBytesUntilLimit() > 0) { - int64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000020; - } - while (input.getBytesUntilLimit() > 0) { - int64SPacked_.add(input.readInt64()); - } - input.popLimit(limit); - break; - } - case 576: { - if (!((mutable_bitField1_ & 0x00000040) == 0x00000040)) { - uint32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000040; - } - uint32SPacked_.add(input.readUInt32()); - break; - } - case 578: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000040) == 0x00000040) && input.getBytesUntilLimit() > 0) { - uint32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000040; - } - while (input.getBytesUntilLimit() > 0) { - uint32SPacked_.add(input.readUInt32()); - } - input.popLimit(limit); - break; - } - case 584: { - if (!((mutable_bitField1_ & 0x00000080) == 0x00000080)) { - uint64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000080; - } - uint64SPacked_.add(input.readUInt64()); - break; - } - case 586: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000080) == 0x00000080) && input.getBytesUntilLimit() > 0) { - uint64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000080; - } - while (input.getBytesUntilLimit() > 0) { - uint64SPacked_.add(input.readUInt64()); - } - input.popLimit(limit); - break; - } - case 592: { - if (!((mutable_bitField1_ & 0x00000100) == 0x00000100)) { - sint32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000100; - } - sint32SPacked_.add(input.readSInt32()); - break; - } - case 594: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000100) == 0x00000100) && input.getBytesUntilLimit() > 0) { - sint32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000100; - } - while (input.getBytesUntilLimit() > 0) { - sint32SPacked_.add(input.readSInt32()); - } - input.popLimit(limit); - break; - } - case 600: { - if (!((mutable_bitField1_ & 0x00000200) == 0x00000200)) { - sint64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000200; - } - sint64SPacked_.add(input.readSInt64()); - break; - } - case 602: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000200) == 0x00000200) && input.getBytesUntilLimit() > 0) { - sint64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000200; - } - while (input.getBytesUntilLimit() > 0) { - sint64SPacked_.add(input.readSInt64()); - } - input.popLimit(limit); - break; - } - case 613: { - if (!((mutable_bitField1_ & 0x00000400) == 0x00000400)) { - fixed32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000400; - } - fixed32SPacked_.add(input.readFixed32()); - break; - } - case 610: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000400) == 0x00000400) && input.getBytesUntilLimit() > 0) { - fixed32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000400; - } - while (input.getBytesUntilLimit() > 0) { - fixed32SPacked_.add(input.readFixed32()); - } - input.popLimit(limit); - break; - } - case 617: { - if (!((mutable_bitField1_ & 0x00000800) == 0x00000800)) { - fixed64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000800; - } - fixed64SPacked_.add(input.readFixed64()); - break; - } - case 618: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00000800) == 0x00000800) && input.getBytesUntilLimit() > 0) { - fixed64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00000800; - } - while (input.getBytesUntilLimit() > 0) { - fixed64SPacked_.add(input.readFixed64()); - } - input.popLimit(limit); - break; - } - case 629: { - if (!((mutable_bitField1_ & 0x00001000) == 0x00001000)) { - sfixed32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00001000; - } - sfixed32SPacked_.add(input.readSFixed32()); - break; - } - case 626: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00001000) == 0x00001000) && input.getBytesUntilLimit() > 0) { - sfixed32SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00001000; - } - while (input.getBytesUntilLimit() > 0) { - sfixed32SPacked_.add(input.readSFixed32()); - } - input.popLimit(limit); - break; - } - case 633: { - if (!((mutable_bitField1_ & 0x00002000) == 0x00002000)) { - sfixed64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00002000; - } - sfixed64SPacked_.add(input.readSFixed64()); - break; - } - case 634: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00002000) == 0x00002000) && input.getBytesUntilLimit() > 0) { - sfixed64SPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00002000; - } - while (input.getBytesUntilLimit() > 0) { - sfixed64SPacked_.add(input.readSFixed64()); - } - input.popLimit(limit); - break; - } - case 645: { - if (!((mutable_bitField1_ & 0x00004000) == 0x00004000)) { - floatsPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00004000; - } - floatsPacked_.add(input.readFloat()); - break; - } - case 642: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00004000) == 0x00004000) && input.getBytesUntilLimit() > 0) { - floatsPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00004000; - } - while (input.getBytesUntilLimit() > 0) { - floatsPacked_.add(input.readFloat()); - } - input.popLimit(limit); - break; - } - case 649: { - if (!((mutable_bitField1_ & 0x00008000) == 0x00008000)) { - doublesPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00008000; - } - doublesPacked_.add(input.readDouble()); - break; - } - case 650: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00008000) == 0x00008000) && input.getBytesUntilLimit() > 0) { - doublesPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00008000; - } - while (input.getBytesUntilLimit() > 0) { - doublesPacked_.add(input.readDouble()); - } - input.popLimit(limit); - break; - } - case 656: { - if (!((mutable_bitField1_ & 0x00010000) == 0x00010000)) { - boolsPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00010000; - } - boolsPacked_.add(input.readBool()); - break; - } - case 658: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00010000) == 0x00010000) && input.getBytesUntilLimit() > 0) { - boolsPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00010000; - } - while (input.getBytesUntilLimit() > 0) { - boolsPacked_.add(input.readBool()); - } - input.popLimit(limit); - break; - } - case 664: { - int rawValue = input.readEnum(); - if (!((mutable_bitField1_ & 0x00020000) == 0x00020000)) { - colorsPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00020000; - } - colorsPacked_.add(rawValue); - break; - } - case 666: { - int length = input.readRawVarint32(); - int oldLimit = input.pushLimit(length); - while(input.getBytesUntilLimit() > 0) { - int rawValue = input.readEnum(); - if (!((mutable_bitField1_ & 0x00020000) == 0x00020000)) { - colorsPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00020000; - } - colorsPacked_.add(rawValue); - } - input.popLimit(oldLimit); - break; - } - case 720: { - if (!((mutable_bitField1_ & 0x00040000) == 0x00040000)) { - int32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00040000; - } - int32SNotPacked_.add(input.readInt32()); - break; - } - case 722: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00040000) == 0x00040000) && input.getBytesUntilLimit() > 0) { - int32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00040000; - } - while (input.getBytesUntilLimit() > 0) { - int32SNotPacked_.add(input.readInt32()); - } - input.popLimit(limit); - break; - } - case 728: { - if (!((mutable_bitField1_ & 0x00080000) == 0x00080000)) { - int64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00080000; - } - int64SNotPacked_.add(input.readInt64()); - break; - } - case 730: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00080000) == 0x00080000) && input.getBytesUntilLimit() > 0) { - int64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00080000; - } - while (input.getBytesUntilLimit() > 0) { - int64SNotPacked_.add(input.readInt64()); - } - input.popLimit(limit); - break; - } - case 736: { - if (!((mutable_bitField1_ & 0x00100000) == 0x00100000)) { - uint32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00100000; - } - uint32SNotPacked_.add(input.readUInt32()); - break; - } - case 738: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00100000) == 0x00100000) && input.getBytesUntilLimit() > 0) { - uint32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00100000; - } - while (input.getBytesUntilLimit() > 0) { - uint32SNotPacked_.add(input.readUInt32()); - } - input.popLimit(limit); - break; - } - case 744: { - if (!((mutable_bitField1_ & 0x00200000) == 0x00200000)) { - uint64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00200000; - } - uint64SNotPacked_.add(input.readUInt64()); - break; - } - case 746: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00200000) == 0x00200000) && input.getBytesUntilLimit() > 0) { - uint64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00200000; - } - while (input.getBytesUntilLimit() > 0) { - uint64SNotPacked_.add(input.readUInt64()); - } - input.popLimit(limit); - break; - } - case 752: { - if (!((mutable_bitField1_ & 0x00400000) == 0x00400000)) { - sint32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00400000; - } - sint32SNotPacked_.add(input.readSInt32()); - break; - } - case 754: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00400000) == 0x00400000) && input.getBytesUntilLimit() > 0) { - sint32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00400000; - } - while (input.getBytesUntilLimit() > 0) { - sint32SNotPacked_.add(input.readSInt32()); - } - input.popLimit(limit); - break; - } - case 760: { - if (!((mutable_bitField1_ & 0x00800000) == 0x00800000)) { - sint64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00800000; - } - sint64SNotPacked_.add(input.readSInt64()); - break; - } - case 762: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x00800000) == 0x00800000) && input.getBytesUntilLimit() > 0) { - sint64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x00800000; - } - while (input.getBytesUntilLimit() > 0) { - sint64SNotPacked_.add(input.readSInt64()); - } - input.popLimit(limit); - break; - } - case 773: { - if (!((mutable_bitField1_ & 0x01000000) == 0x01000000)) { - fixed32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x01000000; - } - fixed32SNotPacked_.add(input.readFixed32()); - break; - } - case 770: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x01000000) == 0x01000000) && input.getBytesUntilLimit() > 0) { - fixed32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x01000000; - } - while (input.getBytesUntilLimit() > 0) { - fixed32SNotPacked_.add(input.readFixed32()); - } - input.popLimit(limit); - break; - } - case 777: { - if (!((mutable_bitField1_ & 0x02000000) == 0x02000000)) { - fixed64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x02000000; - } - fixed64SNotPacked_.add(input.readFixed64()); - break; - } - case 778: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x02000000) == 0x02000000) && input.getBytesUntilLimit() > 0) { - fixed64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x02000000; - } - while (input.getBytesUntilLimit() > 0) { - fixed64SNotPacked_.add(input.readFixed64()); - } - input.popLimit(limit); - break; - } - case 789: { - if (!((mutable_bitField1_ & 0x04000000) == 0x04000000)) { - sfixed32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x04000000; - } - sfixed32SNotPacked_.add(input.readSFixed32()); - break; - } - case 786: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x04000000) == 0x04000000) && input.getBytesUntilLimit() > 0) { - sfixed32SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x04000000; - } - while (input.getBytesUntilLimit() > 0) { - sfixed32SNotPacked_.add(input.readSFixed32()); - } - input.popLimit(limit); - break; - } - case 793: { - if (!((mutable_bitField1_ & 0x08000000) == 0x08000000)) { - sfixed64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x08000000; - } - sfixed64SNotPacked_.add(input.readSFixed64()); - break; - } - case 794: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x08000000) == 0x08000000) && input.getBytesUntilLimit() > 0) { - sfixed64SNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x08000000; - } - while (input.getBytesUntilLimit() > 0) { - sfixed64SNotPacked_.add(input.readSFixed64()); - } - input.popLimit(limit); - break; - } - case 805: { - if (!((mutable_bitField1_ & 0x10000000) == 0x10000000)) { - floatsNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x10000000; - } - floatsNotPacked_.add(input.readFloat()); - break; - } - case 802: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x10000000) == 0x10000000) && input.getBytesUntilLimit() > 0) { - floatsNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x10000000; - } - while (input.getBytesUntilLimit() > 0) { - floatsNotPacked_.add(input.readFloat()); - } - input.popLimit(limit); - break; - } - case 809: { - if (!((mutable_bitField1_ & 0x20000000) == 0x20000000)) { - doublesNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x20000000; - } - doublesNotPacked_.add(input.readDouble()); - break; - } - case 810: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x20000000) == 0x20000000) && input.getBytesUntilLimit() > 0) { - doublesNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x20000000; - } - while (input.getBytesUntilLimit() > 0) { - doublesNotPacked_.add(input.readDouble()); - } - input.popLimit(limit); - break; - } - case 816: { - if (!((mutable_bitField1_ & 0x40000000) == 0x40000000)) { - boolsNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x40000000; - } - boolsNotPacked_.add(input.readBool()); - break; - } - case 818: { - int length = input.readRawVarint32(); - int limit = input.pushLimit(length); - if (!((mutable_bitField1_ & 0x40000000) == 0x40000000) && input.getBytesUntilLimit() > 0) { - boolsNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x40000000; - } - while (input.getBytesUntilLimit() > 0) { - boolsNotPacked_.add(input.readBool()); - } - input.popLimit(limit); - break; - } - case 824: { - int rawValue = input.readEnum(); - if (!((mutable_bitField1_ & 0x80000000) == 0x80000000)) { - colorsNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x80000000; - } - colorsNotPacked_.add(rawValue); - break; - } - case 826: { - int length = input.readRawVarint32(); - int oldLimit = input.pushLimit(length); - while(input.getBytesUntilLimit() > 0) { - int rawValue = input.readEnum(); - if (!((mutable_bitField1_ & 0x80000000) == 0x80000000)) { - colorsNotPacked_ = new java.util.ArrayList(); - mutable_bitField1_ |= 0x80000000; - } - colorsNotPacked_.add(rawValue); - } - input.popLimit(oldLimit); - break; - } - case 882: { - java.lang.String s = input.readStringRequireUtf8(); - if (!((mutable_bitField2_ & 0x00000001) == 0x00000001)) { - strings_ = new com.google.protobuf.LazyStringArrayList(); - mutable_bitField2_ |= 0x00000001; - } - strings_.add(s); - break; - } - case 890: { - if (!((mutable_bitField2_ & 0x00000002) == 0x00000002)) { - bytess_ = new java.util.ArrayList(); - mutable_bitField2_ |= 0x00000002; - } - bytess_.add(input.readBytes()); - break; - } - case 898: { - if (!((mutable_bitField2_ & 0x00000004) == 0x00000004)) { - users_ = new java.util.ArrayList(); - mutable_bitField2_ |= 0x00000004; - } - users_.add( - input.readMessage(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.parser(), extensionRegistry)); - break; - } - default: { - if (!parseUnknownFieldProto3( - input, unknownFields, extensionRegistry, tag)) { - done = true; - } - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - if (((mutable_bitField1_ & 0x00000001) == 0x00000001)) { - anys_ = java.util.Collections.unmodifiableList(anys_); - } - if (((mutable_bitField1_ & 0x00000010) == 0x00000010)) { - int32SPacked_ = java.util.Collections.unmodifiableList(int32SPacked_); - } - if (((mutable_bitField1_ & 0x00000020) == 0x00000020)) { - int64SPacked_ = java.util.Collections.unmodifiableList(int64SPacked_); - } - if (((mutable_bitField1_ & 0x00000040) == 0x00000040)) { - uint32SPacked_ = java.util.Collections.unmodifiableList(uint32SPacked_); - } - if (((mutable_bitField1_ & 0x00000080) == 0x00000080)) { - uint64SPacked_ = java.util.Collections.unmodifiableList(uint64SPacked_); - } - if (((mutable_bitField1_ & 0x00000100) == 0x00000100)) { - sint32SPacked_ = java.util.Collections.unmodifiableList(sint32SPacked_); - } - if (((mutable_bitField1_ & 0x00000200) == 0x00000200)) { - sint64SPacked_ = java.util.Collections.unmodifiableList(sint64SPacked_); - } - if (((mutable_bitField1_ & 0x00000400) == 0x00000400)) { - fixed32SPacked_ = java.util.Collections.unmodifiableList(fixed32SPacked_); - } - if (((mutable_bitField1_ & 0x00000800) == 0x00000800)) { - fixed64SPacked_ = java.util.Collections.unmodifiableList(fixed64SPacked_); - } - if (((mutable_bitField1_ & 0x00001000) == 0x00001000)) { - sfixed32SPacked_ = java.util.Collections.unmodifiableList(sfixed32SPacked_); - } - if (((mutable_bitField1_ & 0x00002000) == 0x00002000)) { - sfixed64SPacked_ = java.util.Collections.unmodifiableList(sfixed64SPacked_); - } - if (((mutable_bitField1_ & 0x00004000) == 0x00004000)) { - floatsPacked_ = java.util.Collections.unmodifiableList(floatsPacked_); - } - if (((mutable_bitField1_ & 0x00008000) == 0x00008000)) { - doublesPacked_ = java.util.Collections.unmodifiableList(doublesPacked_); - } - if (((mutable_bitField1_ & 0x00010000) == 0x00010000)) { - boolsPacked_ = java.util.Collections.unmodifiableList(boolsPacked_); - } - if (((mutable_bitField1_ & 0x00020000) == 0x00020000)) { - colorsPacked_ = java.util.Collections.unmodifiableList(colorsPacked_); - } - if (((mutable_bitField1_ & 0x00040000) == 0x00040000)) { - int32SNotPacked_ = java.util.Collections.unmodifiableList(int32SNotPacked_); - } - if (((mutable_bitField1_ & 0x00080000) == 0x00080000)) { - int64SNotPacked_ = java.util.Collections.unmodifiableList(int64SNotPacked_); - } - if (((mutable_bitField1_ & 0x00100000) == 0x00100000)) { - uint32SNotPacked_ = java.util.Collections.unmodifiableList(uint32SNotPacked_); - } - if (((mutable_bitField1_ & 0x00200000) == 0x00200000)) { - uint64SNotPacked_ = java.util.Collections.unmodifiableList(uint64SNotPacked_); - } - if (((mutable_bitField1_ & 0x00400000) == 0x00400000)) { - sint32SNotPacked_ = java.util.Collections.unmodifiableList(sint32SNotPacked_); - } - if (((mutable_bitField1_ & 0x00800000) == 0x00800000)) { - sint64SNotPacked_ = java.util.Collections.unmodifiableList(sint64SNotPacked_); - } - if (((mutable_bitField1_ & 0x01000000) == 0x01000000)) { - fixed32SNotPacked_ = java.util.Collections.unmodifiableList(fixed32SNotPacked_); - } - if (((mutable_bitField1_ & 0x02000000) == 0x02000000)) { - fixed64SNotPacked_ = java.util.Collections.unmodifiableList(fixed64SNotPacked_); - } - if (((mutable_bitField1_ & 0x04000000) == 0x04000000)) { - sfixed32SNotPacked_ = java.util.Collections.unmodifiableList(sfixed32SNotPacked_); - } - if (((mutable_bitField1_ & 0x08000000) == 0x08000000)) { - sfixed64SNotPacked_ = java.util.Collections.unmodifiableList(sfixed64SNotPacked_); - } - if (((mutable_bitField1_ & 0x10000000) == 0x10000000)) { - floatsNotPacked_ = java.util.Collections.unmodifiableList(floatsNotPacked_); - } - if (((mutable_bitField1_ & 0x20000000) == 0x20000000)) { - doublesNotPacked_ = java.util.Collections.unmodifiableList(doublesNotPacked_); - } - if (((mutable_bitField1_ & 0x40000000) == 0x40000000)) { - boolsNotPacked_ = java.util.Collections.unmodifiableList(boolsNotPacked_); - } - if (((mutable_bitField1_ & 0x80000000) == 0x80000000)) { - colorsNotPacked_ = java.util.Collections.unmodifiableList(colorsNotPacked_); - } - if (((mutable_bitField2_ & 0x00000001) == 0x00000001)) { - strings_ = strings_.getUnmodifiableView(); - } - if (((mutable_bitField2_ & 0x00000002) == 0x00000002)) { - bytess_ = java.util.Collections.unmodifiableList(bytess_); - } - if (((mutable_bitField2_ & 0x00000004) == 0x00000004)) { - users_ = java.util.Collections.unmodifiableList(users_); - } - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - @java.lang.Override - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 60: - return internalGetSsMap(); - case 61: - return internalGetSint32Map(); - case 62: - return internalGetSpMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.class, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder.class); - } - - private int bitField0_; - public static final int INT32_FIELD_NUMBER = 1; - private int int32_; - /** - * int32 int32 = 1; - */ - public int getInt32() { - return int32_; - } - - public static final int INT64_FIELD_NUMBER = 2; - private long int64_; - /** - * int64 int64 = 2; - */ - public long getInt64() { - return int64_; - } - - public static final int UINT32_FIELD_NUMBER = 3; - private int uint32_; - /** - * uint32 uint32 = 3; - */ - public int getUint32() { - return uint32_; - } - - public static final int UINT64_FIELD_NUMBER = 4; - private long uint64_; - /** - * uint64 uint64 = 4; - */ - public long getUint64() { - return uint64_; - } - - public static final int SINT32_FIELD_NUMBER = 5; - private int sint32_; - /** - * sint32 sint32 = 5; - */ - public int getSint32() { - return sint32_; - } - - public static final int SINT64_FIELD_NUMBER = 6; - private long sint64_; - /** - * sint64 sint64 = 6; - */ - public long getSint64() { - return sint64_; - } - - public static final int FIXED32_FIELD_NUMBER = 7; - private int fixed32_; - /** - * fixed32 fixed32 = 7; - */ - public int getFixed32() { - return fixed32_; - } - - public static final int FIXED64_FIELD_NUMBER = 8; - private long fixed64_; - /** - * fixed64 fixed64 = 8; - */ - public long getFixed64() { - return fixed64_; - } - - public static final int SFIXED32_FIELD_NUMBER = 9; - private int sfixed32_; - /** - * sfixed32 sfixed32 = 9; - */ - public int getSfixed32() { - return sfixed32_; - } - - public static final int SFIXED64_FIELD_NUMBER = 10; - private long sfixed64_; - /** - * sfixed64 sfixed64 = 10; - */ - public long getSfixed64() { - return sfixed64_; - } - - public static final int FLOATVALUE_FIELD_NUMBER = 11; - private float floatValue_; - /** - * float floatValue = 11; - */ - public float getFloatValue() { - return floatValue_; - } - - public static final int DOUBLEVALUE_FIELD_NUMBER = 12; - private double doubleValue_; - /** - * double doubleValue = 12; - */ - public double getDoubleValue() { - return doubleValue_; - } - - public static final int BOOL_FIELD_NUMBER = 13; - private boolean bool_; - /** - * bool bool = 13; - */ - public boolean getBool() { - return bool_; - } - - public static final int OBJINT32_FIELD_NUMBER = 20; - private int objInt32_; - /** - * int32 objInt32 = 20; - */ - public int getObjInt32() { - return objInt32_; - } - - public static final int OBJINT64_FIELD_NUMBER = 21; - private long objInt64_; - /** - * int64 objInt64 = 21; - */ - public long getObjInt64() { - return objInt64_; - } - - public static final int OBJUINT32_FIELD_NUMBER = 22; - private int objUint32_; - /** - * uint32 objUint32 = 22; - */ - public int getObjUint32() { - return objUint32_; - } - - public static final int OBJUINT64_FIELD_NUMBER = 23; - private long objUint64_; - /** - * uint64 objUint64 = 23; - */ - public long getObjUint64() { - return objUint64_; - } - - public static final int OBJSINT32_FIELD_NUMBER = 24; - private int objSint32_; - /** - * sint32 objSint32 = 24; - */ - public int getObjSint32() { - return objSint32_; - } - - public static final int OBJSINT64_FIELD_NUMBER = 25; - private long objSint64_; - /** - * sint64 objSint64 = 25; - */ - public long getObjSint64() { - return objSint64_; - } - - public static final int OBJFIXED32_FIELD_NUMBER = 26; - private int objFixed32_; - /** - * fixed32 objFixed32 = 26; - */ - public int getObjFixed32() { - return objFixed32_; - } - - public static final int OBJFIXED64_FIELD_NUMBER = 27; - private long objFixed64_; - /** - * fixed64 objFixed64 = 27; - */ - public long getObjFixed64() { - return objFixed64_; - } - - public static final int OBJSFIXED32_FIELD_NUMBER = 28; - private int objSfixed32_; - /** - * sfixed32 objSfixed32 = 28; - */ - public int getObjSfixed32() { - return objSfixed32_; - } - - public static final int OBJSFIXED64_FIELD_NUMBER = 29; - private long objSfixed64_; - /** - * sfixed64 objSfixed64 = 29; - */ - public long getObjSfixed64() { - return objSfixed64_; - } - - public static final int OBJFLOATVALUE_FIELD_NUMBER = 30; - private float objFloatValue_; - /** - * float objFloatValue = 30; - */ - public float getObjFloatValue() { - return objFloatValue_; - } - - public static final int OBJDOUBLEVALUE_FIELD_NUMBER = 31; - private double objDoubleValue_; - /** - * double objDoubleValue = 31; - */ - public double getObjDoubleValue() { - return objDoubleValue_; - } - - public static final int OBJBOOL_FIELD_NUMBER = 32; - private boolean objBool_; - /** - * bool objBool = 32; - */ - public boolean getObjBool() { - return objBool_; - } - - public static final int STRING_FIELD_NUMBER = 40; - private volatile java.lang.Object string_; - /** - * string string = 40; - */ - public java.lang.String getString() { - java.lang.Object ref = string_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - string_ = s; - return s; - } - } - /** - * string string = 40; - */ - public com.google.protobuf.ByteString - getStringBytes() { - java.lang.Object ref = string_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - string_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int BYTES_FIELD_NUMBER = 41; - private com.google.protobuf.ByteString bytes_; - /** - * bytes bytes = 41; - */ - public com.google.protobuf.ByteString getBytes() { - return bytes_; - } - - public static final int COLOR_FIELD_NUMBER = 42; - private int color_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public int getColorValue() { - return color_; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColor() { - @SuppressWarnings("deprecation") - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color result = org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.valueOf(color_); - return result == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.UNRECOGNIZED : result; - } - - public static final int USER_FIELD_NUMBER = 43; - private org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User user_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public boolean hasUser() { - return user_ != null; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getUser() { - return user_ == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance() : user_; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder getUserOrBuilder() { - return getUser(); - } - - public static final int TYPERECURSIVE_FIELD_NUMBER = 44; - private org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root typeRecursive_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public boolean hasTypeRecursive() { - return typeRecursive_ != null; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getTypeRecursive() { - return typeRecursive_ == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance() : typeRecursive_; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder getTypeRecursiveOrBuilder() { - return getTypeRecursive(); - } - - public static final int ANY_FIELD_NUMBER = 50; - private com.google.protobuf.Any any_; - /** - * .google.protobuf.Any any = 50; - */ - public boolean hasAny() { - return any_ != null; - } - /** - * .google.protobuf.Any any = 50; - */ - public com.google.protobuf.Any getAny() { - return any_ == null ? com.google.protobuf.Any.getDefaultInstance() : any_; - } - /** - * .google.protobuf.Any any = 50; - */ - public com.google.protobuf.AnyOrBuilder getAnyOrBuilder() { - return getAny(); - } - - public static final int ANYS_FIELD_NUMBER = 51; - private java.util.List anys_; - /** - * repeated .google.protobuf.Any anys = 51; - */ - public java.util.List getAnysList() { - return anys_; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public java.util.List - getAnysOrBuilderList() { - return anys_; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public int getAnysCount() { - return anys_.size(); - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.Any getAnys(int index) { - return anys_.get(index); - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.AnyOrBuilder getAnysOrBuilder( - int index) { - return anys_.get(index); - } - - public static final int SSMAP_FIELD_NUMBER = 60; - private static final class SsMapDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.String> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SsMapEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.STRING, - ""); - } - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> ssMap_; - private com.google.protobuf.MapField - internalGetSsMap() { - if (ssMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - SsMapDefaultEntryHolder.defaultEntry); - } - return ssMap_; - } - - public int getSsMapCount() { - return internalGetSsMap().getMap().size(); - } - /** - * map<string, string> ssMap = 60; - */ - - public boolean containsSsMap( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - return internalGetSsMap().getMap().containsKey(key); - } - /** - * Use {@link #getSsMapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getSsMap() { - return getSsMapMap(); - } - /** - * map<string, string> ssMap = 60; - */ - - public java.util.Map getSsMapMap() { - return internalGetSsMap().getMap(); - } - /** - * map<string, string> ssMap = 60; - */ - - public java.lang.String getSsMapOrDefault( - java.lang.String key, - java.lang.String defaultValue) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSsMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> ssMap = 60; - */ - - public java.lang.String getSsMapOrThrow( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSsMap().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int SINT32MAP_FIELD_NUMBER = 61; - private static final class Sint32MapDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, java.lang.Integer> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_Sint32MapEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.INT32, - 0); - } - private com.google.protobuf.MapField< - java.lang.String, java.lang.Integer> sint32Map_; - private com.google.protobuf.MapField - internalGetSint32Map() { - if (sint32Map_ == null) { - return com.google.protobuf.MapField.emptyMapField( - Sint32MapDefaultEntryHolder.defaultEntry); - } - return sint32Map_; - } - - public int getSint32MapCount() { - return internalGetSint32Map().getMap().size(); - } - /** - * map<string, int32> sint32Map = 61; - */ - - public boolean containsSint32Map( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - return internalGetSint32Map().getMap().containsKey(key); - } - /** - * Use {@link #getSint32MapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getSint32Map() { - return getSint32MapMap(); - } - /** - * map<string, int32> sint32Map = 61; - */ - - public java.util.Map getSint32MapMap() { - return internalGetSint32Map().getMap(); - } - /** - * map<string, int32> sint32Map = 61; - */ - - public int getSint32MapOrDefault( - java.lang.String key, - int defaultValue) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSint32Map().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, int32> sint32Map = 61; - */ - - public int getSint32MapOrThrow( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSint32Map().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int SPMAP_FIELD_NUMBER = 62; - private static final class SpMapDefaultEntryHolder { - static final com.google.protobuf.MapEntry< - java.lang.String, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User> defaultEntry = - com.google.protobuf.MapEntry - .newDefaultInstance( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SpMapEntry_descriptor, - com.google.protobuf.WireFormat.FieldType.STRING, - "", - com.google.protobuf.WireFormat.FieldType.MESSAGE, - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance()); - } - private com.google.protobuf.MapField< - java.lang.String, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User> spMap_; - private com.google.protobuf.MapField - internalGetSpMap() { - if (spMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - SpMapDefaultEntryHolder.defaultEntry); - } - return spMap_; - } - - public int getSpMapCount() { - return internalGetSpMap().getMap().size(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public boolean containsSpMap( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - return internalGetSpMap().getMap().containsKey(key); - } - /** - * Use {@link #getSpMapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getSpMap() { - return getSpMapMap(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public java.util.Map getSpMapMap() { - return internalGetSpMap().getMap(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getSpMapOrDefault( - java.lang.String key, - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User defaultValue) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSpMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getSpMapOrThrow( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSpMap().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public static final int INT32SPACKED_FIELD_NUMBER = 70; - private java.util.List int32SPacked_; - /** - * repeated int32 int32sPacked = 70; - */ - public java.util.List - getInt32SPackedList() { - return int32SPacked_; - } - /** - * repeated int32 int32sPacked = 70; - */ - public int getInt32SPackedCount() { - return int32SPacked_.size(); - } - /** - * repeated int32 int32sPacked = 70; - */ - public int getInt32SPacked(int index) { - return int32SPacked_.get(index); - } - private int int32SPackedMemoizedSerializedSize = -1; - - public static final int INT64SPACKED_FIELD_NUMBER = 71; - private java.util.List int64SPacked_; - /** - * repeated int64 int64sPacked = 71; - */ - public java.util.List - getInt64SPackedList() { - return int64SPacked_; - } - /** - * repeated int64 int64sPacked = 71; - */ - public int getInt64SPackedCount() { - return int64SPacked_.size(); - } - /** - * repeated int64 int64sPacked = 71; - */ - public long getInt64SPacked(int index) { - return int64SPacked_.get(index); - } - private int int64SPackedMemoizedSerializedSize = -1; - - public static final int UINT32SPACKED_FIELD_NUMBER = 72; - private java.util.List uint32SPacked_; - /** - * repeated uint32 uint32sPacked = 72; - */ - public java.util.List - getUint32SPackedList() { - return uint32SPacked_; - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public int getUint32SPackedCount() { - return uint32SPacked_.size(); - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public int getUint32SPacked(int index) { - return uint32SPacked_.get(index); - } - private int uint32SPackedMemoizedSerializedSize = -1; - - public static final int UINT64SPACKED_FIELD_NUMBER = 73; - private java.util.List uint64SPacked_; - /** - * repeated uint64 uint64sPacked = 73; - */ - public java.util.List - getUint64SPackedList() { - return uint64SPacked_; - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public int getUint64SPackedCount() { - return uint64SPacked_.size(); - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public long getUint64SPacked(int index) { - return uint64SPacked_.get(index); - } - private int uint64SPackedMemoizedSerializedSize = -1; - - public static final int SINT32SPACKED_FIELD_NUMBER = 74; - private java.util.List sint32SPacked_; - /** - * repeated sint32 sint32sPacked = 74; - */ - public java.util.List - getSint32SPackedList() { - return sint32SPacked_; - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public int getSint32SPackedCount() { - return sint32SPacked_.size(); - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public int getSint32SPacked(int index) { - return sint32SPacked_.get(index); - } - private int sint32SPackedMemoizedSerializedSize = -1; - - public static final int SINT64SPACKED_FIELD_NUMBER = 75; - private java.util.List sint64SPacked_; - /** - * repeated sint64 sint64sPacked = 75; - */ - public java.util.List - getSint64SPackedList() { - return sint64SPacked_; - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public int getSint64SPackedCount() { - return sint64SPacked_.size(); - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public long getSint64SPacked(int index) { - return sint64SPacked_.get(index); - } - private int sint64SPackedMemoizedSerializedSize = -1; - - public static final int FIXED32SPACKED_FIELD_NUMBER = 76; - private java.util.List fixed32SPacked_; - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public java.util.List - getFixed32SPackedList() { - return fixed32SPacked_; - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public int getFixed32SPackedCount() { - return fixed32SPacked_.size(); - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public int getFixed32SPacked(int index) { - return fixed32SPacked_.get(index); - } - private int fixed32SPackedMemoizedSerializedSize = -1; - - public static final int FIXED64SPACKED_FIELD_NUMBER = 77; - private java.util.List fixed64SPacked_; - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public java.util.List - getFixed64SPackedList() { - return fixed64SPacked_; - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public int getFixed64SPackedCount() { - return fixed64SPacked_.size(); - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public long getFixed64SPacked(int index) { - return fixed64SPacked_.get(index); - } - private int fixed64SPackedMemoizedSerializedSize = -1; - - public static final int SFIXED32SPACKED_FIELD_NUMBER = 78; - private java.util.List sfixed32SPacked_; - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public java.util.List - getSfixed32SPackedList() { - return sfixed32SPacked_; - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public int getSfixed32SPackedCount() { - return sfixed32SPacked_.size(); - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public int getSfixed32SPacked(int index) { - return sfixed32SPacked_.get(index); - } - private int sfixed32SPackedMemoizedSerializedSize = -1; - - public static final int SFIXED64SPACKED_FIELD_NUMBER = 79; - private java.util.List sfixed64SPacked_; - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public java.util.List - getSfixed64SPackedList() { - return sfixed64SPacked_; - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public int getSfixed64SPackedCount() { - return sfixed64SPacked_.size(); - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public long getSfixed64SPacked(int index) { - return sfixed64SPacked_.get(index); - } - private int sfixed64SPackedMemoizedSerializedSize = -1; - - public static final int FLOATSPACKED_FIELD_NUMBER = 80; - private java.util.List floatsPacked_; - /** - * repeated float floatsPacked = 80; - */ - public java.util.List - getFloatsPackedList() { - return floatsPacked_; - } - /** - * repeated float floatsPacked = 80; - */ - public int getFloatsPackedCount() { - return floatsPacked_.size(); - } - /** - * repeated float floatsPacked = 80; - */ - public float getFloatsPacked(int index) { - return floatsPacked_.get(index); - } - private int floatsPackedMemoizedSerializedSize = -1; - - public static final int DOUBLESPACKED_FIELD_NUMBER = 81; - private java.util.List doublesPacked_; - /** - * repeated double doublesPacked = 81; - */ - public java.util.List - getDoublesPackedList() { - return doublesPacked_; - } - /** - * repeated double doublesPacked = 81; - */ - public int getDoublesPackedCount() { - return doublesPacked_.size(); - } - /** - * repeated double doublesPacked = 81; - */ - public double getDoublesPacked(int index) { - return doublesPacked_.get(index); - } - private int doublesPackedMemoizedSerializedSize = -1; - - public static final int BOOLSPACKED_FIELD_NUMBER = 82; - private java.util.List boolsPacked_; - /** - * repeated bool boolsPacked = 82; - */ - public java.util.List - getBoolsPackedList() { - return boolsPacked_; - } - /** - * repeated bool boolsPacked = 82; - */ - public int getBoolsPackedCount() { - return boolsPacked_.size(); - } - /** - * repeated bool boolsPacked = 82; - */ - public boolean getBoolsPacked(int index) { - return boolsPacked_.get(index); - } - private int boolsPackedMemoizedSerializedSize = -1; - - public static final int COLORSPACKED_FIELD_NUMBER = 83; - private java.util.List colorsPacked_; - private static final com.google.protobuf.Internal.ListAdapter.Converter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color> colorsPacked_converter_ = - new com.google.protobuf.Internal.ListAdapter.Converter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color>() { - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color convert(java.lang.Integer from) { - @SuppressWarnings("deprecation") - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color result = org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.valueOf(from); - return result == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.UNRECOGNIZED : result; - } - }; - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public java.util.List getColorsPackedList() { - return new com.google.protobuf.Internal.ListAdapter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color>(colorsPacked_, colorsPacked_converter_); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public int getColorsPackedCount() { - return colorsPacked_.size(); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColorsPacked(int index) { - return colorsPacked_converter_.convert(colorsPacked_.get(index)); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public java.util.List - getColorsPackedValueList() { - return colorsPacked_; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public int getColorsPackedValue(int index) { - return colorsPacked_.get(index); - } - private int colorsPackedMemoizedSerializedSize; - - public static final int INT32SNOTPACKED_FIELD_NUMBER = 90; - private java.util.List int32SNotPacked_; - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public java.util.List - getInt32SNotPackedList() { - return int32SNotPacked_; - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public int getInt32SNotPackedCount() { - return int32SNotPacked_.size(); - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public int getInt32SNotPacked(int index) { - return int32SNotPacked_.get(index); - } - - public static final int INT64SNOTPACKED_FIELD_NUMBER = 91; - private java.util.List int64SNotPacked_; - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public java.util.List - getInt64SNotPackedList() { - return int64SNotPacked_; - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public int getInt64SNotPackedCount() { - return int64SNotPacked_.size(); - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public long getInt64SNotPacked(int index) { - return int64SNotPacked_.get(index); - } - - public static final int UINT32SNOTPACKED_FIELD_NUMBER = 92; - private java.util.List uint32SNotPacked_; - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public java.util.List - getUint32SNotPackedList() { - return uint32SNotPacked_; - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public int getUint32SNotPackedCount() { - return uint32SNotPacked_.size(); - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public int getUint32SNotPacked(int index) { - return uint32SNotPacked_.get(index); - } - - public static final int UINT64SNOTPACKED_FIELD_NUMBER = 93; - private java.util.List uint64SNotPacked_; - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public java.util.List - getUint64SNotPackedList() { - return uint64SNotPacked_; - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public int getUint64SNotPackedCount() { - return uint64SNotPacked_.size(); - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public long getUint64SNotPacked(int index) { - return uint64SNotPacked_.get(index); - } - - public static final int SINT32SNOTPACKED_FIELD_NUMBER = 94; - private java.util.List sint32SNotPacked_; - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public java.util.List - getSint32SNotPackedList() { - return sint32SNotPacked_; - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public int getSint32SNotPackedCount() { - return sint32SNotPacked_.size(); - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public int getSint32SNotPacked(int index) { - return sint32SNotPacked_.get(index); - } - - public static final int SINT64SNOTPACKED_FIELD_NUMBER = 95; - private java.util.List sint64SNotPacked_; - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public java.util.List - getSint64SNotPackedList() { - return sint64SNotPacked_; - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public int getSint64SNotPackedCount() { - return sint64SNotPacked_.size(); - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public long getSint64SNotPacked(int index) { - return sint64SNotPacked_.get(index); - } - - public static final int FIXED32SNOTPACKED_FIELD_NUMBER = 96; - private java.util.List fixed32SNotPacked_; - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public java.util.List - getFixed32SNotPackedList() { - return fixed32SNotPacked_; - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public int getFixed32SNotPackedCount() { - return fixed32SNotPacked_.size(); - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public int getFixed32SNotPacked(int index) { - return fixed32SNotPacked_.get(index); - } - - public static final int FIXED64SNOTPACKED_FIELD_NUMBER = 97; - private java.util.List fixed64SNotPacked_; - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public java.util.List - getFixed64SNotPackedList() { - return fixed64SNotPacked_; - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public int getFixed64SNotPackedCount() { - return fixed64SNotPacked_.size(); - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public long getFixed64SNotPacked(int index) { - return fixed64SNotPacked_.get(index); - } - - public static final int SFIXED32SNOTPACKED_FIELD_NUMBER = 98; - private java.util.List sfixed32SNotPacked_; - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public java.util.List - getSfixed32SNotPackedList() { - return sfixed32SNotPacked_; - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public int getSfixed32SNotPackedCount() { - return sfixed32SNotPacked_.size(); - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public int getSfixed32SNotPacked(int index) { - return sfixed32SNotPacked_.get(index); - } - - public static final int SFIXED64SNOTPACKED_FIELD_NUMBER = 99; - private java.util.List sfixed64SNotPacked_; - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public java.util.List - getSfixed64SNotPackedList() { - return sfixed64SNotPacked_; - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public int getSfixed64SNotPackedCount() { - return sfixed64SNotPacked_.size(); - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public long getSfixed64SNotPacked(int index) { - return sfixed64SNotPacked_.get(index); - } - - public static final int FLOATSNOTPACKED_FIELD_NUMBER = 100; - private java.util.List floatsNotPacked_; - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public java.util.List - getFloatsNotPackedList() { - return floatsNotPacked_; - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public int getFloatsNotPackedCount() { - return floatsNotPacked_.size(); - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public float getFloatsNotPacked(int index) { - return floatsNotPacked_.get(index); - } - - public static final int DOUBLESNOTPACKED_FIELD_NUMBER = 101; - private java.util.List doublesNotPacked_; - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public java.util.List - getDoublesNotPackedList() { - return doublesNotPacked_; - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public int getDoublesNotPackedCount() { - return doublesNotPacked_.size(); - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public double getDoublesNotPacked(int index) { - return doublesNotPacked_.get(index); - } - - public static final int BOOLSNOTPACKED_FIELD_NUMBER = 102; - private java.util.List boolsNotPacked_; - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public java.util.List - getBoolsNotPackedList() { - return boolsNotPacked_; - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public int getBoolsNotPackedCount() { - return boolsNotPacked_.size(); - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public boolean getBoolsNotPacked(int index) { - return boolsNotPacked_.get(index); - } - - public static final int COLORSNOTPACKED_FIELD_NUMBER = 103; - private java.util.List colorsNotPacked_; - private static final com.google.protobuf.Internal.ListAdapter.Converter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color> colorsNotPacked_converter_ = - new com.google.protobuf.Internal.ListAdapter.Converter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color>() { - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color convert(java.lang.Integer from) { - @SuppressWarnings("deprecation") - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color result = org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.valueOf(from); - return result == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.UNRECOGNIZED : result; - } - }; - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public java.util.List getColorsNotPackedList() { - return new com.google.protobuf.Internal.ListAdapter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color>(colorsNotPacked_, colorsNotPacked_converter_); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public int getColorsNotPackedCount() { - return colorsNotPacked_.size(); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColorsNotPacked(int index) { - return colorsNotPacked_converter_.convert(colorsNotPacked_.get(index)); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public java.util.List - getColorsNotPackedValueList() { - return colorsNotPacked_; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public int getColorsNotPackedValue(int index) { - return colorsNotPacked_.get(index); - } - - public static final int STRINGS_FIELD_NUMBER = 110; - private com.google.protobuf.LazyStringList strings_; - /** - * repeated string strings = 110; - */ - public com.google.protobuf.ProtocolStringList - getStringsList() { - return strings_; - } - /** - * repeated string strings = 110; - */ - public int getStringsCount() { - return strings_.size(); - } - /** - * repeated string strings = 110; - */ - public java.lang.String getStrings(int index) { - return strings_.get(index); - } - /** - * repeated string strings = 110; - */ - public com.google.protobuf.ByteString - getStringsBytes(int index) { - return strings_.getByteString(index); - } - - public static final int BYTESS_FIELD_NUMBER = 111; - private java.util.List bytess_; - /** - * repeated bytes bytess = 111; - */ - public java.util.List - getBytessList() { - return bytess_; - } - /** - * repeated bytes bytess = 111; - */ - public int getBytessCount() { - return bytess_.size(); - } - /** - * repeated bytes bytess = 111; - */ - public com.google.protobuf.ByteString getBytess(int index) { - return bytess_.get(index); - } - - public static final int USERS_FIELD_NUMBER = 112; - private java.util.List users_; - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public java.util.List getUsersList() { - return users_; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public java.util.List - getUsersOrBuilderList() { - return users_; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public int getUsersCount() { - return users_.size(); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getUsers(int index) { - return users_.get(index); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder getUsersOrBuilder( - int index) { - return users_.get(index); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - getSerializedSize(); - if (int32_ != 0) { - output.writeInt32(1, int32_); - } - if (int64_ != 0L) { - output.writeInt64(2, int64_); - } - if (uint32_ != 0) { - output.writeUInt32(3, uint32_); - } - if (uint64_ != 0L) { - output.writeUInt64(4, uint64_); - } - if (sint32_ != 0) { - output.writeSInt32(5, sint32_); - } - if (sint64_ != 0L) { - output.writeSInt64(6, sint64_); - } - if (fixed32_ != 0) { - output.writeFixed32(7, fixed32_); - } - if (fixed64_ != 0L) { - output.writeFixed64(8, fixed64_); - } - if (sfixed32_ != 0) { - output.writeSFixed32(9, sfixed32_); - } - if (sfixed64_ != 0L) { - output.writeSFixed64(10, sfixed64_); - } - if (floatValue_ != 0F) { - output.writeFloat(11, floatValue_); - } - if (doubleValue_ != 0D) { - output.writeDouble(12, doubleValue_); - } - if (bool_ != false) { - output.writeBool(13, bool_); - } - if (objInt32_ != 0) { - output.writeInt32(20, objInt32_); - } - if (objInt64_ != 0L) { - output.writeInt64(21, objInt64_); - } - if (objUint32_ != 0) { - output.writeUInt32(22, objUint32_); - } - if (objUint64_ != 0L) { - output.writeUInt64(23, objUint64_); - } - if (objSint32_ != 0) { - output.writeSInt32(24, objSint32_); - } - if (objSint64_ != 0L) { - output.writeSInt64(25, objSint64_); - } - if (objFixed32_ != 0) { - output.writeFixed32(26, objFixed32_); - } - if (objFixed64_ != 0L) { - output.writeFixed64(27, objFixed64_); - } - if (objSfixed32_ != 0) { - output.writeSFixed32(28, objSfixed32_); - } - if (objSfixed64_ != 0L) { - output.writeSFixed64(29, objSfixed64_); - } - if (objFloatValue_ != 0F) { - output.writeFloat(30, objFloatValue_); - } - if (objDoubleValue_ != 0D) { - output.writeDouble(31, objDoubleValue_); - } - if (objBool_ != false) { - output.writeBool(32, objBool_); - } - if (!getStringBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 40, string_); - } - if (!bytes_.isEmpty()) { - output.writeBytes(41, bytes_); - } - if (color_ != org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.RED.getNumber()) { - output.writeEnum(42, color_); - } - if (user_ != null) { - output.writeMessage(43, getUser()); - } - if (typeRecursive_ != null) { - output.writeMessage(44, getTypeRecursive()); - } - if (any_ != null) { - output.writeMessage(50, getAny()); - } - for (int i = 0; i < anys_.size(); i++) { - output.writeMessage(51, anys_.get(i)); - } - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetSsMap(), - SsMapDefaultEntryHolder.defaultEntry, - 60); - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetSint32Map(), - Sint32MapDefaultEntryHolder.defaultEntry, - 61); - com.google.protobuf.GeneratedMessageV3 - .serializeStringMapTo( - output, - internalGetSpMap(), - SpMapDefaultEntryHolder.defaultEntry, - 62); - if (getInt32SPackedList().size() > 0) { - output.writeUInt32NoTag(562); - output.writeUInt32NoTag(int32SPackedMemoizedSerializedSize); - } - for (int i = 0; i < int32SPacked_.size(); i++) { - output.writeInt32NoTag(int32SPacked_.get(i)); - } - if (getInt64SPackedList().size() > 0) { - output.writeUInt32NoTag(570); - output.writeUInt32NoTag(int64SPackedMemoizedSerializedSize); - } - for (int i = 0; i < int64SPacked_.size(); i++) { - output.writeInt64NoTag(int64SPacked_.get(i)); - } - if (getUint32SPackedList().size() > 0) { - output.writeUInt32NoTag(578); - output.writeUInt32NoTag(uint32SPackedMemoizedSerializedSize); - } - for (int i = 0; i < uint32SPacked_.size(); i++) { - output.writeUInt32NoTag(uint32SPacked_.get(i)); - } - if (getUint64SPackedList().size() > 0) { - output.writeUInt32NoTag(586); - output.writeUInt32NoTag(uint64SPackedMemoizedSerializedSize); - } - for (int i = 0; i < uint64SPacked_.size(); i++) { - output.writeUInt64NoTag(uint64SPacked_.get(i)); - } - if (getSint32SPackedList().size() > 0) { - output.writeUInt32NoTag(594); - output.writeUInt32NoTag(sint32SPackedMemoizedSerializedSize); - } - for (int i = 0; i < sint32SPacked_.size(); i++) { - output.writeSInt32NoTag(sint32SPacked_.get(i)); - } - if (getSint64SPackedList().size() > 0) { - output.writeUInt32NoTag(602); - output.writeUInt32NoTag(sint64SPackedMemoizedSerializedSize); - } - for (int i = 0; i < sint64SPacked_.size(); i++) { - output.writeSInt64NoTag(sint64SPacked_.get(i)); - } - if (getFixed32SPackedList().size() > 0) { - output.writeUInt32NoTag(610); - output.writeUInt32NoTag(fixed32SPackedMemoizedSerializedSize); - } - for (int i = 0; i < fixed32SPacked_.size(); i++) { - output.writeFixed32NoTag(fixed32SPacked_.get(i)); - } - if (getFixed64SPackedList().size() > 0) { - output.writeUInt32NoTag(618); - output.writeUInt32NoTag(fixed64SPackedMemoizedSerializedSize); - } - for (int i = 0; i < fixed64SPacked_.size(); i++) { - output.writeFixed64NoTag(fixed64SPacked_.get(i)); - } - if (getSfixed32SPackedList().size() > 0) { - output.writeUInt32NoTag(626); - output.writeUInt32NoTag(sfixed32SPackedMemoizedSerializedSize); - } - for (int i = 0; i < sfixed32SPacked_.size(); i++) { - output.writeSFixed32NoTag(sfixed32SPacked_.get(i)); - } - if (getSfixed64SPackedList().size() > 0) { - output.writeUInt32NoTag(634); - output.writeUInt32NoTag(sfixed64SPackedMemoizedSerializedSize); - } - for (int i = 0; i < sfixed64SPacked_.size(); i++) { - output.writeSFixed64NoTag(sfixed64SPacked_.get(i)); - } - if (getFloatsPackedList().size() > 0) { - output.writeUInt32NoTag(642); - output.writeUInt32NoTag(floatsPackedMemoizedSerializedSize); - } - for (int i = 0; i < floatsPacked_.size(); i++) { - output.writeFloatNoTag(floatsPacked_.get(i)); - } - if (getDoublesPackedList().size() > 0) { - output.writeUInt32NoTag(650); - output.writeUInt32NoTag(doublesPackedMemoizedSerializedSize); - } - for (int i = 0; i < doublesPacked_.size(); i++) { - output.writeDoubleNoTag(doublesPacked_.get(i)); - } - if (getBoolsPackedList().size() > 0) { - output.writeUInt32NoTag(658); - output.writeUInt32NoTag(boolsPackedMemoizedSerializedSize); - } - for (int i = 0; i < boolsPacked_.size(); i++) { - output.writeBoolNoTag(boolsPacked_.get(i)); - } - if (getColorsPackedList().size() > 0) { - output.writeUInt32NoTag(666); - output.writeUInt32NoTag(colorsPackedMemoizedSerializedSize); - } - for (int i = 0; i < colorsPacked_.size(); i++) { - output.writeEnumNoTag(colorsPacked_.get(i)); - } - for (int i = 0; i < int32SNotPacked_.size(); i++) { - output.writeInt32(90, int32SNotPacked_.get(i)); - } - for (int i = 0; i < int64SNotPacked_.size(); i++) { - output.writeInt64(91, int64SNotPacked_.get(i)); - } - for (int i = 0; i < uint32SNotPacked_.size(); i++) { - output.writeUInt32(92, uint32SNotPacked_.get(i)); - } - for (int i = 0; i < uint64SNotPacked_.size(); i++) { - output.writeUInt64(93, uint64SNotPacked_.get(i)); - } - for (int i = 0; i < sint32SNotPacked_.size(); i++) { - output.writeSInt32(94, sint32SNotPacked_.get(i)); - } - for (int i = 0; i < sint64SNotPacked_.size(); i++) { - output.writeSInt64(95, sint64SNotPacked_.get(i)); - } - for (int i = 0; i < fixed32SNotPacked_.size(); i++) { - output.writeFixed32(96, fixed32SNotPacked_.get(i)); - } - for (int i = 0; i < fixed64SNotPacked_.size(); i++) { - output.writeFixed64(97, fixed64SNotPacked_.get(i)); - } - for (int i = 0; i < sfixed32SNotPacked_.size(); i++) { - output.writeSFixed32(98, sfixed32SNotPacked_.get(i)); - } - for (int i = 0; i < sfixed64SNotPacked_.size(); i++) { - output.writeSFixed64(99, sfixed64SNotPacked_.get(i)); - } - for (int i = 0; i < floatsNotPacked_.size(); i++) { - output.writeFloat(100, floatsNotPacked_.get(i)); - } - for (int i = 0; i < doublesNotPacked_.size(); i++) { - output.writeDouble(101, doublesNotPacked_.get(i)); - } - for (int i = 0; i < boolsNotPacked_.size(); i++) { - output.writeBool(102, boolsNotPacked_.get(i)); - } - for (int i = 0; i < colorsNotPacked_.size(); i++) { - output.writeEnum(103, colorsNotPacked_.get(i)); - } - for (int i = 0; i < strings_.size(); i++) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 110, strings_.getRaw(i)); - } - for (int i = 0; i < bytess_.size(); i++) { - output.writeBytes(111, bytess_.get(i)); - } - for (int i = 0; i < users_.size(); i++) { - output.writeMessage(112, users_.get(i)); - } - unknownFields.writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (int32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(1, int32_); - } - if (int64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(2, int64_); - } - if (uint32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(3, uint32_); - } - if (uint64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(4, uint64_); - } - if (sint32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeSInt32Size(5, sint32_); - } - if (sint64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeSInt64Size(6, sint64_); - } - if (fixed32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeFixed32Size(7, fixed32_); - } - if (fixed64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeFixed64Size(8, fixed64_); - } - if (sfixed32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeSFixed32Size(9, sfixed32_); - } - if (sfixed64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeSFixed64Size(10, sfixed64_); - } - if (floatValue_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(11, floatValue_); - } - if (doubleValue_ != 0D) { - size += com.google.protobuf.CodedOutputStream - .computeDoubleSize(12, doubleValue_); - } - if (bool_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(13, bool_); - } - if (objInt32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeInt32Size(20, objInt32_); - } - if (objInt64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeInt64Size(21, objInt64_); - } - if (objUint32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeUInt32Size(22, objUint32_); - } - if (objUint64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeUInt64Size(23, objUint64_); - } - if (objSint32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeSInt32Size(24, objSint32_); - } - if (objSint64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeSInt64Size(25, objSint64_); - } - if (objFixed32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeFixed32Size(26, objFixed32_); - } - if (objFixed64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeFixed64Size(27, objFixed64_); - } - if (objSfixed32_ != 0) { - size += com.google.protobuf.CodedOutputStream - .computeSFixed32Size(28, objSfixed32_); - } - if (objSfixed64_ != 0L) { - size += com.google.protobuf.CodedOutputStream - .computeSFixed64Size(29, objSfixed64_); - } - if (objFloatValue_ != 0F) { - size += com.google.protobuf.CodedOutputStream - .computeFloatSize(30, objFloatValue_); - } - if (objDoubleValue_ != 0D) { - size += com.google.protobuf.CodedOutputStream - .computeDoubleSize(31, objDoubleValue_); - } - if (objBool_ != false) { - size += com.google.protobuf.CodedOutputStream - .computeBoolSize(32, objBool_); - } - if (!getStringBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(40, string_); - } - if (!bytes_.isEmpty()) { - size += com.google.protobuf.CodedOutputStream - .computeBytesSize(41, bytes_); - } - if (color_ != org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.RED.getNumber()) { - size += com.google.protobuf.CodedOutputStream - .computeEnumSize(42, color_); - } - if (user_ != null) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(43, getUser()); - } - if (typeRecursive_ != null) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(44, getTypeRecursive()); - } - if (any_ != null) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(50, getAny()); - } - for (int i = 0; i < anys_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(51, anys_.get(i)); - } - for (java.util.Map.Entry entry - : internalGetSsMap().getMap().entrySet()) { - com.google.protobuf.MapEntry - ssMap__ = SsMapDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(60, ssMap__); - } - for (java.util.Map.Entry entry - : internalGetSint32Map().getMap().entrySet()) { - com.google.protobuf.MapEntry - sint32Map__ = Sint32MapDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(61, sint32Map__); - } - for (java.util.Map.Entry entry - : internalGetSpMap().getMap().entrySet()) { - com.google.protobuf.MapEntry - spMap__ = SpMapDefaultEntryHolder.defaultEntry.newBuilderForType() - .setKey(entry.getKey()) - .setValue(entry.getValue()) - .build(); - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(62, spMap__); - } - { - int dataSize = 0; - for (int i = 0; i < int32SPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(int32SPacked_.get(i)); - } - size += dataSize; - if (!getInt32SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - int32SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < int64SPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeInt64SizeNoTag(int64SPacked_.get(i)); - } - size += dataSize; - if (!getInt64SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - int64SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < uint32SPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeUInt32SizeNoTag(uint32SPacked_.get(i)); - } - size += dataSize; - if (!getUint32SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - uint32SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < uint64SPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeUInt64SizeNoTag(uint64SPacked_.get(i)); - } - size += dataSize; - if (!getUint64SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - uint64SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < sint32SPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeSInt32SizeNoTag(sint32SPacked_.get(i)); - } - size += dataSize; - if (!getSint32SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - sint32SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < sint64SPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeSInt64SizeNoTag(sint64SPacked_.get(i)); - } - size += dataSize; - if (!getSint64SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - sint64SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 4 * getFixed32SPackedList().size(); - size += dataSize; - if (!getFixed32SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - fixed32SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 8 * getFixed64SPackedList().size(); - size += dataSize; - if (!getFixed64SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - fixed64SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 4 * getSfixed32SPackedList().size(); - size += dataSize; - if (!getSfixed32SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - sfixed32SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 8 * getSfixed64SPackedList().size(); - size += dataSize; - if (!getSfixed64SPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - sfixed64SPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 4 * getFloatsPackedList().size(); - size += dataSize; - if (!getFloatsPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - floatsPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 8 * getDoublesPackedList().size(); - size += dataSize; - if (!getDoublesPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - doublesPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - dataSize = 1 * getBoolsPackedList().size(); - size += dataSize; - if (!getBoolsPackedList().isEmpty()) { - size += 2; - size += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(dataSize); - } - boolsPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < colorsPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeEnumSizeNoTag(colorsPacked_.get(i)); - } - size += dataSize; - if (!getColorsPackedList().isEmpty()) { size += 2; - size += com.google.protobuf.CodedOutputStream - .computeUInt32SizeNoTag(dataSize); - }colorsPackedMemoizedSerializedSize = dataSize; - } - { - int dataSize = 0; - for (int i = 0; i < int32SNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeInt32SizeNoTag(int32SNotPacked_.get(i)); - } - size += dataSize; - size += 2 * getInt32SNotPackedList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < int64SNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeInt64SizeNoTag(int64SNotPacked_.get(i)); - } - size += dataSize; - size += 2 * getInt64SNotPackedList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < uint32SNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeUInt32SizeNoTag(uint32SNotPacked_.get(i)); - } - size += dataSize; - size += 2 * getUint32SNotPackedList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < uint64SNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeUInt64SizeNoTag(uint64SNotPacked_.get(i)); - } - size += dataSize; - size += 2 * getUint64SNotPackedList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < sint32SNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeSInt32SizeNoTag(sint32SNotPacked_.get(i)); - } - size += dataSize; - size += 2 * getSint32SNotPackedList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < sint64SNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeSInt64SizeNoTag(sint64SNotPacked_.get(i)); - } - size += dataSize; - size += 2 * getSint64SNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 4 * getFixed32SNotPackedList().size(); - size += dataSize; - size += 2 * getFixed32SNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 8 * getFixed64SNotPackedList().size(); - size += dataSize; - size += 2 * getFixed64SNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 4 * getSfixed32SNotPackedList().size(); - size += dataSize; - size += 2 * getSfixed32SNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 8 * getSfixed64SNotPackedList().size(); - size += dataSize; - size += 2 * getSfixed64SNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 4 * getFloatsNotPackedList().size(); - size += dataSize; - size += 2 * getFloatsNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 8 * getDoublesNotPackedList().size(); - size += dataSize; - size += 2 * getDoublesNotPackedList().size(); - } - { - int dataSize = 0; - dataSize = 1 * getBoolsNotPackedList().size(); - size += dataSize; - size += 2 * getBoolsNotPackedList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < colorsNotPacked_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeEnumSizeNoTag(colorsNotPacked_.get(i)); - } - size += dataSize; - size += 2 * colorsNotPacked_.size(); - } - { - int dataSize = 0; - for (int i = 0; i < strings_.size(); i++) { - dataSize += computeStringSizeNoTag(strings_.getRaw(i)); - } - size += dataSize; - size += 2 * getStringsList().size(); - } - { - int dataSize = 0; - for (int i = 0; i < bytess_.size(); i++) { - dataSize += com.google.protobuf.CodedOutputStream - .computeBytesSizeNoTag(bytess_.get(i)); - } - size += dataSize; - size += 2 * getBytessList().size(); - } - for (int i = 0; i < users_.size(); i++) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(112, users_.get(i)); - } - size += unknownFields.getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root)) { - return super.equals(obj); - } - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root other = (org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root) obj; - - boolean result = true; - result = result && (getInt32() - == other.getInt32()); - result = result && (getInt64() - == other.getInt64()); - result = result && (getUint32() - == other.getUint32()); - result = result && (getUint64() - == other.getUint64()); - result = result && (getSint32() - == other.getSint32()); - result = result && (getSint64() - == other.getSint64()); - result = result && (getFixed32() - == other.getFixed32()); - result = result && (getFixed64() - == other.getFixed64()); - result = result && (getSfixed32() - == other.getSfixed32()); - result = result && (getSfixed64() - == other.getSfixed64()); - result = result && ( - java.lang.Float.floatToIntBits(getFloatValue()) - == java.lang.Float.floatToIntBits( - other.getFloatValue())); - result = result && ( - java.lang.Double.doubleToLongBits(getDoubleValue()) - == java.lang.Double.doubleToLongBits( - other.getDoubleValue())); - result = result && (getBool() - == other.getBool()); - result = result && (getObjInt32() - == other.getObjInt32()); - result = result && (getObjInt64() - == other.getObjInt64()); - result = result && (getObjUint32() - == other.getObjUint32()); - result = result && (getObjUint64() - == other.getObjUint64()); - result = result && (getObjSint32() - == other.getObjSint32()); - result = result && (getObjSint64() - == other.getObjSint64()); - result = result && (getObjFixed32() - == other.getObjFixed32()); - result = result && (getObjFixed64() - == other.getObjFixed64()); - result = result && (getObjSfixed32() - == other.getObjSfixed32()); - result = result && (getObjSfixed64() - == other.getObjSfixed64()); - result = result && ( - java.lang.Float.floatToIntBits(getObjFloatValue()) - == java.lang.Float.floatToIntBits( - other.getObjFloatValue())); - result = result && ( - java.lang.Double.doubleToLongBits(getObjDoubleValue()) - == java.lang.Double.doubleToLongBits( - other.getObjDoubleValue())); - result = result && (getObjBool() - == other.getObjBool()); - result = result && getString() - .equals(other.getString()); - result = result && getBytes() - .equals(other.getBytes()); - result = result && color_ == other.color_; - result = result && (hasUser() == other.hasUser()); - if (hasUser()) { - result = result && getUser() - .equals(other.getUser()); - } - result = result && (hasTypeRecursive() == other.hasTypeRecursive()); - if (hasTypeRecursive()) { - result = result && getTypeRecursive() - .equals(other.getTypeRecursive()); - } - result = result && (hasAny() == other.hasAny()); - if (hasAny()) { - result = result && getAny() - .equals(other.getAny()); - } - result = result && getAnysList() - .equals(other.getAnysList()); - result = result && internalGetSsMap().equals( - other.internalGetSsMap()); - result = result && internalGetSint32Map().equals( - other.internalGetSint32Map()); - result = result && internalGetSpMap().equals( - other.internalGetSpMap()); - result = result && getInt32SPackedList() - .equals(other.getInt32SPackedList()); - result = result && getInt64SPackedList() - .equals(other.getInt64SPackedList()); - result = result && getUint32SPackedList() - .equals(other.getUint32SPackedList()); - result = result && getUint64SPackedList() - .equals(other.getUint64SPackedList()); - result = result && getSint32SPackedList() - .equals(other.getSint32SPackedList()); - result = result && getSint64SPackedList() - .equals(other.getSint64SPackedList()); - result = result && getFixed32SPackedList() - .equals(other.getFixed32SPackedList()); - result = result && getFixed64SPackedList() - .equals(other.getFixed64SPackedList()); - result = result && getSfixed32SPackedList() - .equals(other.getSfixed32SPackedList()); - result = result && getSfixed64SPackedList() - .equals(other.getSfixed64SPackedList()); - result = result && getFloatsPackedList() - .equals(other.getFloatsPackedList()); - result = result && getDoublesPackedList() - .equals(other.getDoublesPackedList()); - result = result && getBoolsPackedList() - .equals(other.getBoolsPackedList()); - result = result && colorsPacked_.equals(other.colorsPacked_); - result = result && getInt32SNotPackedList() - .equals(other.getInt32SNotPackedList()); - result = result && getInt64SNotPackedList() - .equals(other.getInt64SNotPackedList()); - result = result && getUint32SNotPackedList() - .equals(other.getUint32SNotPackedList()); - result = result && getUint64SNotPackedList() - .equals(other.getUint64SNotPackedList()); - result = result && getSint32SNotPackedList() - .equals(other.getSint32SNotPackedList()); - result = result && getSint64SNotPackedList() - .equals(other.getSint64SNotPackedList()); - result = result && getFixed32SNotPackedList() - .equals(other.getFixed32SNotPackedList()); - result = result && getFixed64SNotPackedList() - .equals(other.getFixed64SNotPackedList()); - result = result && getSfixed32SNotPackedList() - .equals(other.getSfixed32SNotPackedList()); - result = result && getSfixed64SNotPackedList() - .equals(other.getSfixed64SNotPackedList()); - result = result && getFloatsNotPackedList() - .equals(other.getFloatsNotPackedList()); - result = result && getDoublesNotPackedList() - .equals(other.getDoublesNotPackedList()); - result = result && getBoolsNotPackedList() - .equals(other.getBoolsNotPackedList()); - result = result && colorsNotPacked_.equals(other.colorsNotPacked_); - result = result && getStringsList() - .equals(other.getStringsList()); - result = result && getBytessList() - .equals(other.getBytessList()); - result = result && getUsersList() - .equals(other.getUsersList()); - result = result && unknownFields.equals(other.unknownFields); - return result; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + INT32_FIELD_NUMBER; - hash = (53 * hash) + getInt32(); - hash = (37 * hash) + INT64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getInt64()); - hash = (37 * hash) + UINT32_FIELD_NUMBER; - hash = (53 * hash) + getUint32(); - hash = (37 * hash) + UINT64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getUint64()); - hash = (37 * hash) + SINT32_FIELD_NUMBER; - hash = (53 * hash) + getSint32(); - hash = (37 * hash) + SINT64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getSint64()); - hash = (37 * hash) + FIXED32_FIELD_NUMBER; - hash = (53 * hash) + getFixed32(); - hash = (37 * hash) + FIXED64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getFixed64()); - hash = (37 * hash) + SFIXED32_FIELD_NUMBER; - hash = (53 * hash) + getSfixed32(); - hash = (37 * hash) + SFIXED64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getSfixed64()); - hash = (37 * hash) + FLOATVALUE_FIELD_NUMBER; - hash = (53 * hash) + java.lang.Float.floatToIntBits( - getFloatValue()); - hash = (37 * hash) + DOUBLEVALUE_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - java.lang.Double.doubleToLongBits(getDoubleValue())); - hash = (37 * hash) + BOOL_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getBool()); - hash = (37 * hash) + OBJINT32_FIELD_NUMBER; - hash = (53 * hash) + getObjInt32(); - hash = (37 * hash) + OBJINT64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getObjInt64()); - hash = (37 * hash) + OBJUINT32_FIELD_NUMBER; - hash = (53 * hash) + getObjUint32(); - hash = (37 * hash) + OBJUINT64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getObjUint64()); - hash = (37 * hash) + OBJSINT32_FIELD_NUMBER; - hash = (53 * hash) + getObjSint32(); - hash = (37 * hash) + OBJSINT64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getObjSint64()); - hash = (37 * hash) + OBJFIXED32_FIELD_NUMBER; - hash = (53 * hash) + getObjFixed32(); - hash = (37 * hash) + OBJFIXED64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getObjFixed64()); - hash = (37 * hash) + OBJSFIXED32_FIELD_NUMBER; - hash = (53 * hash) + getObjSfixed32(); - hash = (37 * hash) + OBJSFIXED64_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - getObjSfixed64()); - hash = (37 * hash) + OBJFLOATVALUE_FIELD_NUMBER; - hash = (53 * hash) + java.lang.Float.floatToIntBits( - getObjFloatValue()); - hash = (37 * hash) + OBJDOUBLEVALUE_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashLong( - java.lang.Double.doubleToLongBits(getObjDoubleValue())); - hash = (37 * hash) + OBJBOOL_FIELD_NUMBER; - hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean( - getObjBool()); - hash = (37 * hash) + STRING_FIELD_NUMBER; - hash = (53 * hash) + getString().hashCode(); - hash = (37 * hash) + BYTES_FIELD_NUMBER; - hash = (53 * hash) + getBytes().hashCode(); - hash = (37 * hash) + COLOR_FIELD_NUMBER; - hash = (53 * hash) + color_; - if (hasUser()) { - hash = (37 * hash) + USER_FIELD_NUMBER; - hash = (53 * hash) + getUser().hashCode(); - } - if (hasTypeRecursive()) { - hash = (37 * hash) + TYPERECURSIVE_FIELD_NUMBER; - hash = (53 * hash) + getTypeRecursive().hashCode(); - } - if (hasAny()) { - hash = (37 * hash) + ANY_FIELD_NUMBER; - hash = (53 * hash) + getAny().hashCode(); - } - if (getAnysCount() > 0) { - hash = (37 * hash) + ANYS_FIELD_NUMBER; - hash = (53 * hash) + getAnysList().hashCode(); - } - if (!internalGetSsMap().getMap().isEmpty()) { - hash = (37 * hash) + SSMAP_FIELD_NUMBER; - hash = (53 * hash) + internalGetSsMap().hashCode(); - } - if (!internalGetSint32Map().getMap().isEmpty()) { - hash = (37 * hash) + SINT32MAP_FIELD_NUMBER; - hash = (53 * hash) + internalGetSint32Map().hashCode(); - } - if (!internalGetSpMap().getMap().isEmpty()) { - hash = (37 * hash) + SPMAP_FIELD_NUMBER; - hash = (53 * hash) + internalGetSpMap().hashCode(); - } - if (getInt32SPackedCount() > 0) { - hash = (37 * hash) + INT32SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getInt32SPackedList().hashCode(); - } - if (getInt64SPackedCount() > 0) { - hash = (37 * hash) + INT64SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getInt64SPackedList().hashCode(); - } - if (getUint32SPackedCount() > 0) { - hash = (37 * hash) + UINT32SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getUint32SPackedList().hashCode(); - } - if (getUint64SPackedCount() > 0) { - hash = (37 * hash) + UINT64SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getUint64SPackedList().hashCode(); - } - if (getSint32SPackedCount() > 0) { - hash = (37 * hash) + SINT32SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSint32SPackedList().hashCode(); - } - if (getSint64SPackedCount() > 0) { - hash = (37 * hash) + SINT64SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSint64SPackedList().hashCode(); - } - if (getFixed32SPackedCount() > 0) { - hash = (37 * hash) + FIXED32SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getFixed32SPackedList().hashCode(); - } - if (getFixed64SPackedCount() > 0) { - hash = (37 * hash) + FIXED64SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getFixed64SPackedList().hashCode(); - } - if (getSfixed32SPackedCount() > 0) { - hash = (37 * hash) + SFIXED32SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSfixed32SPackedList().hashCode(); - } - if (getSfixed64SPackedCount() > 0) { - hash = (37 * hash) + SFIXED64SPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSfixed64SPackedList().hashCode(); - } - if (getFloatsPackedCount() > 0) { - hash = (37 * hash) + FLOATSPACKED_FIELD_NUMBER; - hash = (53 * hash) + getFloatsPackedList().hashCode(); - } - if (getDoublesPackedCount() > 0) { - hash = (37 * hash) + DOUBLESPACKED_FIELD_NUMBER; - hash = (53 * hash) + getDoublesPackedList().hashCode(); - } - if (getBoolsPackedCount() > 0) { - hash = (37 * hash) + BOOLSPACKED_FIELD_NUMBER; - hash = (53 * hash) + getBoolsPackedList().hashCode(); - } - if (getColorsPackedCount() > 0) { - hash = (37 * hash) + COLORSPACKED_FIELD_NUMBER; - hash = (53 * hash) + colorsPacked_.hashCode(); - } - if (getInt32SNotPackedCount() > 0) { - hash = (37 * hash) + INT32SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getInt32SNotPackedList().hashCode(); - } - if (getInt64SNotPackedCount() > 0) { - hash = (37 * hash) + INT64SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getInt64SNotPackedList().hashCode(); - } - if (getUint32SNotPackedCount() > 0) { - hash = (37 * hash) + UINT32SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getUint32SNotPackedList().hashCode(); - } - if (getUint64SNotPackedCount() > 0) { - hash = (37 * hash) + UINT64SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getUint64SNotPackedList().hashCode(); - } - if (getSint32SNotPackedCount() > 0) { - hash = (37 * hash) + SINT32SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSint32SNotPackedList().hashCode(); - } - if (getSint64SNotPackedCount() > 0) { - hash = (37 * hash) + SINT64SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSint64SNotPackedList().hashCode(); - } - if (getFixed32SNotPackedCount() > 0) { - hash = (37 * hash) + FIXED32SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getFixed32SNotPackedList().hashCode(); - } - if (getFixed64SNotPackedCount() > 0) { - hash = (37 * hash) + FIXED64SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getFixed64SNotPackedList().hashCode(); - } - if (getSfixed32SNotPackedCount() > 0) { - hash = (37 * hash) + SFIXED32SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSfixed32SNotPackedList().hashCode(); - } - if (getSfixed64SNotPackedCount() > 0) { - hash = (37 * hash) + SFIXED64SNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getSfixed64SNotPackedList().hashCode(); - } - if (getFloatsNotPackedCount() > 0) { - hash = (37 * hash) + FLOATSNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getFloatsNotPackedList().hashCode(); - } - if (getDoublesNotPackedCount() > 0) { - hash = (37 * hash) + DOUBLESNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getDoublesNotPackedList().hashCode(); - } - if (getBoolsNotPackedCount() > 0) { - hash = (37 * hash) + BOOLSNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + getBoolsNotPackedList().hashCode(); - } - if (getColorsNotPackedCount() > 0) { - hash = (37 * hash) + COLORSNOTPACKED_FIELD_NUMBER; - hash = (53 * hash) + colorsNotPacked_.hashCode(); - } - if (getStringsCount() > 0) { - hash = (37 * hash) + STRINGS_FIELD_NUMBER; - hash = (53 * hash) + getStringsList().hashCode(); - } - if (getBytessCount() > 0) { - hash = (37 * hash) + BYTESS_FIELD_NUMBER; - hash = (53 * hash) + getBytessList().hashCode(); - } - if (getUsersCount() > 0) { - hash = (37 * hash) + USERS_FIELD_NUMBER; - hash = (53 * hash) + getUsersList().hashCode(); - } - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code org.apache.servicecomb.foundation.protobuf.internal.model.Root} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:org.apache.servicecomb.foundation.protobuf.internal.model.Root) - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor; - } - - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMapField( - int number) { - switch (number) { - case 60: - return internalGetSsMap(); - case 61: - return internalGetSint32Map(); - case 62: - return internalGetSpMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @SuppressWarnings({"rawtypes"}) - protected com.google.protobuf.MapField internalGetMutableMapField( - int number) { - switch (number) { - case 60: - return internalGetMutableSsMap(); - case 61: - return internalGetMutableSint32Map(); - case 62: - return internalGetMutableSpMap(); - default: - throw new RuntimeException( - "Invalid map field number: " + number); - } - } - @java.lang.Override - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.class, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder.class); - } - - // Construct using org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - getAnysFieldBuilder(); - getUsersFieldBuilder(); - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - int32_ = 0; - - int64_ = 0L; - - uint32_ = 0; - - uint64_ = 0L; - - sint32_ = 0; - - sint64_ = 0L; - - fixed32_ = 0; - - fixed64_ = 0L; - - sfixed32_ = 0; - - sfixed64_ = 0L; - - floatValue_ = 0F; - - doubleValue_ = 0D; - - bool_ = false; - - objInt32_ = 0; - - objInt64_ = 0L; - - objUint32_ = 0; - - objUint64_ = 0L; - - objSint32_ = 0; - - objSint64_ = 0L; - - objFixed32_ = 0; - - objFixed64_ = 0L; - - objSfixed32_ = 0; - - objSfixed64_ = 0L; - - objFloatValue_ = 0F; - - objDoubleValue_ = 0D; - - objBool_ = false; - - string_ = ""; - - bytes_ = com.google.protobuf.ByteString.EMPTY; - - color_ = 0; - - if (userBuilder_ == null) { - user_ = null; - } else { - user_ = null; - userBuilder_ = null; - } - if (typeRecursiveBuilder_ == null) { - typeRecursive_ = null; - } else { - typeRecursive_ = null; - typeRecursiveBuilder_ = null; - } - if (anyBuilder_ == null) { - any_ = null; - } else { - any_ = null; - anyBuilder_ = null; - } - if (anysBuilder_ == null) { - anys_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000001); - } else { - anysBuilder_.clear(); - } - internalGetMutableSsMap().clear(); - internalGetMutableSint32Map().clear(); - internalGetMutableSpMap().clear(); - int32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000010); - int64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000020); - uint32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000040); - uint64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000080); - sint32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000100); - sint64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000200); - fixed32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000400); - fixed64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000800); - sfixed32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00001000); - sfixed64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00002000); - floatsPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00004000); - doublesPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00008000); - boolsPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00010000); - colorsPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00020000); - int32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00040000); - int64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00080000); - uint32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00100000); - uint64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00200000); - sint32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00400000); - sint64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00800000); - fixed32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x01000000); - fixed64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x02000000); - sfixed32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x04000000); - sfixed64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x08000000); - floatsNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x10000000); - doublesNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x20000000); - boolsNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x40000000); - colorsNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x80000000); - strings_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bitField2_ = (bitField2_ & ~0x00000001); - bytess_ = java.util.Collections.emptyList(); - bitField2_ = (bitField2_ & ~0x00000002); - if (usersBuilder_ == null) { - users_ = java.util.Collections.emptyList(); - bitField2_ = (bitField2_ & ~0x00000004); - } else { - usersBuilder_.clear(); - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor; - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getDefaultInstanceForType() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance(); - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root build() { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root buildPartial() { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root result = new org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root(this); - int from_bitField0_ = bitField0_; - int from_bitField1_ = bitField1_; - int from_bitField2_ = bitField2_; - int to_bitField0_ = 0; - result.int32_ = int32_; - result.int64_ = int64_; - result.uint32_ = uint32_; - result.uint64_ = uint64_; - result.sint32_ = sint32_; - result.sint64_ = sint64_; - result.fixed32_ = fixed32_; - result.fixed64_ = fixed64_; - result.sfixed32_ = sfixed32_; - result.sfixed64_ = sfixed64_; - result.floatValue_ = floatValue_; - result.doubleValue_ = doubleValue_; - result.bool_ = bool_; - result.objInt32_ = objInt32_; - result.objInt64_ = objInt64_; - result.objUint32_ = objUint32_; - result.objUint64_ = objUint64_; - result.objSint32_ = objSint32_; - result.objSint64_ = objSint64_; - result.objFixed32_ = objFixed32_; - result.objFixed64_ = objFixed64_; - result.objSfixed32_ = objSfixed32_; - result.objSfixed64_ = objSfixed64_; - result.objFloatValue_ = objFloatValue_; - result.objDoubleValue_ = objDoubleValue_; - result.objBool_ = objBool_; - result.string_ = string_; - result.bytes_ = bytes_; - result.color_ = color_; - if (userBuilder_ == null) { - result.user_ = user_; - } else { - result.user_ = userBuilder_.build(); - } - if (typeRecursiveBuilder_ == null) { - result.typeRecursive_ = typeRecursive_; - } else { - result.typeRecursive_ = typeRecursiveBuilder_.build(); - } - if (anyBuilder_ == null) { - result.any_ = any_; - } else { - result.any_ = anyBuilder_.build(); - } - if (anysBuilder_ == null) { - if (((bitField1_ & 0x00000001) == 0x00000001)) { - anys_ = java.util.Collections.unmodifiableList(anys_); - bitField1_ = (bitField1_ & ~0x00000001); - } - result.anys_ = anys_; - } else { - result.anys_ = anysBuilder_.build(); - } - result.ssMap_ = internalGetSsMap(); - result.ssMap_.makeImmutable(); - result.sint32Map_ = internalGetSint32Map(); - result.sint32Map_.makeImmutable(); - result.spMap_ = internalGetSpMap(); - result.spMap_.makeImmutable(); - if (((bitField1_ & 0x00000010) == 0x00000010)) { - int32SPacked_ = java.util.Collections.unmodifiableList(int32SPacked_); - bitField1_ = (bitField1_ & ~0x00000010); - } - result.int32SPacked_ = int32SPacked_; - if (((bitField1_ & 0x00000020) == 0x00000020)) { - int64SPacked_ = java.util.Collections.unmodifiableList(int64SPacked_); - bitField1_ = (bitField1_ & ~0x00000020); - } - result.int64SPacked_ = int64SPacked_; - if (((bitField1_ & 0x00000040) == 0x00000040)) { - uint32SPacked_ = java.util.Collections.unmodifiableList(uint32SPacked_); - bitField1_ = (bitField1_ & ~0x00000040); - } - result.uint32SPacked_ = uint32SPacked_; - if (((bitField1_ & 0x00000080) == 0x00000080)) { - uint64SPacked_ = java.util.Collections.unmodifiableList(uint64SPacked_); - bitField1_ = (bitField1_ & ~0x00000080); - } - result.uint64SPacked_ = uint64SPacked_; - if (((bitField1_ & 0x00000100) == 0x00000100)) { - sint32SPacked_ = java.util.Collections.unmodifiableList(sint32SPacked_); - bitField1_ = (bitField1_ & ~0x00000100); - } - result.sint32SPacked_ = sint32SPacked_; - if (((bitField1_ & 0x00000200) == 0x00000200)) { - sint64SPacked_ = java.util.Collections.unmodifiableList(sint64SPacked_); - bitField1_ = (bitField1_ & ~0x00000200); - } - result.sint64SPacked_ = sint64SPacked_; - if (((bitField1_ & 0x00000400) == 0x00000400)) { - fixed32SPacked_ = java.util.Collections.unmodifiableList(fixed32SPacked_); - bitField1_ = (bitField1_ & ~0x00000400); - } - result.fixed32SPacked_ = fixed32SPacked_; - if (((bitField1_ & 0x00000800) == 0x00000800)) { - fixed64SPacked_ = java.util.Collections.unmodifiableList(fixed64SPacked_); - bitField1_ = (bitField1_ & ~0x00000800); - } - result.fixed64SPacked_ = fixed64SPacked_; - if (((bitField1_ & 0x00001000) == 0x00001000)) { - sfixed32SPacked_ = java.util.Collections.unmodifiableList(sfixed32SPacked_); - bitField1_ = (bitField1_ & ~0x00001000); - } - result.sfixed32SPacked_ = sfixed32SPacked_; - if (((bitField1_ & 0x00002000) == 0x00002000)) { - sfixed64SPacked_ = java.util.Collections.unmodifiableList(sfixed64SPacked_); - bitField1_ = (bitField1_ & ~0x00002000); - } - result.sfixed64SPacked_ = sfixed64SPacked_; - if (((bitField1_ & 0x00004000) == 0x00004000)) { - floatsPacked_ = java.util.Collections.unmodifiableList(floatsPacked_); - bitField1_ = (bitField1_ & ~0x00004000); - } - result.floatsPacked_ = floatsPacked_; - if (((bitField1_ & 0x00008000) == 0x00008000)) { - doublesPacked_ = java.util.Collections.unmodifiableList(doublesPacked_); - bitField1_ = (bitField1_ & ~0x00008000); - } - result.doublesPacked_ = doublesPacked_; - if (((bitField1_ & 0x00010000) == 0x00010000)) { - boolsPacked_ = java.util.Collections.unmodifiableList(boolsPacked_); - bitField1_ = (bitField1_ & ~0x00010000); - } - result.boolsPacked_ = boolsPacked_; - if (((bitField1_ & 0x00020000) == 0x00020000)) { - colorsPacked_ = java.util.Collections.unmodifiableList(colorsPacked_); - bitField1_ = (bitField1_ & ~0x00020000); - } - result.colorsPacked_ = colorsPacked_; - if (((bitField1_ & 0x00040000) == 0x00040000)) { - int32SNotPacked_ = java.util.Collections.unmodifiableList(int32SNotPacked_); - bitField1_ = (bitField1_ & ~0x00040000); - } - result.int32SNotPacked_ = int32SNotPacked_; - if (((bitField1_ & 0x00080000) == 0x00080000)) { - int64SNotPacked_ = java.util.Collections.unmodifiableList(int64SNotPacked_); - bitField1_ = (bitField1_ & ~0x00080000); - } - result.int64SNotPacked_ = int64SNotPacked_; - if (((bitField1_ & 0x00100000) == 0x00100000)) { - uint32SNotPacked_ = java.util.Collections.unmodifiableList(uint32SNotPacked_); - bitField1_ = (bitField1_ & ~0x00100000); - } - result.uint32SNotPacked_ = uint32SNotPacked_; - if (((bitField1_ & 0x00200000) == 0x00200000)) { - uint64SNotPacked_ = java.util.Collections.unmodifiableList(uint64SNotPacked_); - bitField1_ = (bitField1_ & ~0x00200000); - } - result.uint64SNotPacked_ = uint64SNotPacked_; - if (((bitField1_ & 0x00400000) == 0x00400000)) { - sint32SNotPacked_ = java.util.Collections.unmodifiableList(sint32SNotPacked_); - bitField1_ = (bitField1_ & ~0x00400000); - } - result.sint32SNotPacked_ = sint32SNotPacked_; - if (((bitField1_ & 0x00800000) == 0x00800000)) { - sint64SNotPacked_ = java.util.Collections.unmodifiableList(sint64SNotPacked_); - bitField1_ = (bitField1_ & ~0x00800000); - } - result.sint64SNotPacked_ = sint64SNotPacked_; - if (((bitField1_ & 0x01000000) == 0x01000000)) { - fixed32SNotPacked_ = java.util.Collections.unmodifiableList(fixed32SNotPacked_); - bitField1_ = (bitField1_ & ~0x01000000); - } - result.fixed32SNotPacked_ = fixed32SNotPacked_; - if (((bitField1_ & 0x02000000) == 0x02000000)) { - fixed64SNotPacked_ = java.util.Collections.unmodifiableList(fixed64SNotPacked_); - bitField1_ = (bitField1_ & ~0x02000000); - } - result.fixed64SNotPacked_ = fixed64SNotPacked_; - if (((bitField1_ & 0x04000000) == 0x04000000)) { - sfixed32SNotPacked_ = java.util.Collections.unmodifiableList(sfixed32SNotPacked_); - bitField1_ = (bitField1_ & ~0x04000000); - } - result.sfixed32SNotPacked_ = sfixed32SNotPacked_; - if (((bitField1_ & 0x08000000) == 0x08000000)) { - sfixed64SNotPacked_ = java.util.Collections.unmodifiableList(sfixed64SNotPacked_); - bitField1_ = (bitField1_ & ~0x08000000); - } - result.sfixed64SNotPacked_ = sfixed64SNotPacked_; - if (((bitField1_ & 0x10000000) == 0x10000000)) { - floatsNotPacked_ = java.util.Collections.unmodifiableList(floatsNotPacked_); - bitField1_ = (bitField1_ & ~0x10000000); - } - result.floatsNotPacked_ = floatsNotPacked_; - if (((bitField1_ & 0x20000000) == 0x20000000)) { - doublesNotPacked_ = java.util.Collections.unmodifiableList(doublesNotPacked_); - bitField1_ = (bitField1_ & ~0x20000000); - } - result.doublesNotPacked_ = doublesNotPacked_; - if (((bitField1_ & 0x40000000) == 0x40000000)) { - boolsNotPacked_ = java.util.Collections.unmodifiableList(boolsNotPacked_); - bitField1_ = (bitField1_ & ~0x40000000); - } - result.boolsNotPacked_ = boolsNotPacked_; - if (((bitField1_ & 0x80000000) == 0x80000000)) { - colorsNotPacked_ = java.util.Collections.unmodifiableList(colorsNotPacked_); - bitField1_ = (bitField1_ & ~0x80000000); - } - result.colorsNotPacked_ = colorsNotPacked_; - if (((bitField2_ & 0x00000001) == 0x00000001)) { - strings_ = strings_.getUnmodifiableView(); - bitField2_ = (bitField2_ & ~0x00000001); - } - result.strings_ = strings_; - if (((bitField2_ & 0x00000002) == 0x00000002)) { - bytess_ = java.util.Collections.unmodifiableList(bytess_); - bitField2_ = (bitField2_ & ~0x00000002); - } - result.bytess_ = bytess_; - if (usersBuilder_ == null) { - if (((bitField2_ & 0x00000004) == 0x00000004)) { - users_ = java.util.Collections.unmodifiableList(users_); - bitField2_ = (bitField2_ & ~0x00000004); - } - result.users_ = users_; - } else { - result.users_ = usersBuilder_.build(); - } - result.bitField0_ = to_bitField0_; - onBuilt(); - return result; - } - - @java.lang.Override - public Builder clone() { - return (Builder) super.clone(); - } - @java.lang.Override - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { - return (Builder) super.setField(field, value); - } - @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - @java.lang.Override - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - @java.lang.Override - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { - return (Builder) super.addRepeatedField(field, value); - } - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root) { - return mergeFrom((org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root other) { - if (other == org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance()) return this; - if (other.getInt32() != 0) { - setInt32(other.getInt32()); - } - if (other.getInt64() != 0L) { - setInt64(other.getInt64()); - } - if (other.getUint32() != 0) { - setUint32(other.getUint32()); - } - if (other.getUint64() != 0L) { - setUint64(other.getUint64()); - } - if (other.getSint32() != 0) { - setSint32(other.getSint32()); - } - if (other.getSint64() != 0L) { - setSint64(other.getSint64()); - } - if (other.getFixed32() != 0) { - setFixed32(other.getFixed32()); - } - if (other.getFixed64() != 0L) { - setFixed64(other.getFixed64()); - } - if (other.getSfixed32() != 0) { - setSfixed32(other.getSfixed32()); - } - if (other.getSfixed64() != 0L) { - setSfixed64(other.getSfixed64()); - } - if (other.getFloatValue() != 0F) { - setFloatValue(other.getFloatValue()); - } - if (other.getDoubleValue() != 0D) { - setDoubleValue(other.getDoubleValue()); - } - if (other.getBool() != false) { - setBool(other.getBool()); - } - if (other.getObjInt32() != 0) { - setObjInt32(other.getObjInt32()); - } - if (other.getObjInt64() != 0L) { - setObjInt64(other.getObjInt64()); - } - if (other.getObjUint32() != 0) { - setObjUint32(other.getObjUint32()); - } - if (other.getObjUint64() != 0L) { - setObjUint64(other.getObjUint64()); - } - if (other.getObjSint32() != 0) { - setObjSint32(other.getObjSint32()); - } - if (other.getObjSint64() != 0L) { - setObjSint64(other.getObjSint64()); - } - if (other.getObjFixed32() != 0) { - setObjFixed32(other.getObjFixed32()); - } - if (other.getObjFixed64() != 0L) { - setObjFixed64(other.getObjFixed64()); - } - if (other.getObjSfixed32() != 0) { - setObjSfixed32(other.getObjSfixed32()); - } - if (other.getObjSfixed64() != 0L) { - setObjSfixed64(other.getObjSfixed64()); - } - if (other.getObjFloatValue() != 0F) { - setObjFloatValue(other.getObjFloatValue()); - } - if (other.getObjDoubleValue() != 0D) { - setObjDoubleValue(other.getObjDoubleValue()); - } - if (other.getObjBool() != false) { - setObjBool(other.getObjBool()); - } - if (!other.getString().isEmpty()) { - string_ = other.string_; - onChanged(); - } - if (other.getBytes() != com.google.protobuf.ByteString.EMPTY) { - setBytes(other.getBytes()); - } - if (other.color_ != 0) { - setColorValue(other.getColorValue()); - } - if (other.hasUser()) { - mergeUser(other.getUser()); - } - if (other.hasTypeRecursive()) { - mergeTypeRecursive(other.getTypeRecursive()); - } - if (other.hasAny()) { - mergeAny(other.getAny()); - } - if (anysBuilder_ == null) { - if (!other.anys_.isEmpty()) { - if (anys_.isEmpty()) { - anys_ = other.anys_; - bitField1_ = (bitField1_ & ~0x00000001); - } else { - ensureAnysIsMutable(); - anys_.addAll(other.anys_); - } - onChanged(); - } - } else { - if (!other.anys_.isEmpty()) { - if (anysBuilder_.isEmpty()) { - anysBuilder_.dispose(); - anysBuilder_ = null; - anys_ = other.anys_; - bitField1_ = (bitField1_ & ~0x00000001); - anysBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getAnysFieldBuilder() : null; - } else { - anysBuilder_.addAllMessages(other.anys_); - } - } - } - internalGetMutableSsMap().mergeFrom( - other.internalGetSsMap()); - internalGetMutableSint32Map().mergeFrom( - other.internalGetSint32Map()); - internalGetMutableSpMap().mergeFrom( - other.internalGetSpMap()); - if (!other.int32SPacked_.isEmpty()) { - if (int32SPacked_.isEmpty()) { - int32SPacked_ = other.int32SPacked_; - bitField1_ = (bitField1_ & ~0x00000010); - } else { - ensureInt32SPackedIsMutable(); - int32SPacked_.addAll(other.int32SPacked_); - } - onChanged(); - } - if (!other.int64SPacked_.isEmpty()) { - if (int64SPacked_.isEmpty()) { - int64SPacked_ = other.int64SPacked_; - bitField1_ = (bitField1_ & ~0x00000020); - } else { - ensureInt64SPackedIsMutable(); - int64SPacked_.addAll(other.int64SPacked_); - } - onChanged(); - } - if (!other.uint32SPacked_.isEmpty()) { - if (uint32SPacked_.isEmpty()) { - uint32SPacked_ = other.uint32SPacked_; - bitField1_ = (bitField1_ & ~0x00000040); - } else { - ensureUint32SPackedIsMutable(); - uint32SPacked_.addAll(other.uint32SPacked_); - } - onChanged(); - } - if (!other.uint64SPacked_.isEmpty()) { - if (uint64SPacked_.isEmpty()) { - uint64SPacked_ = other.uint64SPacked_; - bitField1_ = (bitField1_ & ~0x00000080); - } else { - ensureUint64SPackedIsMutable(); - uint64SPacked_.addAll(other.uint64SPacked_); - } - onChanged(); - } - if (!other.sint32SPacked_.isEmpty()) { - if (sint32SPacked_.isEmpty()) { - sint32SPacked_ = other.sint32SPacked_; - bitField1_ = (bitField1_ & ~0x00000100); - } else { - ensureSint32SPackedIsMutable(); - sint32SPacked_.addAll(other.sint32SPacked_); - } - onChanged(); - } - if (!other.sint64SPacked_.isEmpty()) { - if (sint64SPacked_.isEmpty()) { - sint64SPacked_ = other.sint64SPacked_; - bitField1_ = (bitField1_ & ~0x00000200); - } else { - ensureSint64SPackedIsMutable(); - sint64SPacked_.addAll(other.sint64SPacked_); - } - onChanged(); - } - if (!other.fixed32SPacked_.isEmpty()) { - if (fixed32SPacked_.isEmpty()) { - fixed32SPacked_ = other.fixed32SPacked_; - bitField1_ = (bitField1_ & ~0x00000400); - } else { - ensureFixed32SPackedIsMutable(); - fixed32SPacked_.addAll(other.fixed32SPacked_); - } - onChanged(); - } - if (!other.fixed64SPacked_.isEmpty()) { - if (fixed64SPacked_.isEmpty()) { - fixed64SPacked_ = other.fixed64SPacked_; - bitField1_ = (bitField1_ & ~0x00000800); - } else { - ensureFixed64SPackedIsMutable(); - fixed64SPacked_.addAll(other.fixed64SPacked_); - } - onChanged(); - } - if (!other.sfixed32SPacked_.isEmpty()) { - if (sfixed32SPacked_.isEmpty()) { - sfixed32SPacked_ = other.sfixed32SPacked_; - bitField1_ = (bitField1_ & ~0x00001000); - } else { - ensureSfixed32SPackedIsMutable(); - sfixed32SPacked_.addAll(other.sfixed32SPacked_); - } - onChanged(); - } - if (!other.sfixed64SPacked_.isEmpty()) { - if (sfixed64SPacked_.isEmpty()) { - sfixed64SPacked_ = other.sfixed64SPacked_; - bitField1_ = (bitField1_ & ~0x00002000); - } else { - ensureSfixed64SPackedIsMutable(); - sfixed64SPacked_.addAll(other.sfixed64SPacked_); - } - onChanged(); - } - if (!other.floatsPacked_.isEmpty()) { - if (floatsPacked_.isEmpty()) { - floatsPacked_ = other.floatsPacked_; - bitField1_ = (bitField1_ & ~0x00004000); - } else { - ensureFloatsPackedIsMutable(); - floatsPacked_.addAll(other.floatsPacked_); - } - onChanged(); - } - if (!other.doublesPacked_.isEmpty()) { - if (doublesPacked_.isEmpty()) { - doublesPacked_ = other.doublesPacked_; - bitField1_ = (bitField1_ & ~0x00008000); - } else { - ensureDoublesPackedIsMutable(); - doublesPacked_.addAll(other.doublesPacked_); - } - onChanged(); - } - if (!other.boolsPacked_.isEmpty()) { - if (boolsPacked_.isEmpty()) { - boolsPacked_ = other.boolsPacked_; - bitField1_ = (bitField1_ & ~0x00010000); - } else { - ensureBoolsPackedIsMutable(); - boolsPacked_.addAll(other.boolsPacked_); - } - onChanged(); - } - if (!other.colorsPacked_.isEmpty()) { - if (colorsPacked_.isEmpty()) { - colorsPacked_ = other.colorsPacked_; - bitField1_ = (bitField1_ & ~0x00020000); - } else { - ensureColorsPackedIsMutable(); - colorsPacked_.addAll(other.colorsPacked_); - } - onChanged(); - } - if (!other.int32SNotPacked_.isEmpty()) { - if (int32SNotPacked_.isEmpty()) { - int32SNotPacked_ = other.int32SNotPacked_; - bitField1_ = (bitField1_ & ~0x00040000); - } else { - ensureInt32SNotPackedIsMutable(); - int32SNotPacked_.addAll(other.int32SNotPacked_); - } - onChanged(); - } - if (!other.int64SNotPacked_.isEmpty()) { - if (int64SNotPacked_.isEmpty()) { - int64SNotPacked_ = other.int64SNotPacked_; - bitField1_ = (bitField1_ & ~0x00080000); - } else { - ensureInt64SNotPackedIsMutable(); - int64SNotPacked_.addAll(other.int64SNotPacked_); - } - onChanged(); - } - if (!other.uint32SNotPacked_.isEmpty()) { - if (uint32SNotPacked_.isEmpty()) { - uint32SNotPacked_ = other.uint32SNotPacked_; - bitField1_ = (bitField1_ & ~0x00100000); - } else { - ensureUint32SNotPackedIsMutable(); - uint32SNotPacked_.addAll(other.uint32SNotPacked_); - } - onChanged(); - } - if (!other.uint64SNotPacked_.isEmpty()) { - if (uint64SNotPacked_.isEmpty()) { - uint64SNotPacked_ = other.uint64SNotPacked_; - bitField1_ = (bitField1_ & ~0x00200000); - } else { - ensureUint64SNotPackedIsMutable(); - uint64SNotPacked_.addAll(other.uint64SNotPacked_); - } - onChanged(); - } - if (!other.sint32SNotPacked_.isEmpty()) { - if (sint32SNotPacked_.isEmpty()) { - sint32SNotPacked_ = other.sint32SNotPacked_; - bitField1_ = (bitField1_ & ~0x00400000); - } else { - ensureSint32SNotPackedIsMutable(); - sint32SNotPacked_.addAll(other.sint32SNotPacked_); - } - onChanged(); - } - if (!other.sint64SNotPacked_.isEmpty()) { - if (sint64SNotPacked_.isEmpty()) { - sint64SNotPacked_ = other.sint64SNotPacked_; - bitField1_ = (bitField1_ & ~0x00800000); - } else { - ensureSint64SNotPackedIsMutable(); - sint64SNotPacked_.addAll(other.sint64SNotPacked_); - } - onChanged(); - } - if (!other.fixed32SNotPacked_.isEmpty()) { - if (fixed32SNotPacked_.isEmpty()) { - fixed32SNotPacked_ = other.fixed32SNotPacked_; - bitField1_ = (bitField1_ & ~0x01000000); - } else { - ensureFixed32SNotPackedIsMutable(); - fixed32SNotPacked_.addAll(other.fixed32SNotPacked_); - } - onChanged(); - } - if (!other.fixed64SNotPacked_.isEmpty()) { - if (fixed64SNotPacked_.isEmpty()) { - fixed64SNotPacked_ = other.fixed64SNotPacked_; - bitField1_ = (bitField1_ & ~0x02000000); - } else { - ensureFixed64SNotPackedIsMutable(); - fixed64SNotPacked_.addAll(other.fixed64SNotPacked_); - } - onChanged(); - } - if (!other.sfixed32SNotPacked_.isEmpty()) { - if (sfixed32SNotPacked_.isEmpty()) { - sfixed32SNotPacked_ = other.sfixed32SNotPacked_; - bitField1_ = (bitField1_ & ~0x04000000); - } else { - ensureSfixed32SNotPackedIsMutable(); - sfixed32SNotPacked_.addAll(other.sfixed32SNotPacked_); - } - onChanged(); - } - if (!other.sfixed64SNotPacked_.isEmpty()) { - if (sfixed64SNotPacked_.isEmpty()) { - sfixed64SNotPacked_ = other.sfixed64SNotPacked_; - bitField1_ = (bitField1_ & ~0x08000000); - } else { - ensureSfixed64SNotPackedIsMutable(); - sfixed64SNotPacked_.addAll(other.sfixed64SNotPacked_); - } - onChanged(); - } - if (!other.floatsNotPacked_.isEmpty()) { - if (floatsNotPacked_.isEmpty()) { - floatsNotPacked_ = other.floatsNotPacked_; - bitField1_ = (bitField1_ & ~0x10000000); - } else { - ensureFloatsNotPackedIsMutable(); - floatsNotPacked_.addAll(other.floatsNotPacked_); - } - onChanged(); - } - if (!other.doublesNotPacked_.isEmpty()) { - if (doublesNotPacked_.isEmpty()) { - doublesNotPacked_ = other.doublesNotPacked_; - bitField1_ = (bitField1_ & ~0x20000000); - } else { - ensureDoublesNotPackedIsMutable(); - doublesNotPacked_.addAll(other.doublesNotPacked_); - } - onChanged(); - } - if (!other.boolsNotPacked_.isEmpty()) { - if (boolsNotPacked_.isEmpty()) { - boolsNotPacked_ = other.boolsNotPacked_; - bitField1_ = (bitField1_ & ~0x40000000); - } else { - ensureBoolsNotPackedIsMutable(); - boolsNotPacked_.addAll(other.boolsNotPacked_); - } - onChanged(); - } - if (!other.colorsNotPacked_.isEmpty()) { - if (colorsNotPacked_.isEmpty()) { - colorsNotPacked_ = other.colorsNotPacked_; - bitField1_ = (bitField1_ & ~0x80000000); - } else { - ensureColorsNotPackedIsMutable(); - colorsNotPacked_.addAll(other.colorsNotPacked_); - } - onChanged(); - } - if (!other.strings_.isEmpty()) { - if (strings_.isEmpty()) { - strings_ = other.strings_; - bitField2_ = (bitField2_ & ~0x00000001); - } else { - ensureStringsIsMutable(); - strings_.addAll(other.strings_); - } - onChanged(); - } - if (!other.bytess_.isEmpty()) { - if (bytess_.isEmpty()) { - bytess_ = other.bytess_; - bitField2_ = (bitField2_ & ~0x00000002); - } else { - ensureBytessIsMutable(); - bytess_.addAll(other.bytess_); - } - onChanged(); - } - if (usersBuilder_ == null) { - if (!other.users_.isEmpty()) { - if (users_.isEmpty()) { - users_ = other.users_; - bitField2_ = (bitField2_ & ~0x00000004); - } else { - ensureUsersIsMutable(); - users_.addAll(other.users_); - } - onChanged(); - } - } else { - if (!other.users_.isEmpty()) { - if (usersBuilder_.isEmpty()) { - usersBuilder_.dispose(); - usersBuilder_ = null; - users_ = other.users_; - bitField2_ = (bitField2_ & ~0x00000004); - usersBuilder_ = - com.google.protobuf.GeneratedMessageV3.alwaysUseFieldBuilders ? - getUsersFieldBuilder() : null; - } else { - usersBuilder_.addAllMessages(other.users_); - } - } - } - this.mergeUnknownFields(other.unknownFields); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - private int bitField0_; - private int bitField1_; - private int bitField2_; - - private int int32_ ; - /** - * int32 int32 = 1; - */ - public int getInt32() { - return int32_; - } - /** - * int32 int32 = 1; - */ - public Builder setInt32(int value) { - - int32_ = value; - onChanged(); - return this; - } - /** - * int32 int32 = 1; - */ - public Builder clearInt32() { - - int32_ = 0; - onChanged(); - return this; - } - - private long int64_ ; - /** - * int64 int64 = 2; - */ - public long getInt64() { - return int64_; - } - /** - * int64 int64 = 2; - */ - public Builder setInt64(long value) { - - int64_ = value; - onChanged(); - return this; - } - /** - * int64 int64 = 2; - */ - public Builder clearInt64() { - - int64_ = 0L; - onChanged(); - return this; - } - - private int uint32_ ; - /** - * uint32 uint32 = 3; - */ - public int getUint32() { - return uint32_; - } - /** - * uint32 uint32 = 3; - */ - public Builder setUint32(int value) { - - uint32_ = value; - onChanged(); - return this; - } - /** - * uint32 uint32 = 3; - */ - public Builder clearUint32() { - - uint32_ = 0; - onChanged(); - return this; - } - - private long uint64_ ; - /** - * uint64 uint64 = 4; - */ - public long getUint64() { - return uint64_; - } - /** - * uint64 uint64 = 4; - */ - public Builder setUint64(long value) { - - uint64_ = value; - onChanged(); - return this; - } - /** - * uint64 uint64 = 4; - */ - public Builder clearUint64() { - - uint64_ = 0L; - onChanged(); - return this; - } - - private int sint32_ ; - /** - * sint32 sint32 = 5; - */ - public int getSint32() { - return sint32_; - } - /** - * sint32 sint32 = 5; - */ - public Builder setSint32(int value) { - - sint32_ = value; - onChanged(); - return this; - } - /** - * sint32 sint32 = 5; - */ - public Builder clearSint32() { - - sint32_ = 0; - onChanged(); - return this; - } - - private long sint64_ ; - /** - * sint64 sint64 = 6; - */ - public long getSint64() { - return sint64_; - } - /** - * sint64 sint64 = 6; - */ - public Builder setSint64(long value) { - - sint64_ = value; - onChanged(); - return this; - } - /** - * sint64 sint64 = 6; - */ - public Builder clearSint64() { - - sint64_ = 0L; - onChanged(); - return this; - } - - private int fixed32_ ; - /** - * fixed32 fixed32 = 7; - */ - public int getFixed32() { - return fixed32_; - } - /** - * fixed32 fixed32 = 7; - */ - public Builder setFixed32(int value) { - - fixed32_ = value; - onChanged(); - return this; - } - /** - * fixed32 fixed32 = 7; - */ - public Builder clearFixed32() { - - fixed32_ = 0; - onChanged(); - return this; - } - - private long fixed64_ ; - /** - * fixed64 fixed64 = 8; - */ - public long getFixed64() { - return fixed64_; - } - /** - * fixed64 fixed64 = 8; - */ - public Builder setFixed64(long value) { - - fixed64_ = value; - onChanged(); - return this; - } - /** - * fixed64 fixed64 = 8; - */ - public Builder clearFixed64() { - - fixed64_ = 0L; - onChanged(); - return this; - } - - private int sfixed32_ ; - /** - * sfixed32 sfixed32 = 9; - */ - public int getSfixed32() { - return sfixed32_; - } - /** - * sfixed32 sfixed32 = 9; - */ - public Builder setSfixed32(int value) { - - sfixed32_ = value; - onChanged(); - return this; - } - /** - * sfixed32 sfixed32 = 9; - */ - public Builder clearSfixed32() { - - sfixed32_ = 0; - onChanged(); - return this; - } - - private long sfixed64_ ; - /** - * sfixed64 sfixed64 = 10; - */ - public long getSfixed64() { - return sfixed64_; - } - /** - * sfixed64 sfixed64 = 10; - */ - public Builder setSfixed64(long value) { - - sfixed64_ = value; - onChanged(); - return this; - } - /** - * sfixed64 sfixed64 = 10; - */ - public Builder clearSfixed64() { - - sfixed64_ = 0L; - onChanged(); - return this; - } - - private float floatValue_ ; - /** - * float floatValue = 11; - */ - public float getFloatValue() { - return floatValue_; - } - /** - * float floatValue = 11; - */ - public Builder setFloatValue(float value) { - - floatValue_ = value; - onChanged(); - return this; - } - /** - * float floatValue = 11; - */ - public Builder clearFloatValue() { - - floatValue_ = 0F; - onChanged(); - return this; - } - - private double doubleValue_ ; - /** - * double doubleValue = 12; - */ - public double getDoubleValue() { - return doubleValue_; - } - /** - * double doubleValue = 12; - */ - public Builder setDoubleValue(double value) { - - doubleValue_ = value; - onChanged(); - return this; - } - /** - * double doubleValue = 12; - */ - public Builder clearDoubleValue() { - - doubleValue_ = 0D; - onChanged(); - return this; - } - - private boolean bool_ ; - /** - * bool bool = 13; - */ - public boolean getBool() { - return bool_; - } - /** - * bool bool = 13; - */ - public Builder setBool(boolean value) { - - bool_ = value; - onChanged(); - return this; - } - /** - * bool bool = 13; - */ - public Builder clearBool() { - - bool_ = false; - onChanged(); - return this; - } - - private int objInt32_ ; - /** - * int32 objInt32 = 20; - */ - public int getObjInt32() { - return objInt32_; - } - /** - * int32 objInt32 = 20; - */ - public Builder setObjInt32(int value) { - - objInt32_ = value; - onChanged(); - return this; - } - /** - * int32 objInt32 = 20; - */ - public Builder clearObjInt32() { - - objInt32_ = 0; - onChanged(); - return this; - } - - private long objInt64_ ; - /** - * int64 objInt64 = 21; - */ - public long getObjInt64() { - return objInt64_; - } - /** - * int64 objInt64 = 21; - */ - public Builder setObjInt64(long value) { - - objInt64_ = value; - onChanged(); - return this; - } - /** - * int64 objInt64 = 21; - */ - public Builder clearObjInt64() { - - objInt64_ = 0L; - onChanged(); - return this; - } - - private int objUint32_ ; - /** - * uint32 objUint32 = 22; - */ - public int getObjUint32() { - return objUint32_; - } - /** - * uint32 objUint32 = 22; - */ - public Builder setObjUint32(int value) { - - objUint32_ = value; - onChanged(); - return this; - } - /** - * uint32 objUint32 = 22; - */ - public Builder clearObjUint32() { - - objUint32_ = 0; - onChanged(); - return this; - } - - private long objUint64_ ; - /** - * uint64 objUint64 = 23; - */ - public long getObjUint64() { - return objUint64_; - } - /** - * uint64 objUint64 = 23; - */ - public Builder setObjUint64(long value) { - - objUint64_ = value; - onChanged(); - return this; - } - /** - * uint64 objUint64 = 23; - */ - public Builder clearObjUint64() { - - objUint64_ = 0L; - onChanged(); - return this; - } - - private int objSint32_ ; - /** - * sint32 objSint32 = 24; - */ - public int getObjSint32() { - return objSint32_; - } - /** - * sint32 objSint32 = 24; - */ - public Builder setObjSint32(int value) { - - objSint32_ = value; - onChanged(); - return this; - } - /** - * sint32 objSint32 = 24; - */ - public Builder clearObjSint32() { - - objSint32_ = 0; - onChanged(); - return this; - } - - private long objSint64_ ; - /** - * sint64 objSint64 = 25; - */ - public long getObjSint64() { - return objSint64_; - } - /** - * sint64 objSint64 = 25; - */ - public Builder setObjSint64(long value) { - - objSint64_ = value; - onChanged(); - return this; - } - /** - * sint64 objSint64 = 25; - */ - public Builder clearObjSint64() { - - objSint64_ = 0L; - onChanged(); - return this; - } - - private int objFixed32_ ; - /** - * fixed32 objFixed32 = 26; - */ - public int getObjFixed32() { - return objFixed32_; - } - /** - * fixed32 objFixed32 = 26; - */ - public Builder setObjFixed32(int value) { - - objFixed32_ = value; - onChanged(); - return this; - } - /** - * fixed32 objFixed32 = 26; - */ - public Builder clearObjFixed32() { - - objFixed32_ = 0; - onChanged(); - return this; - } - - private long objFixed64_ ; - /** - * fixed64 objFixed64 = 27; - */ - public long getObjFixed64() { - return objFixed64_; - } - /** - * fixed64 objFixed64 = 27; - */ - public Builder setObjFixed64(long value) { - - objFixed64_ = value; - onChanged(); - return this; - } - /** - * fixed64 objFixed64 = 27; - */ - public Builder clearObjFixed64() { - - objFixed64_ = 0L; - onChanged(); - return this; - } - - private int objSfixed32_ ; - /** - * sfixed32 objSfixed32 = 28; - */ - public int getObjSfixed32() { - return objSfixed32_; - } - /** - * sfixed32 objSfixed32 = 28; - */ - public Builder setObjSfixed32(int value) { - - objSfixed32_ = value; - onChanged(); - return this; - } - /** - * sfixed32 objSfixed32 = 28; - */ - public Builder clearObjSfixed32() { - - objSfixed32_ = 0; - onChanged(); - return this; - } - - private long objSfixed64_ ; - /** - * sfixed64 objSfixed64 = 29; - */ - public long getObjSfixed64() { - return objSfixed64_; - } - /** - * sfixed64 objSfixed64 = 29; - */ - public Builder setObjSfixed64(long value) { - - objSfixed64_ = value; - onChanged(); - return this; - } - /** - * sfixed64 objSfixed64 = 29; - */ - public Builder clearObjSfixed64() { - - objSfixed64_ = 0L; - onChanged(); - return this; - } - - private float objFloatValue_ ; - /** - * float objFloatValue = 30; - */ - public float getObjFloatValue() { - return objFloatValue_; - } - /** - * float objFloatValue = 30; - */ - public Builder setObjFloatValue(float value) { - - objFloatValue_ = value; - onChanged(); - return this; - } - /** - * float objFloatValue = 30; - */ - public Builder clearObjFloatValue() { - - objFloatValue_ = 0F; - onChanged(); - return this; - } - - private double objDoubleValue_ ; - /** - * double objDoubleValue = 31; - */ - public double getObjDoubleValue() { - return objDoubleValue_; - } - /** - * double objDoubleValue = 31; - */ - public Builder setObjDoubleValue(double value) { - - objDoubleValue_ = value; - onChanged(); - return this; - } - /** - * double objDoubleValue = 31; - */ - public Builder clearObjDoubleValue() { - - objDoubleValue_ = 0D; - onChanged(); - return this; - } - - private boolean objBool_ ; - /** - * bool objBool = 32; - */ - public boolean getObjBool() { - return objBool_; - } - /** - * bool objBool = 32; - */ - public Builder setObjBool(boolean value) { - - objBool_ = value; - onChanged(); - return this; - } - /** - * bool objBool = 32; - */ - public Builder clearObjBool() { - - objBool_ = false; - onChanged(); - return this; - } - - private java.lang.Object string_ = ""; - /** - * string string = 40; - */ - public java.lang.String getString() { - java.lang.Object ref = string_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - string_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * string string = 40; - */ - public com.google.protobuf.ByteString - getStringBytes() { - java.lang.Object ref = string_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - string_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string string = 40; - */ - public Builder setString( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - string_ = value; - onChanged(); - return this; - } - /** - * string string = 40; - */ - public Builder clearString() { - - string_ = getDefaultInstance().getString(); - onChanged(); - return this; - } - /** - * string string = 40; - */ - public Builder setStringBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - string_ = value; - onChanged(); - return this; - } - - private com.google.protobuf.ByteString bytes_ = com.google.protobuf.ByteString.EMPTY; - /** - * bytes bytes = 41; - */ - public com.google.protobuf.ByteString getBytes() { - return bytes_; - } - /** - * bytes bytes = 41; - */ - public Builder setBytes(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - - bytes_ = value; - onChanged(); - return this; - } - /** - * bytes bytes = 41; - */ - public Builder clearBytes() { - - bytes_ = getDefaultInstance().getBytes(); - onChanged(); - return this; - } - - private int color_ = 0; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public int getColorValue() { - return color_; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public Builder setColorValue(int value) { - color_ = value; - onChanged(); - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColor() { - @SuppressWarnings("deprecation") - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color result = org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.valueOf(color_); - return result == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color.UNRECOGNIZED : result; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public Builder setColor(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value) { - if (value == null) { - throw new NullPointerException(); - } - - color_ = value.getNumber(); - onChanged(); - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Color color = 42; - */ - public Builder clearColor() { - - color_ = 0; - onChanged(); - return this; - } - - private org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User user_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder> userBuilder_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public boolean hasUser() { - return userBuilder_ != null || user_ != null; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getUser() { - if (userBuilder_ == null) { - return user_ == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance() : user_; - } else { - return userBuilder_.getMessage(); - } - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public Builder setUser(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User value) { - if (userBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - user_ = value; - onChanged(); - } else { - userBuilder_.setMessage(value); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public Builder setUser( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder builderForValue) { - if (userBuilder_ == null) { - user_ = builderForValue.build(); - onChanged(); - } else { - userBuilder_.setMessage(builderForValue.build()); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public Builder mergeUser(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User value) { - if (userBuilder_ == null) { - if (user_ != null) { - user_ = - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.newBuilder(user_).mergeFrom(value).buildPartial(); - } else { - user_ = value; - } - onChanged(); - } else { - userBuilder_.mergeFrom(value); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public Builder clearUser() { - if (userBuilder_ == null) { - user_ = null; - onChanged(); - } else { - user_ = null; - userBuilder_ = null; - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder getUserBuilder() { - - onChanged(); - return getUserFieldBuilder().getBuilder(); - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder getUserOrBuilder() { - if (userBuilder_ != null) { - return userBuilder_.getMessageOrBuilder(); - } else { - return user_ == null ? - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance() : user_; - } - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.User user = 43; - */ - private com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder> - getUserFieldBuilder() { - if (userBuilder_ == null) { - userBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder>( - getUser(), - getParentForChildren(), - isClean()); - user_ = null; - } - return userBuilder_; - } - - private org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root typeRecursive_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder> typeRecursiveBuilder_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public boolean hasTypeRecursive() { - return typeRecursiveBuilder_ != null || typeRecursive_ != null; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getTypeRecursive() { - if (typeRecursiveBuilder_ == null) { - return typeRecursive_ == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance() : typeRecursive_; - } else { - return typeRecursiveBuilder_.getMessage(); - } - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public Builder setTypeRecursive(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root value) { - if (typeRecursiveBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - typeRecursive_ = value; - onChanged(); - } else { - typeRecursiveBuilder_.setMessage(value); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public Builder setTypeRecursive( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder builderForValue) { - if (typeRecursiveBuilder_ == null) { - typeRecursive_ = builderForValue.build(); - onChanged(); - } else { - typeRecursiveBuilder_.setMessage(builderForValue.build()); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public Builder mergeTypeRecursive(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root value) { - if (typeRecursiveBuilder_ == null) { - if (typeRecursive_ != null) { - typeRecursive_ = - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.newBuilder(typeRecursive_).mergeFrom(value).buildPartial(); - } else { - typeRecursive_ = value; - } - onChanged(); - } else { - typeRecursiveBuilder_.mergeFrom(value); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public Builder clearTypeRecursive() { - if (typeRecursiveBuilder_ == null) { - typeRecursive_ = null; - onChanged(); - } else { - typeRecursive_ = null; - typeRecursiveBuilder_ = null; - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder getTypeRecursiveBuilder() { - - onChanged(); - return getTypeRecursiveFieldBuilder().getBuilder(); - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder getTypeRecursiveOrBuilder() { - if (typeRecursiveBuilder_ != null) { - return typeRecursiveBuilder_.getMessageOrBuilder(); - } else { - return typeRecursive_ == null ? - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance() : typeRecursive_; - } - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 44; - */ - private com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder> - getTypeRecursiveFieldBuilder() { - if (typeRecursiveBuilder_ == null) { - typeRecursiveBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder>( - getTypeRecursive(), - getParentForChildren(), - isClean()); - typeRecursive_ = null; - } - return typeRecursiveBuilder_; - } - - private com.google.protobuf.Any any_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder> anyBuilder_; - /** - * .google.protobuf.Any any = 50; - */ - public boolean hasAny() { - return anyBuilder_ != null || any_ != null; - } - /** - * .google.protobuf.Any any = 50; - */ - public com.google.protobuf.Any getAny() { - if (anyBuilder_ == null) { - return any_ == null ? com.google.protobuf.Any.getDefaultInstance() : any_; - } else { - return anyBuilder_.getMessage(); - } - } - /** - * .google.protobuf.Any any = 50; - */ - public Builder setAny(com.google.protobuf.Any value) { - if (anyBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - any_ = value; - onChanged(); - } else { - anyBuilder_.setMessage(value); - } - - return this; - } - /** - * .google.protobuf.Any any = 50; - */ - public Builder setAny( - com.google.protobuf.Any.Builder builderForValue) { - if (anyBuilder_ == null) { - any_ = builderForValue.build(); - onChanged(); - } else { - anyBuilder_.setMessage(builderForValue.build()); - } - - return this; - } - /** - * .google.protobuf.Any any = 50; - */ - public Builder mergeAny(com.google.protobuf.Any value) { - if (anyBuilder_ == null) { - if (any_ != null) { - any_ = - com.google.protobuf.Any.newBuilder(any_).mergeFrom(value).buildPartial(); - } else { - any_ = value; - } - onChanged(); - } else { - anyBuilder_.mergeFrom(value); - } - - return this; - } - /** - * .google.protobuf.Any any = 50; - */ - public Builder clearAny() { - if (anyBuilder_ == null) { - any_ = null; - onChanged(); - } else { - any_ = null; - anyBuilder_ = null; - } - - return this; - } - /** - * .google.protobuf.Any any = 50; - */ - public com.google.protobuf.Any.Builder getAnyBuilder() { - - onChanged(); - return getAnyFieldBuilder().getBuilder(); - } - /** - * .google.protobuf.Any any = 50; - */ - public com.google.protobuf.AnyOrBuilder getAnyOrBuilder() { - if (anyBuilder_ != null) { - return anyBuilder_.getMessageOrBuilder(); - } else { - return any_ == null ? - com.google.protobuf.Any.getDefaultInstance() : any_; - } - } - /** - * .google.protobuf.Any any = 50; - */ - private com.google.protobuf.SingleFieldBuilderV3< - com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder> - getAnyFieldBuilder() { - if (anyBuilder_ == null) { - anyBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder>( - getAny(), - getParentForChildren(), - isClean()); - any_ = null; - } - return anyBuilder_; - } - - private java.util.List anys_ = - java.util.Collections.emptyList(); - private void ensureAnysIsMutable() { - if (!((bitField1_ & 0x00000001) == 0x00000001)) { - anys_ = new java.util.ArrayList(anys_); - bitField1_ |= 0x00000001; - } - } - - private com.google.protobuf.RepeatedFieldBuilderV3< - com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder> anysBuilder_; - - /** - * repeated .google.protobuf.Any anys = 51; - */ - public java.util.List getAnysList() { - if (anysBuilder_ == null) { - return java.util.Collections.unmodifiableList(anys_); - } else { - return anysBuilder_.getMessageList(); - } - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public int getAnysCount() { - if (anysBuilder_ == null) { - return anys_.size(); - } else { - return anysBuilder_.getCount(); - } - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.Any getAnys(int index) { - if (anysBuilder_ == null) { - return anys_.get(index); - } else { - return anysBuilder_.getMessage(index); - } - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder setAnys( - int index, com.google.protobuf.Any value) { - if (anysBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureAnysIsMutable(); - anys_.set(index, value); - onChanged(); - } else { - anysBuilder_.setMessage(index, value); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder setAnys( - int index, com.google.protobuf.Any.Builder builderForValue) { - if (anysBuilder_ == null) { - ensureAnysIsMutable(); - anys_.set(index, builderForValue.build()); - onChanged(); - } else { - anysBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder addAnys(com.google.protobuf.Any value) { - if (anysBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureAnysIsMutable(); - anys_.add(value); - onChanged(); - } else { - anysBuilder_.addMessage(value); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder addAnys( - int index, com.google.protobuf.Any value) { - if (anysBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureAnysIsMutable(); - anys_.add(index, value); - onChanged(); - } else { - anysBuilder_.addMessage(index, value); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder addAnys( - com.google.protobuf.Any.Builder builderForValue) { - if (anysBuilder_ == null) { - ensureAnysIsMutable(); - anys_.add(builderForValue.build()); - onChanged(); - } else { - anysBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder addAnys( - int index, com.google.protobuf.Any.Builder builderForValue) { - if (anysBuilder_ == null) { - ensureAnysIsMutable(); - anys_.add(index, builderForValue.build()); - onChanged(); - } else { - anysBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder addAllAnys( - java.lang.Iterable values) { - if (anysBuilder_ == null) { - ensureAnysIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, anys_); - onChanged(); - } else { - anysBuilder_.addAllMessages(values); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder clearAnys() { - if (anysBuilder_ == null) { - anys_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000001); - onChanged(); - } else { - anysBuilder_.clear(); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public Builder removeAnys(int index) { - if (anysBuilder_ == null) { - ensureAnysIsMutable(); - anys_.remove(index); - onChanged(); - } else { - anysBuilder_.remove(index); - } - return this; - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.Any.Builder getAnysBuilder( - int index) { - return getAnysFieldBuilder().getBuilder(index); - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.AnyOrBuilder getAnysOrBuilder( - int index) { - if (anysBuilder_ == null) { - return anys_.get(index); } else { - return anysBuilder_.getMessageOrBuilder(index); - } - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public java.util.List - getAnysOrBuilderList() { - if (anysBuilder_ != null) { - return anysBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(anys_); - } - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.Any.Builder addAnysBuilder() { - return getAnysFieldBuilder().addBuilder( - com.google.protobuf.Any.getDefaultInstance()); - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public com.google.protobuf.Any.Builder addAnysBuilder( - int index) { - return getAnysFieldBuilder().addBuilder( - index, com.google.protobuf.Any.getDefaultInstance()); - } - /** - * repeated .google.protobuf.Any anys = 51; - */ - public java.util.List - getAnysBuilderList() { - return getAnysFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilderV3< - com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder> - getAnysFieldBuilder() { - if (anysBuilder_ == null) { - anysBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - com.google.protobuf.Any, com.google.protobuf.Any.Builder, com.google.protobuf.AnyOrBuilder>( - anys_, - ((bitField1_ & 0x00000001) == 0x00000001), - getParentForChildren(), - isClean()); - anys_ = null; - } - return anysBuilder_; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.String> ssMap_; - private com.google.protobuf.MapField - internalGetSsMap() { - if (ssMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - SsMapDefaultEntryHolder.defaultEntry); - } - return ssMap_; - } - private com.google.protobuf.MapField - internalGetMutableSsMap() { - onChanged();; - if (ssMap_ == null) { - ssMap_ = com.google.protobuf.MapField.newMapField( - SsMapDefaultEntryHolder.defaultEntry); - } - if (!ssMap_.isMutable()) { - ssMap_ = ssMap_.copy(); - } - return ssMap_; - } - - public int getSsMapCount() { - return internalGetSsMap().getMap().size(); - } - /** - * map<string, string> ssMap = 60; - */ - - public boolean containsSsMap( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - return internalGetSsMap().getMap().containsKey(key); - } - /** - * Use {@link #getSsMapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getSsMap() { - return getSsMapMap(); - } - /** - * map<string, string> ssMap = 60; - */ - - public java.util.Map getSsMapMap() { - return internalGetSsMap().getMap(); - } - /** - * map<string, string> ssMap = 60; - */ - - public java.lang.String getSsMapOrDefault( - java.lang.String key, - java.lang.String defaultValue) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSsMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, string> ssMap = 60; - */ - - public java.lang.String getSsMapOrThrow( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSsMap().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearSsMap() { - internalGetMutableSsMap().getMutableMap() - .clear(); - return this; - } - /** - * map<string, string> ssMap = 60; - */ - - public Builder removeSsMap( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - internalGetMutableSsMap().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableSsMap() { - return internalGetMutableSsMap().getMutableMap(); - } - /** - * map<string, string> ssMap = 60; - */ - public Builder putSsMap( - java.lang.String key, - java.lang.String value) { - if (key == null) { throw new java.lang.NullPointerException(); } - if (value == null) { throw new java.lang.NullPointerException(); } - internalGetMutableSsMap().getMutableMap() - .put(key, value); - return this; - } - /** - * map<string, string> ssMap = 60; - */ - - public Builder putAllSsMap( - java.util.Map values) { - internalGetMutableSsMap().getMutableMap() - .putAll(values); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, java.lang.Integer> sint32Map_; - private com.google.protobuf.MapField - internalGetSint32Map() { - if (sint32Map_ == null) { - return com.google.protobuf.MapField.emptyMapField( - Sint32MapDefaultEntryHolder.defaultEntry); - } - return sint32Map_; - } - private com.google.protobuf.MapField - internalGetMutableSint32Map() { - onChanged();; - if (sint32Map_ == null) { - sint32Map_ = com.google.protobuf.MapField.newMapField( - Sint32MapDefaultEntryHolder.defaultEntry); - } - if (!sint32Map_.isMutable()) { - sint32Map_ = sint32Map_.copy(); - } - return sint32Map_; - } - - public int getSint32MapCount() { - return internalGetSint32Map().getMap().size(); - } - /** - * map<string, int32> sint32Map = 61; - */ - - public boolean containsSint32Map( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - return internalGetSint32Map().getMap().containsKey(key); - } - /** - * Use {@link #getSint32MapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getSint32Map() { - return getSint32MapMap(); - } - /** - * map<string, int32> sint32Map = 61; - */ - - public java.util.Map getSint32MapMap() { - return internalGetSint32Map().getMap(); - } - /** - * map<string, int32> sint32Map = 61; - */ - - public int getSint32MapOrDefault( - java.lang.String key, - int defaultValue) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSint32Map().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, int32> sint32Map = 61; - */ - - public int getSint32MapOrThrow( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSint32Map().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearSint32Map() { - internalGetMutableSint32Map().getMutableMap() - .clear(); - return this; - } - /** - * map<string, int32> sint32Map = 61; - */ - - public Builder removeSint32Map( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - internalGetMutableSint32Map().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableSint32Map() { - return internalGetMutableSint32Map().getMutableMap(); - } - /** - * map<string, int32> sint32Map = 61; - */ - public Builder putSint32Map( - java.lang.String key, - int value) { - if (key == null) { throw new java.lang.NullPointerException(); } - - internalGetMutableSint32Map().getMutableMap() - .put(key, value); - return this; - } - /** - * map<string, int32> sint32Map = 61; - */ - - public Builder putAllSint32Map( - java.util.Map values) { - internalGetMutableSint32Map().getMutableMap() - .putAll(values); - return this; - } - - private com.google.protobuf.MapField< - java.lang.String, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User> spMap_; - private com.google.protobuf.MapField - internalGetSpMap() { - if (spMap_ == null) { - return com.google.protobuf.MapField.emptyMapField( - SpMapDefaultEntryHolder.defaultEntry); - } - return spMap_; - } - private com.google.protobuf.MapField - internalGetMutableSpMap() { - onChanged();; - if (spMap_ == null) { - spMap_ = com.google.protobuf.MapField.newMapField( - SpMapDefaultEntryHolder.defaultEntry); - } - if (!spMap_.isMutable()) { - spMap_ = spMap_.copy(); - } - return spMap_; - } - - public int getSpMapCount() { - return internalGetSpMap().getMap().size(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public boolean containsSpMap( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - return internalGetSpMap().getMap().containsKey(key); - } - /** - * Use {@link #getSpMapMap()} instead. - */ - @java.lang.Deprecated - public java.util.Map getSpMap() { - return getSpMapMap(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public java.util.Map getSpMapMap() { - return internalGetSpMap().getMap(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getSpMapOrDefault( - java.lang.String key, - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User defaultValue) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSpMap().getMap(); - return map.containsKey(key) ? map.get(key) : defaultValue; - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getSpMapOrThrow( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - java.util.Map map = - internalGetSpMap().getMap(); - if (!map.containsKey(key)) { - throw new java.lang.IllegalArgumentException(); - } - return map.get(key); - } - - public Builder clearSpMap() { - internalGetMutableSpMap().getMutableMap() - .clear(); - return this; - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public Builder removeSpMap( - java.lang.String key) { - if (key == null) { throw new java.lang.NullPointerException(); } - internalGetMutableSpMap().getMutableMap() - .remove(key); - return this; - } - /** - * Use alternate mutation accessors instead. - */ - @java.lang.Deprecated - public java.util.Map - getMutableSpMap() { - return internalGetMutableSpMap().getMutableMap(); - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - public Builder putSpMap( - java.lang.String key, - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User value) { - if (key == null) { throw new java.lang.NullPointerException(); } - if (value == null) { throw new java.lang.NullPointerException(); } - internalGetMutableSpMap().getMutableMap() - .put(key, value); - return this; - } - /** - * map<string, .org.apache.servicecomb.foundation.protobuf.internal.model.User> spMap = 62; - */ - - public Builder putAllSpMap( - java.util.Map values) { - internalGetMutableSpMap().getMutableMap() - .putAll(values); - return this; - } - - private java.util.List int32SPacked_ = java.util.Collections.emptyList(); - private void ensureInt32SPackedIsMutable() { - if (!((bitField1_ & 0x00000010) == 0x00000010)) { - int32SPacked_ = new java.util.ArrayList(int32SPacked_); - bitField1_ |= 0x00000010; - } - } - /** - * repeated int32 int32sPacked = 70; - */ - public java.util.List - getInt32SPackedList() { - return java.util.Collections.unmodifiableList(int32SPacked_); - } - /** - * repeated int32 int32sPacked = 70; - */ - public int getInt32SPackedCount() { - return int32SPacked_.size(); - } - /** - * repeated int32 int32sPacked = 70; - */ - public int getInt32SPacked(int index) { - return int32SPacked_.get(index); - } - /** - * repeated int32 int32sPacked = 70; - */ - public Builder setInt32SPacked( - int index, int value) { - ensureInt32SPackedIsMutable(); - int32SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated int32 int32sPacked = 70; - */ - public Builder addInt32SPacked(int value) { - ensureInt32SPackedIsMutable(); - int32SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated int32 int32sPacked = 70; - */ - public Builder addAllInt32SPacked( - java.lang.Iterable values) { - ensureInt32SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, int32SPacked_); - onChanged(); - return this; - } - /** - * repeated int32 int32sPacked = 70; - */ - public Builder clearInt32SPacked() { - int32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000010); - onChanged(); - return this; - } - - private java.util.List int64SPacked_ = java.util.Collections.emptyList(); - private void ensureInt64SPackedIsMutable() { - if (!((bitField1_ & 0x00000020) == 0x00000020)) { - int64SPacked_ = new java.util.ArrayList(int64SPacked_); - bitField1_ |= 0x00000020; - } - } - /** - * repeated int64 int64sPacked = 71; - */ - public java.util.List - getInt64SPackedList() { - return java.util.Collections.unmodifiableList(int64SPacked_); - } - /** - * repeated int64 int64sPacked = 71; - */ - public int getInt64SPackedCount() { - return int64SPacked_.size(); - } - /** - * repeated int64 int64sPacked = 71; - */ - public long getInt64SPacked(int index) { - return int64SPacked_.get(index); - } - /** - * repeated int64 int64sPacked = 71; - */ - public Builder setInt64SPacked( - int index, long value) { - ensureInt64SPackedIsMutable(); - int64SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated int64 int64sPacked = 71; - */ - public Builder addInt64SPacked(long value) { - ensureInt64SPackedIsMutable(); - int64SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated int64 int64sPacked = 71; - */ - public Builder addAllInt64SPacked( - java.lang.Iterable values) { - ensureInt64SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, int64SPacked_); - onChanged(); - return this; - } - /** - * repeated int64 int64sPacked = 71; - */ - public Builder clearInt64SPacked() { - int64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000020); - onChanged(); - return this; - } - - private java.util.List uint32SPacked_ = java.util.Collections.emptyList(); - private void ensureUint32SPackedIsMutable() { - if (!((bitField1_ & 0x00000040) == 0x00000040)) { - uint32SPacked_ = new java.util.ArrayList(uint32SPacked_); - bitField1_ |= 0x00000040; - } - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public java.util.List - getUint32SPackedList() { - return java.util.Collections.unmodifiableList(uint32SPacked_); - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public int getUint32SPackedCount() { - return uint32SPacked_.size(); - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public int getUint32SPacked(int index) { - return uint32SPacked_.get(index); - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public Builder setUint32SPacked( - int index, int value) { - ensureUint32SPackedIsMutable(); - uint32SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public Builder addUint32SPacked(int value) { - ensureUint32SPackedIsMutable(); - uint32SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public Builder addAllUint32SPacked( - java.lang.Iterable values) { - ensureUint32SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, uint32SPacked_); - onChanged(); - return this; - } - /** - * repeated uint32 uint32sPacked = 72; - */ - public Builder clearUint32SPacked() { - uint32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000040); - onChanged(); - return this; - } - - private java.util.List uint64SPacked_ = java.util.Collections.emptyList(); - private void ensureUint64SPackedIsMutable() { - if (!((bitField1_ & 0x00000080) == 0x00000080)) { - uint64SPacked_ = new java.util.ArrayList(uint64SPacked_); - bitField1_ |= 0x00000080; - } - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public java.util.List - getUint64SPackedList() { - return java.util.Collections.unmodifiableList(uint64SPacked_); - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public int getUint64SPackedCount() { - return uint64SPacked_.size(); - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public long getUint64SPacked(int index) { - return uint64SPacked_.get(index); - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public Builder setUint64SPacked( - int index, long value) { - ensureUint64SPackedIsMutable(); - uint64SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public Builder addUint64SPacked(long value) { - ensureUint64SPackedIsMutable(); - uint64SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public Builder addAllUint64SPacked( - java.lang.Iterable values) { - ensureUint64SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, uint64SPacked_); - onChanged(); - return this; - } - /** - * repeated uint64 uint64sPacked = 73; - */ - public Builder clearUint64SPacked() { - uint64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000080); - onChanged(); - return this; - } - - private java.util.List sint32SPacked_ = java.util.Collections.emptyList(); - private void ensureSint32SPackedIsMutable() { - if (!((bitField1_ & 0x00000100) == 0x00000100)) { - sint32SPacked_ = new java.util.ArrayList(sint32SPacked_); - bitField1_ |= 0x00000100; - } - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public java.util.List - getSint32SPackedList() { - return java.util.Collections.unmodifiableList(sint32SPacked_); - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public int getSint32SPackedCount() { - return sint32SPacked_.size(); - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public int getSint32SPacked(int index) { - return sint32SPacked_.get(index); - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public Builder setSint32SPacked( - int index, int value) { - ensureSint32SPackedIsMutable(); - sint32SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public Builder addSint32SPacked(int value) { - ensureSint32SPackedIsMutable(); - sint32SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public Builder addAllSint32SPacked( - java.lang.Iterable values) { - ensureSint32SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sint32SPacked_); - onChanged(); - return this; - } - /** - * repeated sint32 sint32sPacked = 74; - */ - public Builder clearSint32SPacked() { - sint32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000100); - onChanged(); - return this; - } - - private java.util.List sint64SPacked_ = java.util.Collections.emptyList(); - private void ensureSint64SPackedIsMutable() { - if (!((bitField1_ & 0x00000200) == 0x00000200)) { - sint64SPacked_ = new java.util.ArrayList(sint64SPacked_); - bitField1_ |= 0x00000200; - } - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public java.util.List - getSint64SPackedList() { - return java.util.Collections.unmodifiableList(sint64SPacked_); - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public int getSint64SPackedCount() { - return sint64SPacked_.size(); - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public long getSint64SPacked(int index) { - return sint64SPacked_.get(index); - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public Builder setSint64SPacked( - int index, long value) { - ensureSint64SPackedIsMutable(); - sint64SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public Builder addSint64SPacked(long value) { - ensureSint64SPackedIsMutable(); - sint64SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public Builder addAllSint64SPacked( - java.lang.Iterable values) { - ensureSint64SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sint64SPacked_); - onChanged(); - return this; - } - /** - * repeated sint64 sint64sPacked = 75; - */ - public Builder clearSint64SPacked() { - sint64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000200); - onChanged(); - return this; - } - - private java.util.List fixed32SPacked_ = java.util.Collections.emptyList(); - private void ensureFixed32SPackedIsMutable() { - if (!((bitField1_ & 0x00000400) == 0x00000400)) { - fixed32SPacked_ = new java.util.ArrayList(fixed32SPacked_); - bitField1_ |= 0x00000400; - } - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public java.util.List - getFixed32SPackedList() { - return java.util.Collections.unmodifiableList(fixed32SPacked_); - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public int getFixed32SPackedCount() { - return fixed32SPacked_.size(); - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public int getFixed32SPacked(int index) { - return fixed32SPacked_.get(index); - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public Builder setFixed32SPacked( - int index, int value) { - ensureFixed32SPackedIsMutable(); - fixed32SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public Builder addFixed32SPacked(int value) { - ensureFixed32SPackedIsMutable(); - fixed32SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public Builder addAllFixed32SPacked( - java.lang.Iterable values) { - ensureFixed32SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, fixed32SPacked_); - onChanged(); - return this; - } - /** - * repeated fixed32 fixed32sPacked = 76; - */ - public Builder clearFixed32SPacked() { - fixed32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000400); - onChanged(); - return this; - } - - private java.util.List fixed64SPacked_ = java.util.Collections.emptyList(); - private void ensureFixed64SPackedIsMutable() { - if (!((bitField1_ & 0x00000800) == 0x00000800)) { - fixed64SPacked_ = new java.util.ArrayList(fixed64SPacked_); - bitField1_ |= 0x00000800; - } - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public java.util.List - getFixed64SPackedList() { - return java.util.Collections.unmodifiableList(fixed64SPacked_); - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public int getFixed64SPackedCount() { - return fixed64SPacked_.size(); - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public long getFixed64SPacked(int index) { - return fixed64SPacked_.get(index); - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public Builder setFixed64SPacked( - int index, long value) { - ensureFixed64SPackedIsMutable(); - fixed64SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public Builder addFixed64SPacked(long value) { - ensureFixed64SPackedIsMutable(); - fixed64SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public Builder addAllFixed64SPacked( - java.lang.Iterable values) { - ensureFixed64SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, fixed64SPacked_); - onChanged(); - return this; - } - /** - * repeated fixed64 fixed64sPacked = 77; - */ - public Builder clearFixed64SPacked() { - fixed64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00000800); - onChanged(); - return this; - } - - private java.util.List sfixed32SPacked_ = java.util.Collections.emptyList(); - private void ensureSfixed32SPackedIsMutable() { - if (!((bitField1_ & 0x00001000) == 0x00001000)) { - sfixed32SPacked_ = new java.util.ArrayList(sfixed32SPacked_); - bitField1_ |= 0x00001000; - } - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public java.util.List - getSfixed32SPackedList() { - return java.util.Collections.unmodifiableList(sfixed32SPacked_); - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public int getSfixed32SPackedCount() { - return sfixed32SPacked_.size(); - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public int getSfixed32SPacked(int index) { - return sfixed32SPacked_.get(index); - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public Builder setSfixed32SPacked( - int index, int value) { - ensureSfixed32SPackedIsMutable(); - sfixed32SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public Builder addSfixed32SPacked(int value) { - ensureSfixed32SPackedIsMutable(); - sfixed32SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public Builder addAllSfixed32SPacked( - java.lang.Iterable values) { - ensureSfixed32SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sfixed32SPacked_); - onChanged(); - return this; - } - /** - * repeated sfixed32 sfixed32sPacked = 78; - */ - public Builder clearSfixed32SPacked() { - sfixed32SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00001000); - onChanged(); - return this; - } - - private java.util.List sfixed64SPacked_ = java.util.Collections.emptyList(); - private void ensureSfixed64SPackedIsMutable() { - if (!((bitField1_ & 0x00002000) == 0x00002000)) { - sfixed64SPacked_ = new java.util.ArrayList(sfixed64SPacked_); - bitField1_ |= 0x00002000; - } - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public java.util.List - getSfixed64SPackedList() { - return java.util.Collections.unmodifiableList(sfixed64SPacked_); - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public int getSfixed64SPackedCount() { - return sfixed64SPacked_.size(); - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public long getSfixed64SPacked(int index) { - return sfixed64SPacked_.get(index); - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public Builder setSfixed64SPacked( - int index, long value) { - ensureSfixed64SPackedIsMutable(); - sfixed64SPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public Builder addSfixed64SPacked(long value) { - ensureSfixed64SPackedIsMutable(); - sfixed64SPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public Builder addAllSfixed64SPacked( - java.lang.Iterable values) { - ensureSfixed64SPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sfixed64SPacked_); - onChanged(); - return this; - } - /** - * repeated sfixed64 sfixed64sPacked = 79; - */ - public Builder clearSfixed64SPacked() { - sfixed64SPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00002000); - onChanged(); - return this; - } - - private java.util.List floatsPacked_ = java.util.Collections.emptyList(); - private void ensureFloatsPackedIsMutable() { - if (!((bitField1_ & 0x00004000) == 0x00004000)) { - floatsPacked_ = new java.util.ArrayList(floatsPacked_); - bitField1_ |= 0x00004000; - } - } - /** - * repeated float floatsPacked = 80; - */ - public java.util.List - getFloatsPackedList() { - return java.util.Collections.unmodifiableList(floatsPacked_); - } - /** - * repeated float floatsPacked = 80; - */ - public int getFloatsPackedCount() { - return floatsPacked_.size(); - } - /** - * repeated float floatsPacked = 80; - */ - public float getFloatsPacked(int index) { - return floatsPacked_.get(index); - } - /** - * repeated float floatsPacked = 80; - */ - public Builder setFloatsPacked( - int index, float value) { - ensureFloatsPackedIsMutable(); - floatsPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated float floatsPacked = 80; - */ - public Builder addFloatsPacked(float value) { - ensureFloatsPackedIsMutable(); - floatsPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated float floatsPacked = 80; - */ - public Builder addAllFloatsPacked( - java.lang.Iterable values) { - ensureFloatsPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, floatsPacked_); - onChanged(); - return this; - } - /** - * repeated float floatsPacked = 80; - */ - public Builder clearFloatsPacked() { - floatsPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00004000); - onChanged(); - return this; - } - - private java.util.List doublesPacked_ = java.util.Collections.emptyList(); - private void ensureDoublesPackedIsMutable() { - if (!((bitField1_ & 0x00008000) == 0x00008000)) { - doublesPacked_ = new java.util.ArrayList(doublesPacked_); - bitField1_ |= 0x00008000; - } - } - /** - * repeated double doublesPacked = 81; - */ - public java.util.List - getDoublesPackedList() { - return java.util.Collections.unmodifiableList(doublesPacked_); - } - /** - * repeated double doublesPacked = 81; - */ - public int getDoublesPackedCount() { - return doublesPacked_.size(); - } - /** - * repeated double doublesPacked = 81; - */ - public double getDoublesPacked(int index) { - return doublesPacked_.get(index); - } - /** - * repeated double doublesPacked = 81; - */ - public Builder setDoublesPacked( - int index, double value) { - ensureDoublesPackedIsMutable(); - doublesPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated double doublesPacked = 81; - */ - public Builder addDoublesPacked(double value) { - ensureDoublesPackedIsMutable(); - doublesPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated double doublesPacked = 81; - */ - public Builder addAllDoublesPacked( - java.lang.Iterable values) { - ensureDoublesPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, doublesPacked_); - onChanged(); - return this; - } - /** - * repeated double doublesPacked = 81; - */ - public Builder clearDoublesPacked() { - doublesPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00008000); - onChanged(); - return this; - } - - private java.util.List boolsPacked_ = java.util.Collections.emptyList(); - private void ensureBoolsPackedIsMutable() { - if (!((bitField1_ & 0x00010000) == 0x00010000)) { - boolsPacked_ = new java.util.ArrayList(boolsPacked_); - bitField1_ |= 0x00010000; - } - } - /** - * repeated bool boolsPacked = 82; - */ - public java.util.List - getBoolsPackedList() { - return java.util.Collections.unmodifiableList(boolsPacked_); - } - /** - * repeated bool boolsPacked = 82; - */ - public int getBoolsPackedCount() { - return boolsPacked_.size(); - } - /** - * repeated bool boolsPacked = 82; - */ - public boolean getBoolsPacked(int index) { - return boolsPacked_.get(index); - } - /** - * repeated bool boolsPacked = 82; - */ - public Builder setBoolsPacked( - int index, boolean value) { - ensureBoolsPackedIsMutable(); - boolsPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated bool boolsPacked = 82; - */ - public Builder addBoolsPacked(boolean value) { - ensureBoolsPackedIsMutable(); - boolsPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated bool boolsPacked = 82; - */ - public Builder addAllBoolsPacked( - java.lang.Iterable values) { - ensureBoolsPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, boolsPacked_); - onChanged(); - return this; - } - /** - * repeated bool boolsPacked = 82; - */ - public Builder clearBoolsPacked() { - boolsPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00010000); - onChanged(); - return this; - } - - private java.util.List colorsPacked_ = - java.util.Collections.emptyList(); - private void ensureColorsPackedIsMutable() { - if (!((bitField1_ & 0x00020000) == 0x00020000)) { - colorsPacked_ = new java.util.ArrayList(colorsPacked_); - bitField1_ |= 0x00020000; - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public java.util.List getColorsPackedList() { - return new com.google.protobuf.Internal.ListAdapter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color>(colorsPacked_, colorsPacked_converter_); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public int getColorsPackedCount() { - return colorsPacked_.size(); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColorsPacked(int index) { - return colorsPacked_converter_.convert(colorsPacked_.get(index)); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder setColorsPacked( - int index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value) { - if (value == null) { - throw new NullPointerException(); - } - ensureColorsPackedIsMutable(); - colorsPacked_.set(index, value.getNumber()); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder addColorsPacked(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value) { - if (value == null) { - throw new NullPointerException(); - } - ensureColorsPackedIsMutable(); - colorsPacked_.add(value.getNumber()); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder addAllColorsPacked( - java.lang.Iterable values) { - ensureColorsPackedIsMutable(); - for (org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value : values) { - colorsPacked_.add(value.getNumber()); - } - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder clearColorsPacked() { - colorsPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00020000); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public java.util.List - getColorsPackedValueList() { - return java.util.Collections.unmodifiableList(colorsPacked_); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public int getColorsPackedValue(int index) { - return colorsPacked_.get(index); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder setColorsPackedValue( - int index, int value) { - ensureColorsPackedIsMutable(); - colorsPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder addColorsPackedValue(int value) { - ensureColorsPackedIsMutable(); - colorsPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsPacked = 83; - */ - public Builder addAllColorsPackedValue( - java.lang.Iterable values) { - ensureColorsPackedIsMutable(); - for (int value : values) { - colorsPacked_.add(value); - } - onChanged(); - return this; - } - - private java.util.List int32SNotPacked_ = java.util.Collections.emptyList(); - private void ensureInt32SNotPackedIsMutable() { - if (!((bitField1_ & 0x00040000) == 0x00040000)) { - int32SNotPacked_ = new java.util.ArrayList(int32SNotPacked_); - bitField1_ |= 0x00040000; - } - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public java.util.List - getInt32SNotPackedList() { - return java.util.Collections.unmodifiableList(int32SNotPacked_); - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public int getInt32SNotPackedCount() { - return int32SNotPacked_.size(); - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public int getInt32SNotPacked(int index) { - return int32SNotPacked_.get(index); - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public Builder setInt32SNotPacked( - int index, int value) { - ensureInt32SNotPackedIsMutable(); - int32SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public Builder addInt32SNotPacked(int value) { - ensureInt32SNotPackedIsMutable(); - int32SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public Builder addAllInt32SNotPacked( - java.lang.Iterable values) { - ensureInt32SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, int32SNotPacked_); - onChanged(); - return this; - } - /** - * repeated int32 int32sNotPacked = 90 [packed = false]; - */ - public Builder clearInt32SNotPacked() { - int32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00040000); - onChanged(); - return this; - } - - private java.util.List int64SNotPacked_ = java.util.Collections.emptyList(); - private void ensureInt64SNotPackedIsMutable() { - if (!((bitField1_ & 0x00080000) == 0x00080000)) { - int64SNotPacked_ = new java.util.ArrayList(int64SNotPacked_); - bitField1_ |= 0x00080000; - } - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public java.util.List - getInt64SNotPackedList() { - return java.util.Collections.unmodifiableList(int64SNotPacked_); - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public int getInt64SNotPackedCount() { - return int64SNotPacked_.size(); - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public long getInt64SNotPacked(int index) { - return int64SNotPacked_.get(index); - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public Builder setInt64SNotPacked( - int index, long value) { - ensureInt64SNotPackedIsMutable(); - int64SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public Builder addInt64SNotPacked(long value) { - ensureInt64SNotPackedIsMutable(); - int64SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public Builder addAllInt64SNotPacked( - java.lang.Iterable values) { - ensureInt64SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, int64SNotPacked_); - onChanged(); - return this; - } - /** - * repeated int64 int64sNotPacked = 91 [packed = false]; - */ - public Builder clearInt64SNotPacked() { - int64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00080000); - onChanged(); - return this; - } - - private java.util.List uint32SNotPacked_ = java.util.Collections.emptyList(); - private void ensureUint32SNotPackedIsMutable() { - if (!((bitField1_ & 0x00100000) == 0x00100000)) { - uint32SNotPacked_ = new java.util.ArrayList(uint32SNotPacked_); - bitField1_ |= 0x00100000; - } - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public java.util.List - getUint32SNotPackedList() { - return java.util.Collections.unmodifiableList(uint32SNotPacked_); - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public int getUint32SNotPackedCount() { - return uint32SNotPacked_.size(); - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public int getUint32SNotPacked(int index) { - return uint32SNotPacked_.get(index); - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public Builder setUint32SNotPacked( - int index, int value) { - ensureUint32SNotPackedIsMutable(); - uint32SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public Builder addUint32SNotPacked(int value) { - ensureUint32SNotPackedIsMutable(); - uint32SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public Builder addAllUint32SNotPacked( - java.lang.Iterable values) { - ensureUint32SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, uint32SNotPacked_); - onChanged(); - return this; - } - /** - * repeated uint32 uint32sNotPacked = 92 [packed = false]; - */ - public Builder clearUint32SNotPacked() { - uint32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00100000); - onChanged(); - return this; - } - - private java.util.List uint64SNotPacked_ = java.util.Collections.emptyList(); - private void ensureUint64SNotPackedIsMutable() { - if (!((bitField1_ & 0x00200000) == 0x00200000)) { - uint64SNotPacked_ = new java.util.ArrayList(uint64SNotPacked_); - bitField1_ |= 0x00200000; - } - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public java.util.List - getUint64SNotPackedList() { - return java.util.Collections.unmodifiableList(uint64SNotPacked_); - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public int getUint64SNotPackedCount() { - return uint64SNotPacked_.size(); - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public long getUint64SNotPacked(int index) { - return uint64SNotPacked_.get(index); - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public Builder setUint64SNotPacked( - int index, long value) { - ensureUint64SNotPackedIsMutable(); - uint64SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public Builder addUint64SNotPacked(long value) { - ensureUint64SNotPackedIsMutable(); - uint64SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public Builder addAllUint64SNotPacked( - java.lang.Iterable values) { - ensureUint64SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, uint64SNotPacked_); - onChanged(); - return this; - } - /** - * repeated uint64 uint64sNotPacked = 93 [packed = false]; - */ - public Builder clearUint64SNotPacked() { - uint64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00200000); - onChanged(); - return this; - } - - private java.util.List sint32SNotPacked_ = java.util.Collections.emptyList(); - private void ensureSint32SNotPackedIsMutable() { - if (!((bitField1_ & 0x00400000) == 0x00400000)) { - sint32SNotPacked_ = new java.util.ArrayList(sint32SNotPacked_); - bitField1_ |= 0x00400000; - } - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public java.util.List - getSint32SNotPackedList() { - return java.util.Collections.unmodifiableList(sint32SNotPacked_); - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public int getSint32SNotPackedCount() { - return sint32SNotPacked_.size(); - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public int getSint32SNotPacked(int index) { - return sint32SNotPacked_.get(index); - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public Builder setSint32SNotPacked( - int index, int value) { - ensureSint32SNotPackedIsMutable(); - sint32SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public Builder addSint32SNotPacked(int value) { - ensureSint32SNotPackedIsMutable(); - sint32SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public Builder addAllSint32SNotPacked( - java.lang.Iterable values) { - ensureSint32SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sint32SNotPacked_); - onChanged(); - return this; - } - /** - * repeated sint32 sint32sNotPacked = 94 [packed = false]; - */ - public Builder clearSint32SNotPacked() { - sint32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00400000); - onChanged(); - return this; - } - - private java.util.List sint64SNotPacked_ = java.util.Collections.emptyList(); - private void ensureSint64SNotPackedIsMutable() { - if (!((bitField1_ & 0x00800000) == 0x00800000)) { - sint64SNotPacked_ = new java.util.ArrayList(sint64SNotPacked_); - bitField1_ |= 0x00800000; - } - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public java.util.List - getSint64SNotPackedList() { - return java.util.Collections.unmodifiableList(sint64SNotPacked_); - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public int getSint64SNotPackedCount() { - return sint64SNotPacked_.size(); - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public long getSint64SNotPacked(int index) { - return sint64SNotPacked_.get(index); - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public Builder setSint64SNotPacked( - int index, long value) { - ensureSint64SNotPackedIsMutable(); - sint64SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public Builder addSint64SNotPacked(long value) { - ensureSint64SNotPackedIsMutable(); - sint64SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public Builder addAllSint64SNotPacked( - java.lang.Iterable values) { - ensureSint64SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sint64SNotPacked_); - onChanged(); - return this; - } - /** - * repeated sint64 sint64sNotPacked = 95 [packed = false]; - */ - public Builder clearSint64SNotPacked() { - sint64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x00800000); - onChanged(); - return this; - } - - private java.util.List fixed32SNotPacked_ = java.util.Collections.emptyList(); - private void ensureFixed32SNotPackedIsMutable() { - if (!((bitField1_ & 0x01000000) == 0x01000000)) { - fixed32SNotPacked_ = new java.util.ArrayList(fixed32SNotPacked_); - bitField1_ |= 0x01000000; - } - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public java.util.List - getFixed32SNotPackedList() { - return java.util.Collections.unmodifiableList(fixed32SNotPacked_); - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public int getFixed32SNotPackedCount() { - return fixed32SNotPacked_.size(); - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public int getFixed32SNotPacked(int index) { - return fixed32SNotPacked_.get(index); - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public Builder setFixed32SNotPacked( - int index, int value) { - ensureFixed32SNotPackedIsMutable(); - fixed32SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public Builder addFixed32SNotPacked(int value) { - ensureFixed32SNotPackedIsMutable(); - fixed32SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public Builder addAllFixed32SNotPacked( - java.lang.Iterable values) { - ensureFixed32SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, fixed32SNotPacked_); - onChanged(); - return this; - } - /** - * repeated fixed32 fixed32sNotPacked = 96 [packed = false]; - */ - public Builder clearFixed32SNotPacked() { - fixed32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x01000000); - onChanged(); - return this; - } - - private java.util.List fixed64SNotPacked_ = java.util.Collections.emptyList(); - private void ensureFixed64SNotPackedIsMutable() { - if (!((bitField1_ & 0x02000000) == 0x02000000)) { - fixed64SNotPacked_ = new java.util.ArrayList(fixed64SNotPacked_); - bitField1_ |= 0x02000000; - } - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public java.util.List - getFixed64SNotPackedList() { - return java.util.Collections.unmodifiableList(fixed64SNotPacked_); - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public int getFixed64SNotPackedCount() { - return fixed64SNotPacked_.size(); - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public long getFixed64SNotPacked(int index) { - return fixed64SNotPacked_.get(index); - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public Builder setFixed64SNotPacked( - int index, long value) { - ensureFixed64SNotPackedIsMutable(); - fixed64SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public Builder addFixed64SNotPacked(long value) { - ensureFixed64SNotPackedIsMutable(); - fixed64SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public Builder addAllFixed64SNotPacked( - java.lang.Iterable values) { - ensureFixed64SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, fixed64SNotPacked_); - onChanged(); - return this; - } - /** - * repeated fixed64 fixed64sNotPacked = 97 [packed = false]; - */ - public Builder clearFixed64SNotPacked() { - fixed64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x02000000); - onChanged(); - return this; - } - - private java.util.List sfixed32SNotPacked_ = java.util.Collections.emptyList(); - private void ensureSfixed32SNotPackedIsMutable() { - if (!((bitField1_ & 0x04000000) == 0x04000000)) { - sfixed32SNotPacked_ = new java.util.ArrayList(sfixed32SNotPacked_); - bitField1_ |= 0x04000000; - } - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public java.util.List - getSfixed32SNotPackedList() { - return java.util.Collections.unmodifiableList(sfixed32SNotPacked_); - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public int getSfixed32SNotPackedCount() { - return sfixed32SNotPacked_.size(); - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public int getSfixed32SNotPacked(int index) { - return sfixed32SNotPacked_.get(index); - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public Builder setSfixed32SNotPacked( - int index, int value) { - ensureSfixed32SNotPackedIsMutable(); - sfixed32SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public Builder addSfixed32SNotPacked(int value) { - ensureSfixed32SNotPackedIsMutable(); - sfixed32SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public Builder addAllSfixed32SNotPacked( - java.lang.Iterable values) { - ensureSfixed32SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sfixed32SNotPacked_); - onChanged(); - return this; - } - /** - * repeated sfixed32 sfixed32sNotPacked = 98 [packed = false]; - */ - public Builder clearSfixed32SNotPacked() { - sfixed32SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x04000000); - onChanged(); - return this; - } - - private java.util.List sfixed64SNotPacked_ = java.util.Collections.emptyList(); - private void ensureSfixed64SNotPackedIsMutable() { - if (!((bitField1_ & 0x08000000) == 0x08000000)) { - sfixed64SNotPacked_ = new java.util.ArrayList(sfixed64SNotPacked_); - bitField1_ |= 0x08000000; - } - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public java.util.List - getSfixed64SNotPackedList() { - return java.util.Collections.unmodifiableList(sfixed64SNotPacked_); - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public int getSfixed64SNotPackedCount() { - return sfixed64SNotPacked_.size(); - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public long getSfixed64SNotPacked(int index) { - return sfixed64SNotPacked_.get(index); - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public Builder setSfixed64SNotPacked( - int index, long value) { - ensureSfixed64SNotPackedIsMutable(); - sfixed64SNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public Builder addSfixed64SNotPacked(long value) { - ensureSfixed64SNotPackedIsMutable(); - sfixed64SNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public Builder addAllSfixed64SNotPacked( - java.lang.Iterable values) { - ensureSfixed64SNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, sfixed64SNotPacked_); - onChanged(); - return this; - } - /** - * repeated sfixed64 sfixed64sNotPacked = 99 [packed = false]; - */ - public Builder clearSfixed64SNotPacked() { - sfixed64SNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x08000000); - onChanged(); - return this; - } - - private java.util.List floatsNotPacked_ = java.util.Collections.emptyList(); - private void ensureFloatsNotPackedIsMutable() { - if (!((bitField1_ & 0x10000000) == 0x10000000)) { - floatsNotPacked_ = new java.util.ArrayList(floatsNotPacked_); - bitField1_ |= 0x10000000; - } - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public java.util.List - getFloatsNotPackedList() { - return java.util.Collections.unmodifiableList(floatsNotPacked_); - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public int getFloatsNotPackedCount() { - return floatsNotPacked_.size(); - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public float getFloatsNotPacked(int index) { - return floatsNotPacked_.get(index); - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public Builder setFloatsNotPacked( - int index, float value) { - ensureFloatsNotPackedIsMutable(); - floatsNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public Builder addFloatsNotPacked(float value) { - ensureFloatsNotPackedIsMutable(); - floatsNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public Builder addAllFloatsNotPacked( - java.lang.Iterable values) { - ensureFloatsNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, floatsNotPacked_); - onChanged(); - return this; - } - /** - * repeated float floatsNotPacked = 100 [packed = false]; - */ - public Builder clearFloatsNotPacked() { - floatsNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x10000000); - onChanged(); - return this; - } - - private java.util.List doublesNotPacked_ = java.util.Collections.emptyList(); - private void ensureDoublesNotPackedIsMutable() { - if (!((bitField1_ & 0x20000000) == 0x20000000)) { - doublesNotPacked_ = new java.util.ArrayList(doublesNotPacked_); - bitField1_ |= 0x20000000; - } - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public java.util.List - getDoublesNotPackedList() { - return java.util.Collections.unmodifiableList(doublesNotPacked_); - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public int getDoublesNotPackedCount() { - return doublesNotPacked_.size(); - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public double getDoublesNotPacked(int index) { - return doublesNotPacked_.get(index); - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public Builder setDoublesNotPacked( - int index, double value) { - ensureDoublesNotPackedIsMutable(); - doublesNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public Builder addDoublesNotPacked(double value) { - ensureDoublesNotPackedIsMutable(); - doublesNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public Builder addAllDoublesNotPacked( - java.lang.Iterable values) { - ensureDoublesNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, doublesNotPacked_); - onChanged(); - return this; - } - /** - * repeated double doublesNotPacked = 101 [packed = false]; - */ - public Builder clearDoublesNotPacked() { - doublesNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x20000000); - onChanged(); - return this; - } - - private java.util.List boolsNotPacked_ = java.util.Collections.emptyList(); - private void ensureBoolsNotPackedIsMutable() { - if (!((bitField1_ & 0x40000000) == 0x40000000)) { - boolsNotPacked_ = new java.util.ArrayList(boolsNotPacked_); - bitField1_ |= 0x40000000; - } - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public java.util.List - getBoolsNotPackedList() { - return java.util.Collections.unmodifiableList(boolsNotPacked_); - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public int getBoolsNotPackedCount() { - return boolsNotPacked_.size(); - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public boolean getBoolsNotPacked(int index) { - return boolsNotPacked_.get(index); - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public Builder setBoolsNotPacked( - int index, boolean value) { - ensureBoolsNotPackedIsMutable(); - boolsNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public Builder addBoolsNotPacked(boolean value) { - ensureBoolsNotPackedIsMutable(); - boolsNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public Builder addAllBoolsNotPacked( - java.lang.Iterable values) { - ensureBoolsNotPackedIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, boolsNotPacked_); - onChanged(); - return this; - } - /** - * repeated bool boolsNotPacked = 102 [packed = false]; - */ - public Builder clearBoolsNotPacked() { - boolsNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x40000000); - onChanged(); - return this; - } - - private java.util.List colorsNotPacked_ = - java.util.Collections.emptyList(); - private void ensureColorsNotPackedIsMutable() { - if (!((bitField1_ & 0x80000000) == 0x80000000)) { - colorsNotPacked_ = new java.util.ArrayList(colorsNotPacked_); - bitField1_ |= 0x80000000; - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public java.util.List getColorsNotPackedList() { - return new com.google.protobuf.Internal.ListAdapter< - java.lang.Integer, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color>(colorsNotPacked_, colorsNotPacked_converter_); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public int getColorsNotPackedCount() { - return colorsNotPacked_.size(); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color getColorsNotPacked(int index) { - return colorsNotPacked_converter_.convert(colorsNotPacked_.get(index)); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder setColorsNotPacked( - int index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value) { - if (value == null) { - throw new NullPointerException(); - } - ensureColorsNotPackedIsMutable(); - colorsNotPacked_.set(index, value.getNumber()); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder addColorsNotPacked(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value) { - if (value == null) { - throw new NullPointerException(); - } - ensureColorsNotPackedIsMutable(); - colorsNotPacked_.add(value.getNumber()); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder addAllColorsNotPacked( - java.lang.Iterable values) { - ensureColorsNotPackedIsMutable(); - for (org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color value : values) { - colorsNotPacked_.add(value.getNumber()); - } - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder clearColorsNotPacked() { - colorsNotPacked_ = java.util.Collections.emptyList(); - bitField1_ = (bitField1_ & ~0x80000000); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public java.util.List - getColorsNotPackedValueList() { - return java.util.Collections.unmodifiableList(colorsNotPacked_); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public int getColorsNotPackedValue(int index) { - return colorsNotPacked_.get(index); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder setColorsNotPackedValue( - int index, int value) { - ensureColorsNotPackedIsMutable(); - colorsNotPacked_.set(index, value); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder addColorsNotPackedValue(int value) { - ensureColorsNotPackedIsMutable(); - colorsNotPacked_.add(value); - onChanged(); - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.Color colorsNotPacked = 103 [packed = false]; - */ - public Builder addAllColorsNotPackedValue( - java.lang.Iterable values) { - ensureColorsNotPackedIsMutable(); - for (int value : values) { - colorsNotPacked_.add(value); - } - onChanged(); - return this; - } - - private com.google.protobuf.LazyStringList strings_ = com.google.protobuf.LazyStringArrayList.EMPTY; - private void ensureStringsIsMutable() { - if (!((bitField2_ & 0x00000001) == 0x00000001)) { - strings_ = new com.google.protobuf.LazyStringArrayList(strings_); - bitField2_ |= 0x00000001; - } - } - /** - * repeated string strings = 110; - */ - public com.google.protobuf.ProtocolStringList - getStringsList() { - return strings_.getUnmodifiableView(); - } - /** - * repeated string strings = 110; - */ - public int getStringsCount() { - return strings_.size(); - } - /** - * repeated string strings = 110; - */ - public java.lang.String getStrings(int index) { - return strings_.get(index); - } - /** - * repeated string strings = 110; - */ - public com.google.protobuf.ByteString - getStringsBytes(int index) { - return strings_.getByteString(index); - } - /** - * repeated string strings = 110; - */ - public Builder setStrings( - int index, java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - ensureStringsIsMutable(); - strings_.set(index, value); - onChanged(); - return this; - } - /** - * repeated string strings = 110; - */ - public Builder addStrings( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - ensureStringsIsMutable(); - strings_.add(value); - onChanged(); - return this; - } - /** - * repeated string strings = 110; - */ - public Builder addAllStrings( - java.lang.Iterable values) { - ensureStringsIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, strings_); - onChanged(); - return this; - } - /** - * repeated string strings = 110; - */ - public Builder clearStrings() { - strings_ = com.google.protobuf.LazyStringArrayList.EMPTY; - bitField2_ = (bitField2_ & ~0x00000001); - onChanged(); - return this; - } - /** - * repeated string strings = 110; - */ - public Builder addStringsBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - ensureStringsIsMutable(); - strings_.add(value); - onChanged(); - return this; - } - - private java.util.List bytess_ = java.util.Collections.emptyList(); - private void ensureBytessIsMutable() { - if (!((bitField2_ & 0x00000002) == 0x00000002)) { - bytess_ = new java.util.ArrayList(bytess_); - bitField2_ |= 0x00000002; - } - } - /** - * repeated bytes bytess = 111; - */ - public java.util.List - getBytessList() { - return java.util.Collections.unmodifiableList(bytess_); - } - /** - * repeated bytes bytess = 111; - */ - public int getBytessCount() { - return bytess_.size(); - } - /** - * repeated bytes bytess = 111; - */ - public com.google.protobuf.ByteString getBytess(int index) { - return bytess_.get(index); - } - /** - * repeated bytes bytess = 111; - */ - public Builder setBytess( - int index, com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - ensureBytessIsMutable(); - bytess_.set(index, value); - onChanged(); - return this; - } - /** - * repeated bytes bytess = 111; - */ - public Builder addBytess(com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - ensureBytessIsMutable(); - bytess_.add(value); - onChanged(); - return this; - } - /** - * repeated bytes bytess = 111; - */ - public Builder addAllBytess( - java.lang.Iterable values) { - ensureBytessIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, bytess_); - onChanged(); - return this; - } - /** - * repeated bytes bytess = 111; - */ - public Builder clearBytess() { - bytess_ = java.util.Collections.emptyList(); - bitField2_ = (bitField2_ & ~0x00000002); - onChanged(); - return this; - } - - private java.util.List users_ = - java.util.Collections.emptyList(); - private void ensureUsersIsMutable() { - if (!((bitField2_ & 0x00000004) == 0x00000004)) { - users_ = new java.util.ArrayList(users_); - bitField2_ |= 0x00000004; - } - } - - private com.google.protobuf.RepeatedFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder> usersBuilder_; - - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public java.util.List getUsersList() { - if (usersBuilder_ == null) { - return java.util.Collections.unmodifiableList(users_); - } else { - return usersBuilder_.getMessageList(); - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public int getUsersCount() { - if (usersBuilder_ == null) { - return users_.size(); - } else { - return usersBuilder_.getCount(); - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getUsers(int index) { - if (usersBuilder_ == null) { - return users_.get(index); - } else { - return usersBuilder_.getMessage(index); - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder setUsers( - int index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User value) { - if (usersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureUsersIsMutable(); - users_.set(index, value); - onChanged(); - } else { - usersBuilder_.setMessage(index, value); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder setUsers( - int index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder builderForValue) { - if (usersBuilder_ == null) { - ensureUsersIsMutable(); - users_.set(index, builderForValue.build()); - onChanged(); - } else { - usersBuilder_.setMessage(index, builderForValue.build()); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder addUsers(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User value) { - if (usersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureUsersIsMutable(); - users_.add(value); - onChanged(); - } else { - usersBuilder_.addMessage(value); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder addUsers( - int index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User value) { - if (usersBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - ensureUsersIsMutable(); - users_.add(index, value); - onChanged(); - } else { - usersBuilder_.addMessage(index, value); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder addUsers( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder builderForValue) { - if (usersBuilder_ == null) { - ensureUsersIsMutable(); - users_.add(builderForValue.build()); - onChanged(); - } else { - usersBuilder_.addMessage(builderForValue.build()); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder addUsers( - int index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder builderForValue) { - if (usersBuilder_ == null) { - ensureUsersIsMutable(); - users_.add(index, builderForValue.build()); - onChanged(); - } else { - usersBuilder_.addMessage(index, builderForValue.build()); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder addAllUsers( - java.lang.Iterable values) { - if (usersBuilder_ == null) { - ensureUsersIsMutable(); - com.google.protobuf.AbstractMessageLite.Builder.addAll( - values, users_); - onChanged(); - } else { - usersBuilder_.addAllMessages(values); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder clearUsers() { - if (usersBuilder_ == null) { - users_ = java.util.Collections.emptyList(); - bitField2_ = (bitField2_ & ~0x00000004); - onChanged(); - } else { - usersBuilder_.clear(); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public Builder removeUsers(int index) { - if (usersBuilder_ == null) { - ensureUsersIsMutable(); - users_.remove(index); - onChanged(); - } else { - usersBuilder_.remove(index); - } - return this; - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder getUsersBuilder( - int index) { - return getUsersFieldBuilder().getBuilder(index); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder getUsersOrBuilder( - int index) { - if (usersBuilder_ == null) { - return users_.get(index); } else { - return usersBuilder_.getMessageOrBuilder(index); - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public java.util.List - getUsersOrBuilderList() { - if (usersBuilder_ != null) { - return usersBuilder_.getMessageOrBuilderList(); - } else { - return java.util.Collections.unmodifiableList(users_); - } - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder addUsersBuilder() { - return getUsersFieldBuilder().addBuilder( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance()); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder addUsersBuilder( - int index) { - return getUsersFieldBuilder().addBuilder( - index, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance()); - } - /** - * repeated .org.apache.servicecomb.foundation.protobuf.internal.model.User users = 112; - */ - public java.util.List - getUsersBuilderList() { - return getUsersFieldBuilder().getBuilderList(); - } - private com.google.protobuf.RepeatedFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder> - getUsersFieldBuilder() { - if (usersBuilder_ == null) { - usersBuilder_ = new com.google.protobuf.RepeatedFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder>( - users_, - ((bitField2_ & 0x00000004) == 0x00000004), - getParentForChildren(), - isClean()); - users_ = null; - } - return usersBuilder_; - } - @java.lang.Override - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.setUnknownFieldsProto3(unknownFields); - } - - @java.lang.Override - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.mergeUnknownFields(unknownFields); - } - - - // @@protoc_insertion_point(builder_scope:org.apache.servicecomb.foundation.protobuf.internal.model.Root) - } - - // @@protoc_insertion_point(class_scope:org.apache.servicecomb.foundation.protobuf.internal.model.Root) - private static final org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root(); - } - - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public Root parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new Root(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - - } - - public interface UserOrBuilder extends - // @@protoc_insertion_point(interface_extends:org.apache.servicecomb.foundation.protobuf.internal.model.User) - com.google.protobuf.MessageOrBuilder { - - /** - * string name = 1; - */ - java.lang.String getName(); - /** - * string name = 1; - */ - com.google.protobuf.ByteString - getNameBytes(); - - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - boolean hasTypeRecursive(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getTypeRecursive(); - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder getTypeRecursiveOrBuilder(); - } - /** - * Protobuf type {@code org.apache.servicecomb.foundation.protobuf.internal.model.User} - */ - public static final class User extends - com.google.protobuf.GeneratedMessageV3 implements - // @@protoc_insertion_point(message_implements:org.apache.servicecomb.foundation.protobuf.internal.model.User) - UserOrBuilder { - private static final long serialVersionUID = 0L; - // Use User.newBuilder() to construct. - private User(com.google.protobuf.GeneratedMessageV3.Builder builder) { - super(builder); - } - private User() { - name_ = ""; - } - - @java.lang.Override - public final com.google.protobuf.UnknownFieldSet - getUnknownFields() { - return this.unknownFields; - } - private User( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - this(); - if (extensionRegistry == null) { - throw new java.lang.NullPointerException(); - } - int mutable_bitField0_ = 0; - com.google.protobuf.UnknownFieldSet.Builder unknownFields = - com.google.protobuf.UnknownFieldSet.newBuilder(); - try { - boolean done = false; - while (!done) { - int tag = input.readTag(); - switch (tag) { - case 0: - done = true; - break; - case 10: { - java.lang.String s = input.readStringRequireUtf8(); - - name_ = s; - break; - } - case 18: { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder subBuilder = null; - if (typeRecursive_ != null) { - subBuilder = typeRecursive_.toBuilder(); - } - typeRecursive_ = input.readMessage(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.parser(), extensionRegistry); - if (subBuilder != null) { - subBuilder.mergeFrom(typeRecursive_); - typeRecursive_ = subBuilder.buildPartial(); - } - - break; - } - default: { - if (!parseUnknownFieldProto3( - input, unknownFields, extensionRegistry, tag)) { - done = true; - } - break; - } - } - } - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - throw e.setUnfinishedMessage(this); - } catch (java.io.IOException e) { - throw new com.google.protobuf.InvalidProtocolBufferException( - e).setUnfinishedMessage(this); - } finally { - this.unknownFields = unknownFields.build(); - makeExtensionsImmutable(); - } - } - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.class, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder.class); - } - - public static final int NAME_FIELD_NUMBER = 1; - private volatile java.lang.Object name_; - /** - * string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - return (java.lang.String) ref; - } else { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } - } - /** - * string name = 1; - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof java.lang.String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - - public static final int TYPERECURSIVE_FIELD_NUMBER = 2; - private org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root typeRecursive_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public boolean hasTypeRecursive() { - return typeRecursive_ != null; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getTypeRecursive() { - return typeRecursive_ == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance() : typeRecursive_; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder getTypeRecursiveOrBuilder() { - return getTypeRecursive(); - } - - private byte memoizedIsInitialized = -1; - @java.lang.Override - public final boolean isInitialized() { - byte isInitialized = memoizedIsInitialized; - if (isInitialized == 1) return true; - if (isInitialized == 0) return false; - - memoizedIsInitialized = 1; - return true; - } - - @java.lang.Override - public void writeTo(com.google.protobuf.CodedOutputStream output) - throws java.io.IOException { - if (!getNameBytes().isEmpty()) { - com.google.protobuf.GeneratedMessageV3.writeString(output, 1, name_); - } - if (typeRecursive_ != null) { - output.writeMessage(2, getTypeRecursive()); - } - unknownFields.writeTo(output); - } - - @java.lang.Override - public int getSerializedSize() { - int size = memoizedSize; - if (size != -1) return size; - - size = 0; - if (!getNameBytes().isEmpty()) { - size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, name_); - } - if (typeRecursive_ != null) { - size += com.google.protobuf.CodedOutputStream - .computeMessageSize(2, getTypeRecursive()); - } - size += unknownFields.getSerializedSize(); - memoizedSize = size; - return size; - } - - @java.lang.Override - public boolean equals(final java.lang.Object obj) { - if (obj == this) { - return true; - } - if (!(obj instanceof org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User)) { - return super.equals(obj); - } - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User other = (org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User) obj; - - boolean result = true; - result = result && getName() - .equals(other.getName()); - result = result && (hasTypeRecursive() == other.hasTypeRecursive()); - if (hasTypeRecursive()) { - result = result && getTypeRecursive() - .equals(other.getTypeRecursive()); - } - result = result && unknownFields.equals(other.unknownFields); - return result; - } - - @java.lang.Override - public int hashCode() { - if (memoizedHashCode != 0) { - return memoizedHashCode; - } - int hash = 41; - hash = (19 * hash) + getDescriptor().hashCode(); - hash = (37 * hash) + NAME_FIELD_NUMBER; - hash = (53 * hash) + getName().hashCode(); - if (hasTypeRecursive()) { - hash = (37 * hash) + TYPERECURSIVE_FIELD_NUMBER; - hash = (53 * hash) + getTypeRecursive().hashCode(); - } - hash = (29 * hash) + unknownFields.hashCode(); - memoizedHashCode = hash; - return hash; - } - - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - java.nio.ByteBuffer data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - java.nio.ByteBuffer data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - com.google.protobuf.ByteString data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - com.google.protobuf.ByteString data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom(byte[] data) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - byte[] data, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return PARSER.parseFrom(data, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseDelimitedFrom(java.io.InputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseDelimitedFrom( - java.io.InputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseDelimitedWithIOException(PARSER, input, extensionRegistry); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - com.google.protobuf.CodedInputStream input) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input); - } - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parseFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - return com.google.protobuf.GeneratedMessageV3 - .parseWithIOException(PARSER, input, extensionRegistry); - } - - @java.lang.Override - public Builder newBuilderForType() { return newBuilder(); } - public static Builder newBuilder() { - return DEFAULT_INSTANCE.toBuilder(); - } - public static Builder newBuilder(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User prototype) { - return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); - } - @java.lang.Override - public Builder toBuilder() { - return this == DEFAULT_INSTANCE - ? new Builder() : new Builder().mergeFrom(this); - } - - @java.lang.Override - protected Builder newBuilderForType( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - Builder builder = new Builder(parent); - return builder; - } - /** - * Protobuf type {@code org.apache.servicecomb.foundation.protobuf.internal.model.User} - */ - public static final class Builder extends - com.google.protobuf.GeneratedMessageV3.Builder implements - // @@protoc_insertion_point(builder_implements:org.apache.servicecomb.foundation.protobuf.internal.model.User) - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.UserOrBuilder { - public static final com.google.protobuf.Descriptors.Descriptor - getDescriptor() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_descriptor; - } - - @java.lang.Override - protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internalGetFieldAccessorTable() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_fieldAccessorTable - .ensureFieldAccessorsInitialized( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.class, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.Builder.class); - } - - // Construct using org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.newBuilder() - private Builder() { - maybeForceBuilderInitialization(); - } - - private Builder( - com.google.protobuf.GeneratedMessageV3.BuilderParent parent) { - super(parent); - maybeForceBuilderInitialization(); - } - private void maybeForceBuilderInitialization() { - if (com.google.protobuf.GeneratedMessageV3 - .alwaysUseFieldBuilders) { - } - } - @java.lang.Override - public Builder clear() { - super.clear(); - name_ = ""; - - if (typeRecursiveBuilder_ == null) { - typeRecursive_ = null; - } else { - typeRecursive_ = null; - typeRecursiveBuilder_ = null; - } - return this; - } - - @java.lang.Override - public com.google.protobuf.Descriptors.Descriptor - getDescriptorForType() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_descriptor; - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getDefaultInstanceForType() { - return org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance(); - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User build() { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User result = buildPartial(); - if (!result.isInitialized()) { - throw newUninitializedMessageException(result); - } - return result; - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User buildPartial() { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User result = new org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User(this); - result.name_ = name_; - if (typeRecursiveBuilder_ == null) { - result.typeRecursive_ = typeRecursive_; - } else { - result.typeRecursive_ = typeRecursiveBuilder_.build(); - } - onBuilt(); - return result; - } - - @java.lang.Override - public Builder clone() { - return (Builder) super.clone(); - } - @java.lang.Override - public Builder setField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { - return (Builder) super.setField(field, value); - } - @java.lang.Override - public Builder clearField( - com.google.protobuf.Descriptors.FieldDescriptor field) { - return (Builder) super.clearField(field); - } - @java.lang.Override - public Builder clearOneof( - com.google.protobuf.Descriptors.OneofDescriptor oneof) { - return (Builder) super.clearOneof(oneof); - } - @java.lang.Override - public Builder setRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - int index, java.lang.Object value) { - return (Builder) super.setRepeatedField(field, index, value); - } - @java.lang.Override - public Builder addRepeatedField( - com.google.protobuf.Descriptors.FieldDescriptor field, - java.lang.Object value) { - return (Builder) super.addRepeatedField(field, value); - } - @java.lang.Override - public Builder mergeFrom(com.google.protobuf.Message other) { - if (other instanceof org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User) { - return mergeFrom((org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User)other); - } else { - super.mergeFrom(other); - return this; - } - } - - public Builder mergeFrom(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User other) { - if (other == org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User.getDefaultInstance()) return this; - if (!other.getName().isEmpty()) { - name_ = other.name_; - onChanged(); - } - if (other.hasTypeRecursive()) { - mergeTypeRecursive(other.getTypeRecursive()); - } - this.mergeUnknownFields(other.unknownFields); - onChanged(); - return this; - } - - @java.lang.Override - public final boolean isInitialized() { - return true; - } - - @java.lang.Override - public Builder mergeFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws java.io.IOException { - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User parsedMessage = null; - try { - parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); - } catch (com.google.protobuf.InvalidProtocolBufferException e) { - parsedMessage = (org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User) e.getUnfinishedMessage(); - throw e.unwrapIOException(); - } finally { - if (parsedMessage != null) { - mergeFrom(parsedMessage); - } - } - return this; - } - - private java.lang.Object name_ = ""; - /** - * string name = 1; - */ - public java.lang.String getName() { - java.lang.Object ref = name_; - if (!(ref instanceof java.lang.String)) { - com.google.protobuf.ByteString bs = - (com.google.protobuf.ByteString) ref; - java.lang.String s = bs.toStringUtf8(); - name_ = s; - return s; - } else { - return (java.lang.String) ref; - } - } - /** - * string name = 1; - */ - public com.google.protobuf.ByteString - getNameBytes() { - java.lang.Object ref = name_; - if (ref instanceof String) { - com.google.protobuf.ByteString b = - com.google.protobuf.ByteString.copyFromUtf8( - (java.lang.String) ref); - name_ = b; - return b; - } else { - return (com.google.protobuf.ByteString) ref; - } - } - /** - * string name = 1; - */ - public Builder setName( - java.lang.String value) { - if (value == null) { - throw new NullPointerException(); - } - - name_ = value; - onChanged(); - return this; - } - /** - * string name = 1; - */ - public Builder clearName() { - - name_ = getDefaultInstance().getName(); - onChanged(); - return this; - } - /** - * string name = 1; - */ - public Builder setNameBytes( - com.google.protobuf.ByteString value) { - if (value == null) { - throw new NullPointerException(); - } - checkByteStringIsUtf8(value); - - name_ = value; - onChanged(); - return this; - } - - private org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root typeRecursive_ = null; - private com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder> typeRecursiveBuilder_; - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public boolean hasTypeRecursive() { - return typeRecursiveBuilder_ != null || typeRecursive_ != null; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root getTypeRecursive() { - if (typeRecursiveBuilder_ == null) { - return typeRecursive_ == null ? org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance() : typeRecursive_; - } else { - return typeRecursiveBuilder_.getMessage(); - } - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public Builder setTypeRecursive(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root value) { - if (typeRecursiveBuilder_ == null) { - if (value == null) { - throw new NullPointerException(); - } - typeRecursive_ = value; - onChanged(); - } else { - typeRecursiveBuilder_.setMessage(value); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public Builder setTypeRecursive( - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder builderForValue) { - if (typeRecursiveBuilder_ == null) { - typeRecursive_ = builderForValue.build(); - onChanged(); - } else { - typeRecursiveBuilder_.setMessage(builderForValue.build()); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public Builder mergeTypeRecursive(org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root value) { - if (typeRecursiveBuilder_ == null) { - if (typeRecursive_ != null) { - typeRecursive_ = - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.newBuilder(typeRecursive_).mergeFrom(value).buildPartial(); - } else { - typeRecursive_ = value; - } - onChanged(); - } else { - typeRecursiveBuilder_.mergeFrom(value); - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public Builder clearTypeRecursive() { - if (typeRecursiveBuilder_ == null) { - typeRecursive_ = null; - onChanged(); - } else { - typeRecursive_ = null; - typeRecursiveBuilder_ = null; - } - - return this; - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder getTypeRecursiveBuilder() { - - onChanged(); - return getTypeRecursiveFieldBuilder().getBuilder(); - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder getTypeRecursiveOrBuilder() { - if (typeRecursiveBuilder_ != null) { - return typeRecursiveBuilder_.getMessageOrBuilder(); - } else { - return typeRecursive_ == null ? - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.getDefaultInstance() : typeRecursive_; - } - } - /** - * .org.apache.servicecomb.foundation.protobuf.internal.model.Root typeRecursive = 2; - */ - private com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder> - getTypeRecursiveFieldBuilder() { - if (typeRecursiveBuilder_ == null) { - typeRecursiveBuilder_ = new com.google.protobuf.SingleFieldBuilderV3< - org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Root.Builder, org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.RootOrBuilder>( - getTypeRecursive(), - getParentForChildren(), - isClean()); - typeRecursive_ = null; - } - return typeRecursiveBuilder_; - } - @java.lang.Override - public final Builder setUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.setUnknownFieldsProto3(unknownFields); - } - - @java.lang.Override - public final Builder mergeUnknownFields( - final com.google.protobuf.UnknownFieldSet unknownFields) { - return super.mergeUnknownFields(unknownFields); - } - - - // @@protoc_insertion_point(builder_scope:org.apache.servicecomb.foundation.protobuf.internal.model.User) - } - - // @@protoc_insertion_point(class_scope:org.apache.servicecomb.foundation.protobuf.internal.model.User) - private static final org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User DEFAULT_INSTANCE; - static { - DEFAULT_INSTANCE = new org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User(); - } - - public static org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getDefaultInstance() { - return DEFAULT_INSTANCE; - } - - private static final com.google.protobuf.Parser - PARSER = new com.google.protobuf.AbstractParser() { - @java.lang.Override - public User parsePartialFrom( - com.google.protobuf.CodedInputStream input, - com.google.protobuf.ExtensionRegistryLite extensionRegistry) - throws com.google.protobuf.InvalidProtocolBufferException { - return new User(input, extensionRegistry); - } - }; - - public static com.google.protobuf.Parser parser() { - return PARSER; - } - - @java.lang.Override - public com.google.protobuf.Parser getParserForType() { - return PARSER; - } - - @java.lang.Override - public org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.User getDefaultInstanceForType() { - return DEFAULT_INSTANCE; - } - - } - - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SsMapEntry_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SsMapEntry_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_Sint32MapEntry_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_Sint32MapEntry_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SpMapEntry_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SpMapEntry_fieldAccessorTable; - private static final com.google.protobuf.Descriptors.Descriptor - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_descriptor; - private static final - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_fieldAccessorTable; - - public static com.google.protobuf.Descriptors.FileDescriptor - getDescriptor() { - return descriptor; - } - private static com.google.protobuf.Descriptors.FileDescriptor - descriptor; - static { - java.lang.String[] descriptorData = { - "\n\022protobufRoot.proto\0229org.apache.service" + - "comb.foundation.protobuf.internal.model\032" + - "\031google/protobuf/any.proto\"\204\022\n\004Root\022\r\n\005i" + - "nt32\030\001 \001(\005\022\r\n\005int64\030\002 \001(\003\022\016\n\006uint32\030\003 \001(" + - "\r\022\016\n\006uint64\030\004 \001(\004\022\016\n\006sint32\030\005 \001(\021\022\016\n\006sin" + - "t64\030\006 \001(\022\022\017\n\007fixed32\030\007 \001(\007\022\017\n\007fixed64\030\010 " + - "\001(\006\022\020\n\010sfixed32\030\t \001(\017\022\020\n\010sfixed64\030\n \001(\020\022" + - "\022\n\nfloatValue\030\013 \001(\002\022\023\n\013doubleValue\030\014 \001(\001" + - "\022\014\n\004bool\030\r \001(\010\022\020\n\010objInt32\030\024 \001(\005\022\020\n\010objI" + - "nt64\030\025 \001(\003\022\021\n\tobjUint32\030\026 \001(\r\022\021\n\tobjUint" + - "64\030\027 \001(\004\022\021\n\tobjSint32\030\030 \001(\021\022\021\n\tobjSint64" + - "\030\031 \001(\022\022\022\n\nobjFixed32\030\032 \001(\007\022\022\n\nobjFixed64" + - "\030\033 \001(\006\022\023\n\013objSfixed32\030\034 \001(\017\022\023\n\013objSfixed" + - "64\030\035 \001(\020\022\025\n\robjFloatValue\030\036 \001(\002\022\026\n\016objDo" + - "ubleValue\030\037 \001(\001\022\017\n\007objBool\030 \001(\010\022\016\n\006stri" + - "ng\030( \001(\t\022\r\n\005bytes\030) \001(\014\022O\n\005color\030* \001(\0162@" + - ".org.apache.servicecomb.foundation.proto" + - "buf.internal.model.Color\022M\n\004user\030+ \001(\0132?" + - ".org.apache.servicecomb.foundation.proto" + - "buf.internal.model.User\022V\n\rtypeRecursive" + - "\030, \001(\0132?.org.apache.servicecomb.foundati" + - "on.protobuf.internal.model.Root\022!\n\003any\0302" + - " \001(\0132\024.google.protobuf.Any\022\"\n\004anys\0303 \003(\013" + - "2\024.google.protobuf.Any\022Y\n\005ssMap\030< \003(\0132J." + - "org.apache.servicecomb.foundation.protob" + - "uf.internal.model.Root.SsMapEntry\022a\n\tsin" + - "t32Map\030= \003(\0132N.org.apache.servicecomb.fo" + - "undation.protobuf.internal.model.Root.Si" + - "nt32MapEntry\022Y\n\005spMap\030> \003(\0132J.org.apache" + - ".servicecomb.foundation.protobuf.interna" + - "l.model.Root.SpMapEntry\022\024\n\014int32sPacked\030" + - "F \003(\005\022\024\n\014int64sPacked\030G \003(\003\022\025\n\ruint32sPa" + - "cked\030H \003(\r\022\025\n\ruint64sPacked\030I \003(\004\022\025\n\rsin" + - "t32sPacked\030J \003(\021\022\025\n\rsint64sPacked\030K \003(\022\022" + - "\026\n\016fixed32sPacked\030L \003(\007\022\026\n\016fixed64sPacke" + - "d\030M \003(\006\022\027\n\017sfixed32sPacked\030N \003(\017\022\027\n\017sfix" + - "ed64sPacked\030O \003(\020\022\024\n\014floatsPacked\030P \003(\002\022" + - "\025\n\rdoublesPacked\030Q \003(\001\022\023\n\013boolsPacked\030R " + - "\003(\010\022V\n\014colorsPacked\030S \003(\0162@.org.apache.s" + - "ervicecomb.foundation.protobuf.internal." + - "model.Color\022\033\n\017int32sNotPacked\030Z \003(\005B\002\020\000" + - "\022\033\n\017int64sNotPacked\030[ \003(\003B\002\020\000\022\034\n\020uint32s" + - "NotPacked\030\\ \003(\rB\002\020\000\022\034\n\020uint64sNotPacked\030" + - "] \003(\004B\002\020\000\022\034\n\020sint32sNotPacked\030^ \003(\021B\002\020\000\022" + - "\034\n\020sint64sNotPacked\030_ \003(\022B\002\020\000\022\035\n\021fixed32" + - "sNotPacked\030` \003(\007B\002\020\000\022\035\n\021fixed64sNotPacke" + - "d\030a \003(\006B\002\020\000\022\036\n\022sfixed32sNotPacked\030b \003(\017B" + - "\002\020\000\022\036\n\022sfixed64sNotPacked\030c \003(\020B\002\020\000\022\033\n\017f" + - "loatsNotPacked\030d \003(\002B\002\020\000\022\034\n\020doublesNotPa" + - "cked\030e \003(\001B\002\020\000\022\032\n\016boolsNotPacked\030f \003(\010B\002" + - "\020\000\022]\n\017colorsNotPacked\030g \003(\0162@.org.apache" + - ".servicecomb.foundation.protobuf.interna" + - "l.model.ColorB\002\020\000\022\017\n\007strings\030n \003(\t\022\016\n\006by" + - "tess\030o \003(\014\022N\n\005users\030p \003(\0132?.org.apache.s" + - "ervicecomb.foundation.protobuf.internal." + - "model.User\032,\n\nSsMapEntry\022\013\n\003key\030\001 \001(\t\022\r\n" + - "\005value\030\002 \001(\t:\0028\001\0320\n\016Sint32MapEntry\022\013\n\003ke" + - "y\030\001 \001(\t\022\r\n\005value\030\002 \001(\005:\0028\001\032m\n\nSpMapEntry" + - "\022\013\n\003key\030\001 \001(\t\022N\n\005value\030\002 \001(\0132?.org.apach" + - "e.servicecomb.foundation.protobuf.intern" + - "al.model.User:\0028\001\"l\n\004User\022\014\n\004name\030\001 \001(\t\022" + - "V\n\rtypeRecursive\030\002 \001(\0132?.org.apache.serv" + - "icecomb.foundation.protobuf.internal.mod" + - "el.Root*&\n\005Color\022\007\n\003RED\020\000\022\n\n\006YELLOW\020\001\022\010\n" + - "\004BLUE\020\002b\006proto3" - }; - com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = - new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { - public com.google.protobuf.ExtensionRegistry assignDescriptors( - com.google.protobuf.Descriptors.FileDescriptor root) { - descriptor = root; - return null; - } - }; - com.google.protobuf.Descriptors.FileDescriptor - .internalBuildGeneratedFileFrom(descriptorData, - new com.google.protobuf.Descriptors.FileDescriptor[] { - com.google.protobuf.AnyProto.getDescriptor(), - }, assigner); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor = - getDescriptor().getMessageTypes().get(0); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor, - new java.lang.String[] { "Int32", "Int64", "Uint32", "Uint64", "Sint32", "Sint64", "Fixed32", "Fixed64", "Sfixed32", "Sfixed64", "FloatValue", "DoubleValue", "Bool", "ObjInt32", "ObjInt64", "ObjUint32", "ObjUint64", "ObjSint32", "ObjSint64", "ObjFixed32", "ObjFixed64", "ObjSfixed32", "ObjSfixed64", "ObjFloatValue", "ObjDoubleValue", "ObjBool", "String", "Bytes", "Color", "User", "TypeRecursive", "Any", "Anys", "SsMap", "Sint32Map", "SpMap", "Int32SPacked", "Int64SPacked", "Uint32SPacked", "Uint64SPacked", "Sint32SPacked", "Sint64SPacked", "Fixed32SPacked", "Fixed64SPacked", "Sfixed32SPacked", "Sfixed64SPacked", "FloatsPacked", "DoublesPacked", "BoolsPacked", "ColorsPacked", "Int32SNotPacked", "Int64SNotPacked", "Uint32SNotPacked", "Uint64SNotPacked", "Sint32SNotPacked", "Sint64SNotPacked", "Fixed32SNotPacked", "Fixed64SNotPacked", "Sfixed32SNotPacked", "Sfixed64SNotPacked", "FloatsNotPacked", "DoublesNotPacked", "BoolsNotPacked", "ColorsNotPacked", "Strings", "Bytess", "Users", }); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SsMapEntry_descriptor = - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor.getNestedTypes().get(0); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SsMapEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SsMapEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_Sint32MapEntry_descriptor = - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor.getNestedTypes().get(1); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_Sint32MapEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_Sint32MapEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SpMapEntry_descriptor = - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_descriptor.getNestedTypes().get(2); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SpMapEntry_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_Root_SpMapEntry_descriptor, - new java.lang.String[] { "Key", "Value", }); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_descriptor = - getDescriptor().getMessageTypes().get(1); - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_fieldAccessorTable = new - com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( - internal_static_org_apache_servicecomb_foundation_protobuf_internal_model_User_descriptor, - new java.lang.String[] { "Name", "TypeRecursive", }); - com.google.protobuf.AnyProto.getDescriptor(); - } - - // @@protoc_insertion_point(outer_class_scope) -} diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/parser/TestProtoParser.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/parser/TestProtoParser.java index 0f3bb4b2674..268281b9104 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/parser/TestProtoParser.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/parser/TestProtoParser.java @@ -16,18 +16,16 @@ */ package org.apache.servicecomb.foundation.protobuf.internal.parser; +import com.google.common.base.MoreObjects; +import io.protostuff.compiler.model.Proto; +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; -import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Test; - -import com.google.common.base.MoreObjects; - -import io.protostuff.compiler.model.Proto; - public class TestProtoParser { @Test public void parse() throws IOException { @@ -38,10 +36,10 @@ public void parse() throws IOException { Proto protoFromContent = parser.parseFromContent(content); Proto protoFromName = parser.parse("protobufRoot.proto"); - Assert.assertNotNull(protoFromContent.getMessage("Root")); - Assert.assertNotNull(protoFromContent.getMessage("User")); + Assertions.assertNotNull(protoFromContent.getMessage("Root")); + Assertions.assertNotNull(protoFromContent.getMessage("User")); - Assert.assertEquals(MoreObjects.toStringHelper(protoFromContent) + Assertions.assertEquals(MoreObjects.toStringHelper(protoFromContent) .omitNullValues() .add("messages", protoFromContent.getMessages()) .toString(), diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java index 441bf2f7c7c..8bcbddd9d30 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestAnySchema.java @@ -26,18 +26,19 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot; import org.apache.servicecomb.foundation.protobuf.internal.model.Root; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; import com.google.protobuf.Any; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestAnySchema extends TestSchemaBase { @Test public void empty() throws Throwable { scbMap = new HashMap<>(); scbMap.put("any", null); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); } @Test @@ -55,7 +56,7 @@ public void anys_json() throws IOException { scbRootBytes = rootSerializer.serialize(root); root = rootDeserializer.deserialize(scbRootBytes); - Assert.assertThat(root.getAnys(), Matchers.contains("abc", "123")); + MatcherAssert.assertThat(root.getAnys(), Matchers.contains("abc", "123")); } @Test @@ -68,7 +69,7 @@ public void pack() throws Throwable { map.put("name", "n1"); Root root = new Root(); root.setAny(map); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(root)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(root)); } @SuppressWarnings("unchecked") @@ -81,12 +82,12 @@ public void json_fromMapWithoutType() throws Throwable { scbRootBytes = rootSerializer.serialize(root); root = rootDeserializer.deserialize(scbRootBytes); - Assert.assertThat(root.getAny(), Matchers.instanceOf(Map.class)); - Assert.assertThat((Map) root.getAny(), Matchers.hasEntry("name", "n1")); + MatcherAssert.assertThat(root.getAny(), Matchers.instanceOf(Map.class)); + MatcherAssert.assertThat((Map) root.getAny(), Matchers.hasEntry("name", "n1")); RootDeserializer> deserializer = protoMapper.createRootDeserializer("Root", Map.class); map = deserializer.deserialize(scbRootBytes); - Assert.assertThat((Map) map.get("any"), Matchers.hasEntry("name", "n1")); + MatcherAssert.assertThat((Map) map.get("any"), Matchers.hasEntry("name", "n1")); } @Test @@ -96,6 +97,6 @@ public void json() throws Throwable { scbRootBytes = rootSerializer.serialize(root); root = rootDeserializer.deserialize(scbRootBytes); - Assert.assertEquals("abc", root.getAny()); + Assertions.assertEquals("abc", root.getAny()); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMapSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMapSchema.java index cdd9e524600..1013f3a6cf8 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMapSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMapSchema.java @@ -21,7 +21,7 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot; -import org.junit.Test; +import org.junit.jupiter.api.Test; public class TestMapSchema extends TestSchemaBase { @Test diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMessageSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMessageSchema.java index 56fe45337f8..4e504540874 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMessageSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestMessageSchema.java @@ -24,19 +24,18 @@ import org.apache.servicecomb.foundation.protobuf.internal.model.CustomGeneric; import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot; import org.apache.servicecomb.foundation.protobuf.internal.model.User; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.type.TypeFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestMessageSchema extends TestSchemaBase { @Test public void empty() throws Throwable { check(); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(null)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(null)); } @Test @@ -49,7 +48,7 @@ public void generic() throws Throwable { @SuppressWarnings("unchecked") CustomGeneric generic = (CustomGeneric) scbRoot; - Assert.assertThat(generic.user, Matchers.instanceOf(User.class)); + Assertions.assertNotNull(generic.user); } @Test @@ -71,6 +70,6 @@ public void normal() throws Throwable { map.put("notExist", null); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestRepeatedSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestRepeatedSchema.java index c5b9019c36b..a26156a3778 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestRepeatedSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/TestRepeatedSchema.java @@ -24,10 +24,10 @@ import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot; import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot.Color; import org.apache.servicecomb.foundation.protobuf.internal.model.User; -import org.junit.Assert; -import org.junit.Test; import com.google.protobuf.ByteString; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestRepeatedSchema extends TestSchemaBase { public static class RootWithArray { @@ -213,8 +213,8 @@ public void bytess() throws Throwable { check(); RootWithArray rootWithArray = new RootWithArray(); - rootWithArray.bytess = (byte[][]) sList.toArray(); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(rootWithArray)); + rootWithArray.bytess = sList.toArray(new byte[0][]); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(rootWithArray)); } @Test @@ -224,8 +224,8 @@ public void strings() throws Throwable { check(); RootWithArray rootWithArray = new RootWithArray(); - rootWithArray.strings = (String[]) sList.toArray(); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(rootWithArray)); + rootWithArray.strings = sList.toArray(new String[0]); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(rootWithArray)); } @Test @@ -237,6 +237,6 @@ public void users() throws Throwable { RootWithArray rootWithArray = new RootWithArray(); rootWithArray.users = new User[] {new User("name1"), new User("name2")}; - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(rootWithArray)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(rootWithArray)); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBoolSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBoolSchema.java index 61e79eba66a..5862c723bfc 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBoolSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBoolSchema.java @@ -20,9 +20,8 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.User; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestBoolSchema extends TestSchemaBase { public TestBoolSchema() { @@ -37,7 +36,7 @@ public void testTrue() throws Throwable { // equalsIgnoreCase doTestFromString("true"); - doTestFromString("trUe"); + doTestFromString("true"); } @Test @@ -55,33 +54,32 @@ protected void doTestFromString(String value) throws Throwable { // string[] scbMap = new HashMap<>(); scbMap.put("bool", new String[] {value}); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); // string scbMap.put("bool", value); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); } @Test public void nullOrEmpty() throws Throwable { // null scbMap = new HashMap<>(); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); // empty string[] scbMap.put("bool", new String[] {}); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); } @Test public void type_invalid() throws Throwable { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto bool, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:bool")); - - scbMap = new HashMap<>(); - scbMap.put("bool", new User()); - rootSerializer.serialize(scbMap); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put("bool", new User()); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto bool, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:bool", + exception.getMessage()); } } - diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBytesSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBytesSchema.java index 7baac251f05..db350e87596 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBytesSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestBytesSchema.java @@ -20,10 +20,10 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.User; -import org.hamcrest.Matchers; -import org.junit.Test; import com.google.protobuf.ByteString; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestBytesSchema extends TestSchemaBase { public TestBytesSchema() { @@ -38,13 +38,13 @@ public void normal() throws Throwable { } @Test - public void type_invalid() throws Throwable { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto bytes, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:bytes")); - - scbMap = new HashMap<>(); - scbMap.put("bytes", new User()); - rootSerializer.serialize(scbMap); + public void type_invalid() { + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put("bytes", new User()); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto bytes, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:bytes", + exception.getMessage()); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestEnumSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestEnumSchema.java index bba3d61db30..4c70eb2e40e 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestEnumSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestEnumSchema.java @@ -22,20 +22,19 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.User; import org.apache.servicecomb.foundation.test.scaffolding.model.Color; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestEnumSchema extends TestSchemaBase { @Test public void empty() throws Throwable { // null scbMap = new HashMap<>(); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); // empty string[] scbMap.put("color", new String[] {}); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); } public static class EnumRoot { @@ -57,19 +56,19 @@ public void normal() throws Throwable { Map map = new HashMap<>(); map.put("color", Color.BLUE); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); map.put("color", 2); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); map.put("color", new String[] {"BLUE"}); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); map.put("color", "BLUE"); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(map)); EnumRoot enumRoot = protoMapper.createRootDeserializer("Root", EnumRoot.class).deserialize(protobufBytes); - Assert.assertEquals(2, enumRoot.color); + Assertions.assertEquals(2, enumRoot.color); } enum Sharp { @@ -78,34 +77,32 @@ enum Sharp { @Test public void fromInvalidEnum() throws Throwable { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("invalid enum name ROUND for proto Color, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:color")); - - scbMap = new HashMap<>(); - scbMap.put("color", Sharp.ROUND); - rootSerializer.serialize(scbMap); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put("color", Sharp.ROUND); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("invalid enum name ROUND for proto Color, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:color", exception.getMessage()); } @Test - public void fromInvalidNumber() throws Throwable { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("invalid enum value 3 for proto Color, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:color")); - - scbMap = new HashMap<>(); - scbMap.put("color", 3); - rootSerializer.serialize(scbMap); + public void fromInvalidNumber() { + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put("color", 3); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("invalid enum value 3 for proto Color, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:color", exception.getMessage()); } @Test - public void type_invalid() throws Throwable { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto Color, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:color")); - - scbMap = new HashMap<>(); - scbMap.put("color", new User()); - rootSerializer.serialize(scbMap); + public void type_invalid() { + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put("color", new User()); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto Color, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:color", + exception.getMessage()); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestFixed64Schema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestFixed64Schema.java index 95d10338380..03ea489b263 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestFixed64Schema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestFixed64Schema.java @@ -22,4 +22,4 @@ public TestFixed64Schema() { maxValue = Long.MAX_VALUE; initFields("fixed64", "objFixed64"); } -} \ No newline at end of file +} diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestNumberBaseSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestNumberBaseSchema.java index 5e3d777e93d..fd9a236a089 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestNumberBaseSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestNumberBaseSchema.java @@ -25,15 +25,14 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.ProtobufRoot; import org.apache.servicecomb.foundation.test.scaffolding.model.User; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; import io.protostuff.compiler.model.Field; import io.protostuff.compiler.model.Type; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; -@Ignore +@Disabled public abstract class TestNumberBaseSchema extends TestSchemaBase { protected Object minValue; @@ -52,19 +51,19 @@ private void doTestMapNormal(String field, Object value, byte[] expectBytes) thr // null scbMap = new HashMap<>(); scbMap.put(field, null); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); // empty string[] scbMap.put(field, new String[] {}); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); // string[] scbMap.put(field, new String[] {String.valueOf(value)}); - Assert.assertArrayEquals(expectBytes, rootSerializer.serialize(scbMap)); + Assertions.assertArrayEquals(expectBytes, rootSerializer.serialize(scbMap)); // string scbMap.put(field, String.valueOf(value)); - Assert.assertArrayEquals(expectBytes, rootSerializer.serialize(scbMap)); + Assertions.assertArrayEquals(expectBytes, rootSerializer.serialize(scbMap)); } private byte[] doTestPojoNormal(String name) throws Throwable { @@ -91,13 +90,13 @@ public void strings_invalid() throws Throwable { strings_invalid(protoField); } - private void strings_invalid(Field field) throws IOException { - expectedException.expect(NumberFormatException.class); - expectedException.expectMessage(Matchers.is("For input string: \"a\"")); - - scbMap = new HashMap<>(); - scbMap.put(field.getName(), new String[] {"a"}); - rootSerializer.serialize(scbMap); + private void strings_invalid(Field field) { + NumberFormatException exception = Assertions.assertThrows(NumberFormatException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put(field.getName(), new String[] {"a"}); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("For input string: \"a\"", exception.getMessage()); } @Test @@ -110,17 +109,17 @@ public void string_invalid() throws Throwable { string_invalid(protoField); } - private void string_invalid(Field field) throws IOException { - expectedException.expect(NumberFormatException.class); - expectedException.expectMessage(Matchers.is("For input string: \"a\"")); - - scbMap = new HashMap<>(); - scbMap.put(field.getName(), "a"); - rootSerializer.serialize(scbMap); + private void string_invalid(Field field) { + NumberFormatException exception = Assertions.assertThrows(NumberFormatException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put(field.getName(), "a"); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("For input string: \"a\"", exception.getMessage()); } @Test - public void primitiveType_invalid() throws Throwable { + public void primitiveType_invalid() { type_invalid(primitiveProtoField); } @@ -129,17 +128,16 @@ public void type_invalid() throws Throwable { type_invalid(protoField); } - private void type_invalid(Field field) throws IOException { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is(String.format("not support serialize from %s to proto %s, field=%s:%s", + private void type_invalid(Field field) { + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put(field.getName(), new User()); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals(String.format("not support serialize from %s to proto %s, field=%s:%s", User.class.getName(), field.getTypeName(), ((Type) field.getParent()).getCanonicalName(), - field.getName()))); - - scbMap = new HashMap<>(); - scbMap.put(field.getName(), new User()); - rootSerializer.serialize(scbMap); + field.getName()), exception.getMessage()); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestStringSchema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestStringSchema.java index 4c9cd625a90..c1084568350 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestStringSchema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestStringSchema.java @@ -20,9 +20,8 @@ import org.apache.servicecomb.foundation.protobuf.internal.TestSchemaBase; import org.apache.servicecomb.foundation.protobuf.internal.model.User; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestStringSchema extends TestSchemaBase { @Test @@ -34,32 +33,32 @@ public void normal() throws Throwable { // string[] scbMap = new HashMap<>(); scbMap.put("string", new String[] {value}); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); // string scbMap.put("string", value); - Assert.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); + Assertions.assertArrayEquals(protobufBytes, rootSerializer.serialize(scbMap)); } @Test public void nullOrEmpty() throws Throwable { // null scbMap = new HashMap<>(); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); // empty string[] scbMap.put("string", new String[] {}); - Assert.assertEquals(0, rootSerializer.serialize(scbMap).length); + Assertions.assertEquals(0, rootSerializer.serialize(scbMap).length); } @Test public void type_invalid() throws Throwable { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers - .is("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto string, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:string")); - - scbMap = new HashMap<>(); - scbMap.put("string", new User()); - rootSerializer.serialize(scbMap); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, () -> { + scbMap = new HashMap<>(); + scbMap.put("string", new User()); + rootSerializer.serialize(scbMap); + }); + Assertions.assertEquals("not support serialize from org.apache.servicecomb.foundation.protobuf.internal.model.User to proto string, field=org.apache.servicecomb.foundation.protobuf.internal.model.Root:string", + exception.getMessage()); } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestUInt64Schema.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestUInt64Schema.java index 6aef61edcce..6235a4b3e24 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestUInt64Schema.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/internal/schema/scalar/TestUInt64Schema.java @@ -22,4 +22,4 @@ public TestUInt64Schema() { maxValue = Long.MAX_VALUE; initFields("uint64", "objUint64"); } -} \ No newline at end of file +} diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestBase.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestBase.java index c8c810c6505..c73caf9a327 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestBase.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestBase.java @@ -79,25 +79,25 @@ private TestEngineResult runOneEngine(ProtubufCodecEngine engine, Object model, { long msStart = System.currentTimeMillis(); for (int idx = 0; idx < count; idx++) { - engineResult.serBytes = engine.serialize(model); + engineResult.serializeBytes = engine.serialize(model); } long msEnd = System.currentTimeMillis(); - engineResult.msSerTime = msEnd - msStart; + engineResult.msSerializeTime = msEnd - msStart; } // deserialize { long msStart = System.currentTimeMillis(); for (int idx = 0; idx < count; idx++) { - engineResult.deserResult = engine.deserialize(engineResult.serBytes); + engineResult.deserializeResult = engine.deserialize(engineResult.serializeBytes); } long msEnd = System.currentTimeMillis(); - engineResult.msDeserTime = msEnd - msStart; + engineResult.msDeserializeTime = msEnd - msStart; } - engineResult.deserResultBytes = engine.serialize(engineResult.deserResult); + engineResult.deserializeResultBytes = engine.serialize(engineResult.deserializeResult); return engineResult; } } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestEngineResult.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestEngineResult.java index ffa08506df7..f02ee12092a 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestEngineResult.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestEngineResult.java @@ -20,14 +20,14 @@ public class TestEngineResult { public String engineName; // serialize - public long msSerTime; + public long msSerializeTime; - public byte[] serBytes; + public byte[] serializeBytes; // deserialize - public long msDeserTime; + public long msDeserializeTime; - public Object deserResult; + public Object deserializeResult; - public byte[] deserResultBytes; + public byte[] deserializeResultBytes; } diff --git a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestProtoPerformance.java b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestProtoPerformance.java index eea36041283..98e2f5b7855 100644 --- a/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestProtoPerformance.java +++ b/foundations/foundation-protobuf/src/test/java/org/apache/servicecomb/foundation/protobuf/performance/TestProtoPerformance.java @@ -65,17 +65,17 @@ private static void printResult(TestResult result) { System.out.printf(" " + strFmt + "\n", result.engineResults.stream().map(r -> r.engineName).toArray()); - System.out.printf("ser time(ms) : " + numberFmt + "\n", - result.engineResults.stream().map(r -> r.msSerTime).toArray()); - System.out.printf("ser len : " + numberFmt + "\n", - result.engineResults.stream().map(r -> r.serBytes.length).toArray()); + System.out.printf("serialize time(ms) : " + numberFmt + "\n", + result.engineResults.stream().map(r -> r.msSerializeTime).toArray()); + System.out.printf("serialize len : " + numberFmt + "\n", + result.engineResults.stream().map(r -> r.serializeBytes.length).toArray()); - System.out.printf("deser time(ms): " + numberFmt + "\n", - result.engineResults.stream().map(r -> r.msDeserTime).toArray()); - System.out.printf("deser->ser len: " + numberFmt + "\n", - result.engineResults.stream().map(r -> r.deserResultBytes.length).toArray()); + System.out.printf("deserialize time(ms): " + numberFmt + "\n", + result.engineResults.stream().map(r -> r.msDeserializeTime).toArray()); + System.out.printf("deserialize->serialize len: " + numberFmt + "\n", + result.engineResults.stream().map(r -> r.deserializeResultBytes.length).toArray()); - System.out.printf("ser+deser(ms) : " + numberFmt + "\n\n", - result.engineResults.stream().map(r -> r.msSerTime + r.msDeserTime).toArray()); + System.out.printf("serialize+deserialize(ms) : " + numberFmt + "\n\n", + result.engineResults.stream().map(r -> r.msSerializeTime + r.msDeserializeTime).toArray()); } } diff --git a/foundations/foundation-protobuf/src/test/resources/jacksonRoot.proto b/foundations/foundation-protobuf/src/test/resources/jacksonRoot.proto index 1a0e33938bd..b1804922666 100644 --- a/foundations/foundation-protobuf/src/test/resources/jacksonRoot.proto +++ b/foundations/foundation-protobuf/src/test/resources/jacksonRoot.proto @@ -5,9 +5,9 @@ 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. @@ -95,4 +95,4 @@ enum Color { message User { optional string name = 1; -} \ No newline at end of file +} diff --git a/foundations/foundation-protobuf/src/test/resources/method.proto b/foundations/foundation-protobuf/src/test/resources/method.proto index 08a948ca03f..414b7643880 100644 --- a/foundations/foundation-protobuf/src/test/resources/method.proto +++ b/foundations/foundation-protobuf/src/test/resources/method.proto @@ -42,4 +42,4 @@ message Response { message User { string name = 1; repeated User friends = 2; -} \ No newline at end of file +} diff --git a/foundations/foundation-protobuf/src/test/resources/protobufRoot.proto b/foundations/foundation-protobuf/src/test/resources/protobufRoot.proto index 1945ee57b4a..1e9f7f41076 100644 --- a/foundations/foundation-protobuf/src/test/resources/protobufRoot.proto +++ b/foundations/foundation-protobuf/src/test/resources/protobufRoot.proto @@ -5,9 +5,9 @@ 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. @@ -19,6 +19,9 @@ syntax = "proto3"; import "google/protobuf/any.proto"; package org.apache.servicecomb.foundation.protobuf.internal.model; +option java_package = "org.apache.servicecomb.foundation.protobuf.internal.model"; +option java_outer_classname = "ProtobufRoot"; + message Root { int32 int32 = 1; int64 int64 = 2; @@ -106,4 +109,4 @@ message User { string name = 1; Root typeRecursive = 2; -} \ No newline at end of file +} diff --git a/foundations/foundation-registry/pom.xml b/foundations/foundation-registry/pom.xml index ee9c6f9c8e2..d4cca8111c4 100644 --- a/foundations/foundation-registry/pom.xml +++ b/foundations/foundation-registry/pom.xml @@ -21,7 +21,7 @@ foundations org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -47,5 +47,10 @@ org.apache.servicecomb foundation-test-scaffolding + + org.mockito + mockito-inline + test + diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/DiscoveryManager.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/DiscoveryManager.java index 189ddfe7a2d..edcd3b3caef 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/DiscoveryManager.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/DiscoveryManager.java @@ -18,137 +18,320 @@ package org.apache.servicecomb.registry; import java.util.ArrayList; -import java.util.Collection; -import java.util.LinkedList; +import java.util.HashMap; import java.util.List; -import java.util.concurrent.CompletableFuture; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.foundation.common.NamedThreadFactory; +import org.apache.servicecomb.foundation.common.cache.VersionedCache; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.utils.LambdaUtils; import org.apache.servicecomb.registry.api.Discovery; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstances; -import org.apache.servicecomb.registry.cache.InstanceCacheManager; -import org.apache.servicecomb.registry.cache.InstanceCacheManagerNew; -import org.apache.servicecomb.registry.consumer.AppManager; -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.api.LifeCycle; +import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus; +import org.apache.servicecomb.registry.discovery.InstancePing; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.HistoryStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.IsolationStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.PingStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.CollectionUtils; -import com.google.common.annotations.VisibleForTesting; +public class DiscoveryManager implements LifeCycle { + public interface InstanceChangeListener { + void onInstancesChanged(String registryName, String application, String serviceName, + List instances); + } + + private static final Logger LOGGER = LoggerFactory.getLogger(DiscoveryManager.class); + + private final ScheduledExecutorService task; + + private final List> discoveryList; + + private final InstancePing ping; -public class DiscoveryManager { - public static DiscoveryManager INSTANCE = new DiscoveryManager(); + private final HealthCheckTask healthCheckTask = new HealthCheckTask(); - private final List discoveryList = new ArrayList<>(); + // application:serviceName:instanceId + private final Map>> + allInstances = new ConcurrentHashMapEx<>(); - private final AppManager appManager; + // application:serviceName + private final Map> + versionedCache = new ConcurrentHashMapEx<>(); - private final InstanceCacheManager instanceCacheManager; + private final Object cacheLock = new Object(); + private final List instanceChangeListeners = new ArrayList<>(); - private DiscoveryManager() { - appManager = new AppManager(); - instanceCacheManager = new InstanceCacheManagerNew(appManager); - SPIServiceUtils.getOrLoadSortedService(Discovery.class) - .stream() - .filter((discovery -> discovery.enabled())) - .forEach(discoveryList::add); + public DiscoveryManager(List> discoveryList, + List pings) { + this.discoveryList = discoveryList; + for (Discovery discovery : this.discoveryList) { + discovery.setInstanceChangedListener(this::onInstancesChanged); + } + this.ping = pings.get(0); + task = Executors.newScheduledThreadPool(1, new NamedThreadFactory("discovery-manager-task")); } - @VisibleForTesting - public static void renewInstance() { - DiscoveryManager.INSTANCE = new DiscoveryManager(); + public Discovery getPrimaryDiscovery() { + return this.discoveryList.get(0); } - public MicroserviceInstances findServiceInstances(String appId, String serviceName, - String versionRule) { - return findServiceInstances(appId, serviceName, versionRule, null); + private void onInstancesChanged(String application, String serviceName, + List instances) { + onInstancesChanged(null, application, serviceName, instances); } - public MicroserviceInstances findServiceInstances(String appId, String serviceName, - String versionRule, String revision) { - MicroserviceInstances result = new MicroserviceInstances(); - // default values not suitable for aggregate, reset. - result.setNeedRefresh(false); - result.setMicroserviceNotExist(true); - discoveryList - .forEach(discovery -> { - MicroserviceInstances instances = discovery.findServiceInstances(appId, serviceName, versionRule, revision); - result.mergeMicroserviceInstances(instances); - }); + private void onInstancesChanged(String registryName, String application, String serviceName, + List instances) { + Map statefulInstances = allInstances.computeIfAbsent(application, key -> + new ConcurrentHashMapEx<>()).computeIfAbsent(serviceName, key -> new ConcurrentHashMapEx<>()); - return result; - } + for (StatefulDiscoveryInstance statefulInstance : statefulInstances.values()) { + if (registryName == null || registryName.equals(statefulInstance.getRegistryName())) { + if (!instances.contains(statefulInstance)) { + statefulInstance.setPingTime(0); + statefulInstance.setHistoryStatus(HistoryStatus.HISTORY); + } + } + } - public InstanceCacheManager getInstanceCacheManager() { - return this.instanceCacheManager; + for (DiscoveryInstance instance : instances) { + StatefulDiscoveryInstance target = new StatefulDiscoveryInstance(instance); + StatefulDiscoveryInstance origin = statefulInstances.get(instance.getInstanceId()); + if (origin == null) { + statefulInstances.put(instance.getInstanceId(), target); + continue; + } + target.setPingTime(origin.getPingTime()); + target.setPingStatus(origin.getPingStatus()); + target.setIsolateDuration(origin.getIsolateDuration()); + target.setIsolationStatus(origin.getIsolationStatus()); + statefulInstances.put(instance.getInstanceId(), target); + } + + StringBuilder instanceInfo = new StringBuilder(); + for (DiscoveryInstance instance : instances) { + instanceInfo.append("{") + .append(instance.getInstanceId()).append(",") + .append(instance.getStatus()).append(",") + .append(instance.getEndpoints()).append(",") + .append(instance.getRegistryName()) + .append("}"); + } + LOGGER.info("Applying new instance list for {}/{}/{}. Endpoints {}", + application, serviceName, instances.size(), instanceInfo); + + rebuildVersionCache(application, serviceName); + + for (InstanceChangeListener listener : this.instanceChangeListeners) { + listener.onInstancesChanged(registryName, application, serviceName, instances); + } } - public AppManager getAppManager() { - return this.appManager; + public void addInstanceChangeListener(InstanceChangeListener instanceChangeListener) { + this.instanceChangeListeners.add(instanceChangeListener); } - public MicroserviceInstance getMicroserviceInstance(String serviceId, String instanceId) { - for (Discovery discovery : discoveryList) { - MicroserviceInstance microserviceInstance = discovery.getMicroserviceInstance(serviceId, instanceId); - if (microserviceInstance != null) { - return microserviceInstance; - } + public void onInstanceIsolated(DiscoveryInstance instance, long isolateDuration) { + Map statefulInstances = allInstances.computeIfAbsent( + instance.getApplication(), key -> + new ConcurrentHashMapEx<>()).computeIfAbsent(instance.getServiceName(), key + -> new ConcurrentHashMapEx<>()); + StatefulDiscoveryInstance target = statefulInstances.get(instance.getInstanceId()); + if (target == null) { + return; } - return null; + + target.setIsolatedTime(System.currentTimeMillis()); + target.setIsolateDuration(isolateDuration); + + if (target.getIsolationStatus() != IsolationStatus.ISOLATED) { + target.setIsolationStatus(IsolationStatus.ISOLATED); + rebuildVersionCache(instance.getApplication(), instance.getServiceName()); + } + + LOGGER.warn("Isolated instance {}/{}/{}, time {}/{}", + instance.getApplication(), instance.getServiceName(), instance.getInstanceId(), + target.getIsolatedTime(), target.getIsolateDuration()); } - public String getSchema(String microserviceId, Collection instances, String schemaId) { - for (Discovery discovery : discoveryList) { - String schema = discovery.getSchema(microserviceId, instances, schemaId); - if (schema != null) { - return schema; + private void rebuildVersionCache(String application, String serviceName) { + Map caches = versionedCache.computeIfAbsent(application, key -> + new ConcurrentHashMapEx<>()); + caches.put(serviceName, calcAvailableInstance(application, serviceName)); + } + + private VersionedCache calcAvailableInstance(String application, String serviceName) { + Map statefulInstances = allInstances.computeIfAbsent( + application, key -> + new ConcurrentHashMapEx<>()).computeIfAbsent(serviceName, key + -> new ConcurrentHashMapEx<>()); + List result = new ArrayList<>(); + for (StatefulDiscoveryInstance instance : statefulInstances.values()) { + if (instance.getHistoryStatus() == HistoryStatus.CURRENT) { + result.add(instance); + continue; + } + if (instance.getHistoryStatus() == HistoryStatus.HISTORY + && instance.getStatus() == MicroserviceInstanceStatus.UP + && instance.getPingStatus() == PingStatus.OK + && instance.getIsolationStatus() == IsolationStatus.NORMAL) { + result.add(instance); } } - return null; + StringBuilder instanceInfo = new StringBuilder(); + for (StatefulDiscoveryInstance instance : result) { + instanceInfo.append("{") + .append(instance.getInstanceId()).append(",") + .append(instance.getHistoryStatus()).append(",") + .append(instance.getStatus()).append(",") + .append(instance.getPingStatus()).append(",") + .append(instance.getIsolationStatus()).append(",") + .append(instance.getEndpoints()).append(",") + .append(instance.getRegistryName()) + .append("}"); + } + LOGGER.info("Rebuild cached instance list for {}/{}/{}. Endpoints {}", + application, serviceName, result.size(), instanceInfo); + return new VersionedCache() + .name(application + ":" + serviceName) + .autoCacheVersion() + .data(result); } - public Microservice getMicroservice(String microserviceId) { - for (Discovery discovery : discoveryList) { - Microservice microservice = discovery.getMicroservice(microserviceId); - if (microservice != null) { - return microservice; + public VersionedCache getOrCreateVersionedCache(String application, String serviceName) { + Map caches = versionedCache.computeIfAbsent(application, key -> + new ConcurrentHashMapEx<>()); + VersionedCache cache = caches.get(serviceName); + if (cache == null) { + synchronized (cacheLock) { + cache = caches.get(serviceName); + if (cache != null) { + return cache; + } + List instances = findServiceInstances(application, serviceName); + onInstancesChanged(application, serviceName, instances); + return versionedCache.get(application).get(serviceName); } } - return null; + return cache; } - public List getAllMicroservices() { - List result = new LinkedList<>(); - for (Discovery discovery : discoveryList) { - List microservices = discovery.getAllMicroservices(); - if (microservices != null) { - result.addAll(microservices); + public List findServiceInstances(String application, String serviceName) { + List result = new ArrayList<>(); + for (Discovery discovery : discoveryList) { + if (!discovery.enabled() || !discovery.enabled(application, serviceName)) { + continue; + } + List temp = discovery.findServiceInstances(application, serviceName); + if (CollectionUtils.isEmpty(temp)) { + continue; } + result.addAll(temp); } return result; } - public CompletableFuture getOrCreateMicroserviceVersionsAsync(String appId, - String microserviceName) { - return appManager.getOrCreateMicroserviceVersionsAsync(appId, microserviceName); + @Override + public void destroy() { + discoveryList.forEach(LambdaUtils.ignoreException(LifeCycle::destroy)); + task.shutdownNow(); } - public MicroserviceVersions getOrCreateMicroserviceVersions(String appId, String microserviceName) { - return appManager.getOrCreateMicroserviceVersions(appId, microserviceName); + @Override + public void run() { + discoveryList.forEach(LifeCycle::run); + task.schedule(healthCheckTask, 3, TimeUnit.SECONDS); } - public void destroy() { - discoveryList.forEach(discovery -> discovery.destroy()); + @Override + public void init() { + discoveryList.forEach(LifeCycle::init); } - public void run() { - discoveryList.forEach(discovery -> discovery.run()); + public String info() { + StringBuilder result = new StringBuilder(); + AtomicBoolean first = new AtomicBoolean(true); + discoveryList.forEach(discovery -> { + if (first.getAndSet(false)) { + result.append("Discovery implementations:\n"); + } + result.append(" name:").append(discovery.name()).append("\n"); + }); + return result.toString(); } - public void init() { - BeanUtils.addBeans(Discovery.class, discoveryList); + class HealthCheckTask implements Runnable { - discoveryList.forEach(discovery -> discovery.init()); + @Override + public void run() { + try { + Map>> removed = new HashMap<>(); + for (Entry>> apps : DiscoveryManager.this.allInstances.entrySet()) { + for (Entry> services : apps.getValue().entrySet()) { + boolean changed = false; + for (StatefulDiscoveryInstance instance : services.getValue().values()) { + // check isolated time + if (instance.getIsolationStatus() == IsolationStatus.ISOLATED && + instance.getIsolatedTime() + instance.getIsolateDuration() < System.currentTimeMillis()) { + instance.setIsolationStatus(IsolationStatus.NORMAL); + changed = true; + } + // check ping status + if (System.currentTimeMillis() - instance.getPingTime() > 60_000L) { + boolean pingResult = DiscoveryManager.this.ping.ping(instance); + if (pingResult && instance.getPingStatus() != PingStatus.OK) { + instance.setPingStatus(PingStatus.OK); + changed = true; + } else if (!pingResult && instance.getPingStatus() != PingStatus.FAIL) { + instance.setPingStatus(PingStatus.FAIL); + changed = true; + } + instance.setPingTime(System.currentTimeMillis()); + } + // check unused + if (instance.getHistoryStatus() == HistoryStatus.HISTORY) { + if (instance.getStatus() != MicroserviceInstanceStatus.UP || + instance.getPingStatus() == PingStatus.FAIL || + instance.getIsolationStatus() == IsolationStatus.ISOLATED) { + removed.computeIfAbsent(apps.getKey(), k -> new HashMap<>()) + .computeIfAbsent(services.getKey(), k -> new ArrayList<>()).add(instance.getInstanceId()); + LOGGER.info("Remove instance {}/{}/{}/{}/{}/{}/{}/{}", + apps.getKey(), services.getKey(), instance.getRegistryName(), + instance.getInstanceId(), instance.getHistoryStatus(), + instance.getStatus(), instance.getPingStatus(), instance.getIsolationStatus()); + changed = true; + } + } + } + if (changed) { + rebuildVersionCache(apps.getKey(), services.getKey()); + } + } + } + // remove unused + for (Entry>> apps : removed.entrySet()) { + for (Entry> services : apps.getValue().entrySet()) { + for (String instance : services.getValue()) { + DiscoveryManager.this.allInstances.get(apps.getKey()).get(services.getKey()).remove(instance); + } + } + } + } catch (Throwable e) { + LOGGER.error("discovery manager task error. ", e); + } finally { + DiscoveryManager.this.task.schedule(this, 3, TimeUnit.SECONDS); + } + } } } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationId.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationId.java new file mode 100644 index 00000000000..9932f5fdfc9 --- /dev/null +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationId.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.registry; + +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RegistrationId { + private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationId.class); + + private final String instanceId; + + public RegistrationId() { + this.instanceId = buildInstanceId(); + LOGGER.info("initialized global registration id {}", this.instanceId); + } + + public String getInstanceId() { + return instanceId; + } + + private static String buildInstanceId() { + return UUID.randomUUID().toString(); + } +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationManager.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationManager.java index fb4ae57d61e..9c135d380c8 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationManager.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistrationManager.java @@ -17,97 +17,77 @@ package org.apache.servicecomb.registry; -import java.net.Inet6Address; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; -import org.apache.http.client.utils.URIBuilder; -import org.apache.servicecomb.foundation.common.event.EnableExceptionPropagation; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.net.IpPort; -import org.apache.servicecomb.foundation.common.net.NetUtils; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.common.utils.LambdaUtils; import org.apache.servicecomb.foundation.common.utils.SPIEnabled; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.registry.api.LifeCycle; +import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus; import org.apache.servicecomb.registry.api.Registration; -import org.apache.servicecomb.registry.api.event.MicroserviceInstanceRegisteredEvent; -import org.apache.servicecomb.registry.api.registry.BasePath; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus; -import org.apache.servicecomb.registry.consumer.MicroserviceManager; -import org.apache.servicecomb.registry.consumer.StaticMicroserviceVersions; -import org.apache.servicecomb.registry.definition.MicroserviceNameParser; -import org.apache.servicecomb.registry.swagger.SwaggerLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.eventbus.Subscribe; -import com.netflix.config.DynamicPropertyFactory; +import org.apache.servicecomb.registry.api.RegistrationInstance; +import org.springframework.util.CollectionUtils; import io.vertx.core.json.jackson.JacksonFactory; -import io.vertx.core.spi.json.JsonCodec; public class RegistrationManager { - private static final Logger LOGGER = LoggerFactory.getLogger(RegistrationManager.class); - - // value is ip or {interface name} - public static final String PUBLISH_ADDRESS = "servicecomb.service.publishAddress"; - - private static final String PUBLISH_PORT = "servicecomb.{transport_name}.publishPort"; - - private static SwaggerLoader swaggerLoader = new SwaggerLoader(); - - public static RegistrationManager INSTANCE = new RegistrationManager(); + private final List> registrationList; - private final List registrationList = new ArrayList<>(); - - private Registration primary; - - private RegistrationManager() { - SPIServiceUtils.getOrLoadSortedService(Registration.class) - .stream() - .filter((SPIEnabled::enabled)) - .forEach(registrationList::add); - initPrimary(); - } - - public MicroserviceInstance getMicroserviceInstance() { - return primary.getMicroserviceInstance(); + public RegistrationManager(List> registrationList) { + if (registrationList == null) { + this.registrationList = Collections.emptyList(); + return; + } + this.registrationList = registrationList.stream().filter(SPIEnabled::enabled).collect(Collectors.toList()); } - public Microservice getMicroservice() { - assertPrimaryNotNull(); - return primary.getMicroservice(); + /** + * For internal use. Get instance id from registry name. If not exists, return empty. + */ + public String getInstanceId(String registryName) { + if (CollectionUtils.isEmpty(registrationList)) { + return ""; + } + Optional> registration = + registrationList.stream().filter(r -> registryName.equals(r.name())).collect(Collectors.toList()) + .stream().findFirst(); + if (!registration.isPresent()) { + return ""; + } + return registration.get().getMicroserviceInstance().getInstanceId(); } - private void assertPrimaryNotNull() { - if (primary == null) { - throw new NullPointerException("At least one Registration implementation configured. Missed" - + " to include dependency ? e.g. registry-service-center"); + /** + * For internal use. Get service id from registry name. If not exists, return empty. + */ + public String getServiceId(String registryName) { + if (CollectionUtils.isEmpty(registrationList)) { + return ""; + } + Optional> registration = + registrationList.stream().filter(r -> registryName.equals(r.name())).collect(Collectors.toList()) + .stream().findFirst(); + if (!registration.isPresent()) { + return ""; } + return registration.get().getMicroserviceInstance().getServiceId(); } - public String getAppId() { - assertPrimaryNotNull(); - return primary.getAppId(); + public Registration getPrimaryRegistration() { + return registrationList.get(0); } - public SwaggerLoader getSwaggerLoader() { - return swaggerLoader; + public void updateMicroserviceInstanceStatus(MicroserviceInstanceStatus status) { + registrationList + .forEach(registration -> registration.updateMicroserviceInstanceStatus(status)); } - public void updateMicroserviceInstanceStatus( - MicroserviceInstanceStatus status) { + public void addProperty(String key, String value) { registrationList - .forEach(registration -> registration.updateMicroserviceInstanceStatus(status)); + .forEach(registration -> registration.addProperty(key, value)); } public void addSchema(String schemaId, String content) { @@ -120,188 +100,16 @@ public void addEndpoint(String endpoint) { .forEach(registration -> registration.addEndpoint(endpoint)); } - public void addBasePath(Collection basePaths) { - registrationList - .forEach(registration -> registration.addBasePath(basePaths)); - } - public void destroy() { - registrationList.forEach(registration -> registration.destroy()); + registrationList.forEach(LambdaUtils.ignoreException(LifeCycle::destroy)); } public void run() { - EventManager.getEventBus().register(new AfterServiceInstanceRegistryHandler(registrationList.size())); - registrationList.forEach(registration -> registration.run()); + registrationList.forEach(LifeCycle::run); } public void init() { - BeanUtils.addBeans(Registration.class, registrationList); - - initPrimary(); - registrationList.forEach(registration -> registration.init()); - } - - private void initPrimary() { - if (registrationList.isEmpty()) { - LOGGER.warn("No registration is enabled. Fix this if only in unit tests."); - primary = null; - } else { - primary = registrationList.get(0); - } - } - - /** - *

- * Register a third party service if not registered before, and set it's instances into - * {@linkplain StaticMicroserviceVersions StaticMicroserviceVersions}. - *

- *

- * The registered third party service has the same {@code appId} and {@code environment} as this microservice instance has, - * and there is only one schema represented by {@code schemaIntfCls}, whose name is the same as {@code microserviceName}. - *

- * - * This method is for initializing 3rd party service endpoint config. - * i.e. If this service has not been registered before, this service will be registered and the instances will be set; - * otherwise, NOTHING will happen. - * - * - * @param microserviceName name of the 3rd party service, and this param also specifies the schemaId - * @param version version of this 3rd party service - * @param instances the instances of this 3rd party service. Users only need to specify the endpoint information, other - * necessary information will be generate and set in the implementation of this method. - * @param schemaIntfCls the producer interface of the service. This interface is used to generate swagger schema and - * can also be used for the proxy interface of RPC style invocation. - */ - public void registerMicroserviceMapping(String microserviceName, String version, List instances, - Class schemaIntfCls) { - MicroserviceNameParser parser = new MicroserviceNameParser(getAppId(), microserviceName); - MicroserviceManager microserviceManager = DiscoveryManager.INSTANCE.getAppManager() - .getOrCreateMicroserviceManager(parser.getAppId()); - microserviceManager.getVersionsByName() - .computeIfAbsent(microserviceName, - svcName -> new StaticMicroserviceVersions(DiscoveryManager.INSTANCE.getAppManager(), parser.getAppId(), - microserviceName) - .init(schemaIntfCls, version, instances) - ); - } - - /** - * @see #registerMicroserviceMapping(String, String, List, Class) - * @param endpoints the endpoints of 3rd party service. Each of endpoints will be treated as a separated instance. - * Format of the endpoints is the same as the endpoints that ServiceComb microservices register in service-center, - * like {@code rest://127.0.0.1:8080} - */ - public void registerMicroserviceMappingByEndpoints(String microserviceName, String version, - List endpoints, Class schemaIntfCls) { - ArrayList microserviceInstances = new ArrayList<>(); - for (String endpoint : endpoints) { - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setEndpoints(Collections.singletonList(endpoint)); - microserviceInstances.add(instance); - } - - registerMicroserviceMapping(microserviceName, version, microserviceInstances, schemaIntfCls); - } - - public static String getPublishAddress() { - String publicAddressSetting = - DynamicPropertyFactory.getInstance().getStringProperty(PUBLISH_ADDRESS, "").get(); - publicAddressSetting = publicAddressSetting.trim(); - if (publicAddressSetting.isEmpty()) { - return NetUtils.getHostAddress(); - } - - // placeholder is network interface name - if (publicAddressSetting.startsWith("{") && publicAddressSetting.endsWith("}")) { - return NetUtils - .ensureGetInterfaceAddress(publicAddressSetting.substring(1, publicAddressSetting.length() - 1)) - .getHostAddress(); - } - - return publicAddressSetting; - } - - public static String getPublishHostName() { - String publicAddressSetting = - DynamicPropertyFactory.getInstance().getStringProperty(PUBLISH_ADDRESS, "").get(); - publicAddressSetting = publicAddressSetting.trim(); - if (publicAddressSetting.isEmpty()) { - return NetUtils.getHostName(); - } - - if (publicAddressSetting.startsWith("{") && publicAddressSetting.endsWith("}")) { - return NetUtils - .ensureGetInterfaceAddress(publicAddressSetting.substring(1, publicAddressSetting.length() - 1)) - .getHostName(); - } - - return publicAddressSetting; - } - - /** - * In the case that listening address configured as 0.0.0.0, the publish address will be determined - * by the query result for the net interfaces. - * - * @return the publish address, or {@code null} if the param {@code address} is null. - */ - public static String getPublishAddress(String schema, String address) { - if (address == null) { - return address; - } - - try { - URI originalURI = new URI(schema + "://" + address); - IpPort ipPort = NetUtils.parseIpPort(originalURI); - if (ipPort == null) { - LOGGER.warn("address {} not valid.", address); - return null; - } - - IpPort publishIpPort = genPublishIpPort(schema, ipPort); - URIBuilder builder = new URIBuilder(originalURI); - return builder.setHost(publishIpPort.getHostOrIp()).setPort(publishIpPort.getPort()).build().toString(); - } catch (URISyntaxException e) { - LOGGER.warn("address {} not valid.", address); - return null; - } - } - - private static IpPort genPublishIpPort(String schema, IpPort ipPort) { - String publicAddressSetting = DynamicPropertyFactory.getInstance() - .getStringProperty(PUBLISH_ADDRESS, "") - .get(); - publicAddressSetting = publicAddressSetting.trim(); - - if (publicAddressSetting.isEmpty()) { - InetSocketAddress socketAddress = ipPort.getSocketAddress(); - if (socketAddress.getAddress().isAnyLocalAddress()) { - String host = NetUtils.getHostAddress(); - if (Inet6Address.class.isInstance(socketAddress.getAddress())) { - host = NetUtils.getIpv6HostAddress(); - } - LOGGER.warn("address {}, auto select a host address to publish {}:{}, maybe not the correct one", - socketAddress, - host, - socketAddress.getPort()); - return new IpPort(host, ipPort.getPort()); - } - - return ipPort; - } - - if (publicAddressSetting.startsWith("{") && publicAddressSetting.endsWith("}")) { - publicAddressSetting = NetUtils - .ensureGetInterfaceAddress( - publicAddressSetting.substring(1, publicAddressSetting.length() - 1)) - .getHostAddress(); - } - - String publishPortKey = PUBLISH_PORT.replace("{transport_name}", schema); - int publishPortSetting = DynamicPropertyFactory.getInstance() - .getIntProperty(publishPortKey, 0) - .get(); - int publishPort = publishPortSetting == 0 ? ipPort.getPort() : publishPortSetting; - return new IpPort(publicAddressSetting, publishPort); + registrationList.forEach(LifeCycle::init); } public String info() { @@ -309,17 +117,17 @@ public String info() { AtomicBoolean first = new AtomicBoolean(true); registrationList.forEach(registration -> { if (first.getAndSet(false)) { - result.append("App ID: " + registration.getAppId() + "\n"); - result.append("Service Name: " + registration.getMicroservice().getServiceName() + "\n"); - result.append("Version: " + registration.getMicroservice().getVersion() + "\n"); - result.append("Environment: " + registration.getMicroservice().getEnvironment() + "\n"); - result.append("Endpoints: " + getEndpoints(registration.getMicroserviceInstance().getEndpoints()) + "\n"); + result.append("App ID: ").append(registration.getMicroserviceInstance().getApplication()).append("\n"); + result.append("Service Name: ").append(registration.getMicroserviceInstance().getServiceName()).append("\n"); + result.append("Version: ").append(registration.getMicroserviceInstance().getVersion()).append("\n"); + result.append("Environment: ").append(registration.getMicroserviceInstance().getEnvironment()).append("\n"); + result.append("Endpoints: ").append(getEndpoints(registration.getMicroserviceInstance().getEndpoints())) + .append("\n"); result.append("Registration implementations:\n"); } - result.append(" name:" + registration.name() + "\n"); - result.append(" Service ID: " + registration.getMicroservice().getServiceId() + "\n"); - result.append(" Instance ID: " + registration.getMicroserviceInstance().getInstanceId() + "\n"); + result.append(" name:").append(registration.name()).append("\n"); + result.append(" Instance ID: ").append(registration.getMicroserviceInstance().getInstanceId()).append("\n"); }); return result.toString(); } @@ -327,32 +135,4 @@ public String info() { private String getEndpoints(List endpoints) { return JacksonFactory.CODEC.toString(endpoints); } - - public static class AfterServiceInstanceRegistryHandler { - private AtomicInteger instanceRegisterCounter; - - AfterServiceInstanceRegistryHandler(int counter) { - instanceRegisterCounter = new AtomicInteger(counter); - } - - @Subscribe - @EnableExceptionPropagation - public void afterRegistryInstance(MicroserviceInstanceRegisteredEvent event) { - LOGGER.info("receive MicroserviceInstanceRegisteredEvent event, registration={}, instance id={}", - event.getRegistrationName(), - event.getInstanceId()); - - if (instanceRegisterCounter.decrementAndGet() > 0) { - return; - } - - EventManager.unregister(this); - - EventManager.getEventBus().post(new MicroserviceInstanceRegisteredEvent( - "Registration Manager", - null, - true - )); - } - } -} \ No newline at end of file +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistryConfiguration.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistryConfiguration.java index b33c4f2b45b..7a1d72460cc 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistryConfiguration.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/RegistryConfiguration.java @@ -17,14 +17,58 @@ package org.apache.servicecomb.registry; -import org.apache.servicecomb.registry.consumer.AppManager; +import java.util.List; + +import org.apache.servicecomb.registry.api.Discovery; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.api.Registration; +import org.apache.servicecomb.registry.api.RegistrationInstance; +import org.apache.servicecomb.registry.discovery.DiscoveryTree; +import org.apache.servicecomb.registry.discovery.InstancePing; +import org.apache.servicecomb.registry.discovery.InstanceStatusDiscoveryFilter; +import org.apache.servicecomb.registry.discovery.MicroserviceInstanceCache; +import org.apache.servicecomb.registry.discovery.TelnetInstancePing; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration +@SuppressWarnings("unused") public class RegistryConfiguration { @Bean - public AppManager appManager() { - return DiscoveryManager.INSTANCE.getAppManager(); + public RegistrationManager scbRegistrationManager( + List> registrationList) { + return new RegistrationManager(registrationList); + } + + @Bean + public TelnetInstancePing scbTelnetInstancePing() { + return new TelnetInstancePing(); + } + + @Bean + public DiscoveryManager scbDiscoveryManager( + List> discoveryList, + List pingList) { + return new DiscoveryManager(discoveryList, pingList); + } + + @Bean + public DiscoveryTree scbDiscoveryTree(DiscoveryManager discoveryManager) { + return new DiscoveryTree(discoveryManager); + } + + @Bean + public InstanceStatusDiscoveryFilter scbInstanceStatusDiscoveryFilter() { + return new InstanceStatusDiscoveryFilter(); + } + + @Bean + public MicroserviceInstanceCache scbMicroserviceInstanceCache(DiscoveryManager discoveryManager) { + return new MicroserviceInstanceCache(discoveryManager); + } + + @Bean + public RegistrationId scbRegistrationId() { + return new RegistrationId(); } } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/AbstractDiscoveryInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/AbstractDiscoveryInstance.java new file mode 100644 index 00000000000..08bcd6c02de --- /dev/null +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/AbstractDiscoveryInstance.java @@ -0,0 +1,32 @@ +/* + * 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.registry.api; + +public abstract class AbstractDiscoveryInstance implements DiscoveryInstance { + @Override + public int hashCode() { + return getInstanceId().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DiscoveryInstance) { + return getInstanceId().equals(((DiscoveryInstance) obj).getInstanceId()); + } + return false; + } +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/DataCenterInfo.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/DataCenterInfo.java similarity index 84% rename from foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/DataCenterInfo.java rename to foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/DataCenterInfo.java index b178b3181ca..7c6496e4b91 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/DataCenterInfo.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/DataCenterInfo.java @@ -14,16 +14,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.servicecomb.registry.api.registry; -public class DataCenterInfo { +package org.apache.servicecomb.registry.api; +public class DataCenterInfo { private String name; private String region; private String availableZone; + public DataCenterInfo() { + + } + + public DataCenterInfo(String name, String region, String availableZone) { + this.name = name; + this.region = region; + this.availableZone = availableZone; + } + public String getName() { return name; } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Discovery.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Discovery.java index 593fa43969f..0c57ed6b605 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Discovery.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Discovery.java @@ -17,66 +17,54 @@ package org.apache.servicecomb.registry.api; -import java.util.Collection; import java.util.List; import org.apache.servicecomb.foundation.common.utils.SPIEnabled; import org.apache.servicecomb.foundation.common.utils.SPIOrder; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstances; /** * This is the core service discovery interface.
*/ -public interface Discovery extends SPIEnabled, SPIOrder, LifeCycle { - /** - * get Microservice
- * - * Life Cycle:This method is called anytime after run. - */ - Microservice getMicroservice(String microserviceId); +public interface Discovery extends SPIEnabled, SPIOrder, LifeCycle { + interface InstanceChangedListener { + /** + * Called by Discovery Implementations when instance list changed. + * @param registryName Name of the calling discovery implementation + * @param application Microservice application + * @param serviceName Microservice name + * @param updatedInstances The latest updated instances. + */ + void onInstanceChanged(String registryName, String application, String serviceName, List updatedInstances); + } + + String name(); /** - * get all Microservices
- * - * Life Cycle:This method is called anytime after run. + * If this implementation enabled for this microservice. */ - List getAllMicroservices(); + boolean enabled(String application, String serviceName); /** - * get schema content
+ * Find all instances. * * Life Cycle:This method is called anytime after run. + * + * @param application application + * @param serviceName microservice name + * @return all instances match the criteria. */ - String getSchema(String microserviceId, Collection instances, String schemaId); + List findServiceInstances(String application, String serviceName); /** - * get MicroserviceInstance
+ * Find all services of this application. * - * Life Cycle:This method is called anytime after run. + * @param application application + * @return all services match the criteria. */ - MicroserviceInstance getMicroserviceInstance(String serviceId, String instanceId); + List findServices(String application); /** - * Find all instances. Implementations can use gerRevision to retrieve the - * latest instances changed.
- * - * Life Cycle:This method is called anytime after run. - * - * @param appId application id - * @param serviceName microservice name - * @param versionRule literal version rule. e.g. 1.0.0, 1.0.0+, [1.0.0, 2.0.0) - * @return all instances match the criteria. + * Discovery can call InstanceChangedListener when instance get changed. */ - default MicroserviceInstances findServiceInstances(String appId, String serviceName, String versionRule) { - return findServiceInstances(appId, serviceName, versionRule, null); - } - - default MicroserviceInstances findServiceInstances(String appId, String serviceName, String versionRule, - String revision) { - return null; - } - - String name(); + void setInstanceChangedListener(InstanceChangedListener instanceChangedListener); } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/DiscoveryInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/DiscoveryInstance.java new file mode 100644 index 00000000000..f981aa349e6 --- /dev/null +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/DiscoveryInstance.java @@ -0,0 +1,32 @@ +/* + * 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.registry.api; + +/** + * Microserivce instance discovery object. + */ +public interface DiscoveryInstance extends MicroserviceInstance { + /** + * Microservice instance status. + */ + MicroserviceInstanceStatus getStatus(); + + /** + * This name of Discovery Implementation. + */ + String getRegistryName(); +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/MicroserviceInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/MicroserviceInstance.java new file mode 100644 index 00000000000..c5c872beefd --- /dev/null +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/MicroserviceInstance.java @@ -0,0 +1,102 @@ +/* + * 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.registry.api; + +import java.util.List; +import java.util.Map; + +/** + * Standard information used for microservice instance registration and discovery. + */ +public interface MicroserviceInstance { + /** + * Environment(Required): Used for logic separation of microservice instance. Only + * microservice instance with same environment can discovery each other. + */ + String getEnvironment(); + + /** + * Application(Required): Used for logic separation of microservice instance. Only + * microservice instance with same application can discovery each other. + */ + String getApplication(); + + /** + * Service Name(Required): Unique identifier for microservice. + */ + String getServiceName(); + + /** + * Service Name Alias(Optional): Unique identifier for microservice. + * This alias is used by registry implementation to support rename + * of a microservice, e.g. old consumers use old service name can + * find a renamed microservice service. + */ + String getAlias(); + + /** + * Service Version(Required): version of this microservice. + */ + String getVersion(); + + /** + * Data center info(Optional). + */ + DataCenterInfo getDataCenterInfo(); + + /** + * Service Description(Optional) + */ + String getDescription(); + + /** + * Service Properties(Optional) + */ + Map getProperties(); + + /** + * Service Schemas(Optional): Open API information. + */ + Map getSchemas(); + + /** + * Service endpoints(Optional). + */ + List getEndpoints(); + + /** + * Microservice instance id(Required). This id can be generated when microservice instance is starting + * or assigned by registry implementation. + * + * When microservice instance is restarted, this id should be changed. + */ + String getInstanceId(); + + /** + * Microservice service id(Optional). This is used for service center, other implementations may not + * support service id. + */ + default String getServiceId() { + return ""; + } + + /** + * Service status(Required): status of this microservice. + * + */ + MicroserviceInstanceStatus getStatus(); +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstanceStatus.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/MicroserviceInstanceStatus.java similarity index 89% rename from foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstanceStatus.java rename to foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/MicroserviceInstanceStatus.java index 536feadca7e..4bde42dee91 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstanceStatus.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/MicroserviceInstanceStatus.java @@ -15,16 +15,12 @@ * limitations under the License. */ -package org.apache.servicecomb.registry.api.registry; +package org.apache.servicecomb.registry.api; -/** - * Created by on 2016/12/5. - */ public enum MicroserviceInstanceStatus { STARTING, TESTING, UP, - OUTOFSERVICE, DOWN, UNKNOWN } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Registration.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Registration.java index 5f72f0e0537..014da5f147b 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Registration.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Registration.java @@ -17,67 +17,48 @@ package org.apache.servicecomb.registry.api; -import java.util.Collection; - import org.apache.servicecomb.foundation.common.utils.SPIEnabled; import org.apache.servicecomb.foundation.common.utils.SPIOrder; -import org.apache.servicecomb.registry.api.registry.BasePath; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus; + /** - * This is the core service registration interface.
+ * This is the core service registration interface. */ -public interface Registration extends SPIEnabled, SPIOrder, LifeCycle { +public interface Registration extends SPIEnabled, SPIOrder, LifeCycle { String name(); /** - * get MicroserviceInstance
- * - * Life Cycle:This method is called anytime after run. - */ - MicroserviceInstance getMicroserviceInstance(); - - /** - * get Microservice
- * - * Life Cycle:This method is called anytime after run. - */ - Microservice getMicroservice(); - - /** - * get application id
- * + * get MicroserviceInstance + *

* Life Cycle:This method is called anytime after run. */ - String getAppId(); + R getMicroserviceInstance(); /** - * update MicroserviceInstance status
- * + * update MicroserviceInstance status + *

* Life Cycle:This method is called anytime after run. */ boolean updateMicroserviceInstanceStatus(MicroserviceInstanceStatus status); /** - * adding schemas to Microservice
- * + * adding schemas to Microservice + *

* Life Cycle:This method is called after init and before run. */ void addSchema(String schemaId, String content); /** - * adding endpoints to MicroserviceInstance
- * + * adding endpoints to MicroserviceInstance + *

* Life Cycle:This method is called after init and before run. */ void addEndpoint(String endpoint); /** - * adding BasePath to MicroserviceInstance
- * + * adding property to MicroserviceInstance + *

* Life Cycle:This method is called after init and before run. */ - void addBasePath(Collection basePaths); + void addProperty(String key, String value); } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/RegistrationInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/RegistrationInstance.java new file mode 100644 index 00000000000..a7d7cafda88 --- /dev/null +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/RegistrationInstance.java @@ -0,0 +1,23 @@ +/* + * 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.registry.api; + +/** + * Microserivce instance registration object. + */ +public interface RegistrationInstance extends MicroserviceInstance { +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Versions.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Versions.java deleted file mode 100644 index 685fac68164..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/Versions.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.registry.api; - -import java.util.Map; - -public interface Versions { - public Map loadVersion(); -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/CreateMicroserviceEvent.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/CreateMicroserviceEvent.java deleted file mode 100644 index c2088d7c372..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/CreateMicroserviceEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.registry.api.event; - -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; - -public class CreateMicroserviceEvent { - private MicroserviceVersions microserviceVersions; - - public CreateMicroserviceEvent(MicroserviceVersions microserviceVersions) { - this.microserviceVersions = microserviceVersions; - } - - public MicroserviceVersions getMicroserviceVersions() { - return microserviceVersions; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/CreateMicroserviceVersionEvent.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/CreateMicroserviceVersionEvent.java deleted file mode 100644 index 54eb6205427..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/CreateMicroserviceVersionEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.registry.api.event; - -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; - -public class CreateMicroserviceVersionEvent { - private MicroserviceVersion microserviceVersion; - - public CreateMicroserviceVersionEvent(MicroserviceVersion microserviceVersion) { - this.microserviceVersion = microserviceVersion; - } - - public MicroserviceVersion getMicroserviceVersion() { - return microserviceVersion; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/DestroyMicroserviceEvent.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/DestroyMicroserviceEvent.java deleted file mode 100644 index 02cc094555d..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/DestroyMicroserviceEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.registry.api.event; - -import org.apache.servicecomb.registry.consumer.MicroserviceVersions; - -public class DestroyMicroserviceEvent { - private MicroserviceVersions microserviceVersions; - - public DestroyMicroserviceEvent(MicroserviceVersions microserviceVersions) { - this.microserviceVersions = microserviceVersions; - } - - public MicroserviceVersions getMicroserviceVersions() { - return microserviceVersions; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/DestroyMicroserviceVersionEvent.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/DestroyMicroserviceVersionEvent.java deleted file mode 100644 index 113f605a32c..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/DestroyMicroserviceVersionEvent.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.registry.api.event; - -import org.apache.servicecomb.registry.consumer.MicroserviceVersion; - -public class DestroyMicroserviceVersionEvent { - private MicroserviceVersion microserviceVersion; - - public DestroyMicroserviceVersionEvent(MicroserviceVersion microserviceVersion) { - this.microserviceVersion = microserviceVersion; - } - - public MicroserviceVersion getMicroserviceVersion() { - return microserviceVersion; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/MicroserviceInstanceChangedEvent.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/MicroserviceInstanceChangedEvent.java deleted file mode 100644 index c850be99e62..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/MicroserviceInstanceChangedEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.registry.api.event; - -import org.apache.servicecomb.registry.api.MicroserviceKey; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.WatchAction; - -/** - * Created by on 2016/12/25. - */ -public class MicroserviceInstanceChangedEvent { - private WatchAction action; - - private MicroserviceKey key; - - private MicroserviceInstance instance; - - public MicroserviceInstance getInstance() { - return instance; - } - - public void setInstance(MicroserviceInstance instance) { - this.instance = instance; - } - - public MicroserviceKey getKey() { - return key; - } - - public void setKey(MicroserviceKey key) { - this.key = key; - } - - public WatchAction getAction() { - return action; - } - - public void setAction(WatchAction action) { - this.action = action; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/MicroserviceInstanceRegisteredEvent.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/MicroserviceInstanceRegisteredEvent.java deleted file mode 100644 index cb5de0c17b8..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/event/MicroserviceInstanceRegisteredEvent.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.registry.api.event; - -/** - * when registration is ready, should post this event. - */ -public class MicroserviceInstanceRegisteredEvent { - private String registrationName; - - private String instanceId; - - // If this event is sent by RegistrationManager, which means all Registration are successful. - private boolean registrationManager; - - public MicroserviceInstanceRegisteredEvent(String registrationName, String instanceId, - boolean registrationManager) { - this.registrationName = registrationName; - this.instanceId = instanceId; - this.registrationManager = registrationManager; - } - - public String getInstanceId() { - return instanceId; - } - - public String getRegistrationName() { - return registrationName; - } - - public boolean isRegistrationManager() { - return registrationManager; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/BasePath.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/BasePath.java deleted file mode 100644 index a83e9c859b7..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/BasePath.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.registry.api.registry; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -/** - * Created by on 2017/3/29. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class BasePath { - private String path; - - private Map property; - - public Map getProperty() { - return property; - } - - public void setProperty(Map property) { - this.property = property; - } - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/Framework.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/Framework.java deleted file mode 100644 index 04c970b5d27..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/Framework.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.registry.api.registry; - -/** - * Created by on 2017/12/20. - */ -public class Framework { - private String name; - - private String version; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/FrameworkVersions.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/FrameworkVersions.java deleted file mode 100644 index dd4bf78e1d6..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/FrameworkVersions.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.registry.api.registry; - -import java.util.ServiceLoader; - -import org.apache.servicecomb.registry.api.Versions; - -public class FrameworkVersions { - private static final ServiceLoader frameworkVersions = ServiceLoader.load(Versions.class); - - public static String allVersions() { - StringBuffer sb = new StringBuffer(); - frameworkVersions.forEach(version -> version.loadVersion().forEach((key, value) -> { - sb.append(key).append(":").append(value).append(";"); - })); - if (sb.length() > 0) { - sb.setLength(sb.length() - 1); - } - return sb.toString(); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java deleted file mode 100644 index e4bc81254b9..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceFactory.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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.registry.api.registry; - -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.APP_MAPPING; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_DEFAULT_REGISTER_BY; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.CONFIG_FRAMEWORK_DEFAULT_NAME; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.SERVICE_MAPPING; -import static org.apache.servicecomb.foundation.common.base.ServiceCombConstants.VERSION_MAPPING; - -import java.util.Map; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.EnvironmentConfiguration; -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.config.BootStrapProperties; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.registry.config.ConfigurePropertyUtils; -import org.apache.servicecomb.registry.config.MicroservicePropertiesLoader; -import org.apache.servicecomb.foundation.common.Version; - -public class MicroserviceFactory { - public Microservice create() { - return create(ConfigUtil.createLocalConfig()); - } - - public Microservice create(Configuration configuration) { - Microservice microservice = createMicroserviceFromConfiguration(configuration); - microservice.setInstance(MicroserviceInstance.createFromDefinition(configuration)); - return microservice; - } - - private Microservice createMicroserviceFromConfiguration(Configuration configuration) { - Microservice microservice = new Microservice(); - - EnvironmentConfiguration envConfig = new EnvironmentConfiguration(); - if (!StringUtils.isEmpty(envConfig.getString(APP_MAPPING)) && - !StringUtils.isEmpty(envConfig.getString(envConfig.getString(APP_MAPPING)))) { - microservice.setAppId(envConfig.getString(envConfig.getString(APP_MAPPING))); - } else { - microservice.setAppId(BootStrapProperties.readApplication(configuration)); - } - if (!StringUtils.isEmpty(envConfig.getString(SERVICE_MAPPING)) && - !StringUtils.isEmpty(envConfig.getString(envConfig.getString(SERVICE_MAPPING)))) { - microservice.setServiceName(envConfig.getString(envConfig.getString(SERVICE_MAPPING))); - } else { - microservice.setServiceName(BootStrapProperties.readServiceName(configuration)); - } - String version; - if (!StringUtils.isEmpty(envConfig.getString(VERSION_MAPPING)) && - !StringUtils.isEmpty(envConfig.getString(envConfig.getString(VERSION_MAPPING)))) { - version = envConfig.getString(envConfig.getString(VERSION_MAPPING)); - } else { - version = BootStrapProperties.readServiceVersion(configuration); - } - // just check version format - new Version(version); - microservice.setVersion(version); - - microservice.setDescription(BootStrapProperties.readServiceDescription(configuration)); - microservice.setLevel(BootStrapProperties.readServiceRole(configuration)); - microservice.setPaths(ConfigurePropertyUtils.getMicroservicePaths(configuration)); - Map propertiesMap = MicroservicePropertiesLoader.INSTANCE.loadProperties(configuration); - microservice.setProperties(propertiesMap); - microservice.setEnvironment(BootStrapProperties.readServiceEnvironment(configuration)); - - // set alias name when allow cross app - if (microservice.allowCrossApp()) { - microservice.setAlias(Microservice.generateAbsoluteMicroserviceName(microservice.getAppId(), - microservice.getServiceName())); - } - - microservice.setFramework(createFramework()); - microservice.setRegisterBy(CONFIG_DEFAULT_REGISTER_BY); - - return microservice; - } - - private Framework createFramework() { - Framework framework = new Framework(); - framework.setName(CONFIG_FRAMEWORK_DEFAULT_NAME); - framework.setVersion(FrameworkVersions.allVersions()); - return framework; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java deleted file mode 100644 index 2c23982ba2e..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceInstance.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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.registry.api.registry; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.StringUtils; -import org.apache.servicecomb.config.BootStrapProperties; -import org.apache.servicecomb.registry.config.InstancePropertiesLoader; -import org.apache.servicecomb.registry.definition.DefinitionConst; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.netflix.config.DynamicPropertyFactory; - -/** - * Created by on 2016/12/5. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class MicroserviceInstance { - // even disconnected from service center - // instanceId will not be changed - // when register to service center again, use the old instanceId. - private String instanceId; - - // service center rule: max length: 64 - private String serviceId; - - private List endpoints = new ArrayList<>(); - - private String hostName; - - private MicroserviceInstanceStatus status = MicroserviceInstanceStatus.UP; - - private Map properties = new HashMap<>(); // reserved key list: region|az|stage|group - - private HealthCheck healthCheck; - - /** - * Will be abandoned, use Microservice Environment instead - */ - @Deprecated - private String environment; - - private String stage; - - private DataCenterInfo dataCenterInfo; - - private String timestamp; - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("instanceId=" + instanceId + ";"); - sb.append("serviceId=" + serviceId + ";"); - sb.append("status=" + status + ";"); - sb.append("endpoints=" + endpoints.toString()); - return sb.toString(); - } - - public String getTimestamp() { - return timestamp; - } - - public void setTimestamp(String timestamp) { - this.timestamp = timestamp; - } - - public String getInstanceId() { - return instanceId; - } - - public void setInstanceId(String instanceId) { - this.instanceId = instanceId; - } - - public MicroserviceInstance instanceId(String instanceId) { - this.instanceId = instanceId; - return this; - } - - public String getServiceId() { - return serviceId; - } - - public void setServiceId(String serviceId) { - this.serviceId = serviceId; - } - - public MicroserviceInstance serviceId(String serviceId) { - this.serviceId = serviceId; - return this; - } - - public String getHostName() { - return hostName; - } - - public void setHostName(String hostName) { - this.hostName = hostName; - } - - public List getEndpoints() { - return endpoints; - } - - public void setEndpoints(List endpoints) { - this.endpoints = endpoints; - } - - public MicroserviceInstanceStatus getStatus() { - return status; - } - - public void setStatus(MicroserviceInstanceStatus status) { - this.status = status; - } - - public Map getProperties() { - return properties; - } - - public void setProperties(Map properties) { - this.properties = properties; - } - - public HealthCheck getHealthCheck() { - return healthCheck; - } - - public void setHealthCheck(HealthCheck healthCheck) { - this.healthCheck = healthCheck; - } - - public String getEnvironment() { - return environment; - } - - public void setEnvironment(String environment) { - this.environment = environment; - } - - @Deprecated - public String getStage() { - return stage; - } - - @Deprecated - public void setStage(String stage) { - this.stage = stage; - } - - public DataCenterInfo getDataCenterInfo() { - return dataCenterInfo; - } - - @Override - public int hashCode() { - return this.instanceId.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof MicroserviceInstance) { - return this.instanceId.equals(((MicroserviceInstance) obj).instanceId); - } - return false; - } - - public void setDataCenterInfo(DataCenterInfo dataCenterInfo) { - this.dataCenterInfo = dataCenterInfo; - } - - // Some properties of microservice instance are dynamic changed, not cover them all now. - public static MicroserviceInstance createFromDefinition(Configuration configuration) { - MicroserviceInstance microserviceInstance = new MicroserviceInstance(); - // default hard coded values - microserviceInstance.setStage(DefinitionConst.DEFAULT_STAGE); - microserviceInstance - .setEnvironment(BootStrapProperties.readServiceInstanceEnvironment(configuration)); - microserviceInstance.setStatus(MicroserviceInstanceStatus - .valueOf(BootStrapProperties.readServiceInstanceInitialStatus())); - HealthCheck healthCheck = new HealthCheck(); - healthCheck.setMode(HealthCheckMode.HEARTBEAT); - microserviceInstance.setHealthCheck(healthCheck); - - // load properties - Map propertiesMap = InstancePropertiesLoader.INSTANCE.loadProperties(configuration); - microserviceInstance.setProperties(propertiesMap); - - // load data center information - loadDataCenterInfo(microserviceInstance); - return microserviceInstance; - } - - private static void loadDataCenterInfo(MicroserviceInstance microserviceInstance) { - String dataCenterName = DynamicPropertyFactory.getInstance() - .getStringProperty("servicecomb.datacenter.name", null) - .get(); - if (StringUtils.isNotEmpty(dataCenterName)) { - DataCenterInfo dataCenterInfo = new DataCenterInfo(); - dataCenterInfo.setName(dataCenterName); - dataCenterInfo - .setRegion( - DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.datacenter.region", null).get()); - dataCenterInfo.setAvailableZone( - DynamicPropertyFactory.getInstance().getStringProperty("servicecomb.datacenter.availableZone", null).get()); - microserviceInstance.setDataCenterInfo(dataCenterInfo); - } - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceStatus.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceStatus.java deleted file mode 100644 index ca043fd9ed7..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/MicroserviceStatus.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.registry.api.registry; - -/** - * Created by on 2016/12/5. - */ -public enum MicroserviceStatus { - UNKNOWN, - UP, - DOWN -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/ServiceCombVersion.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/ServiceCombVersion.java deleted file mode 100644 index 61b8ba0a587..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/ServiceCombVersion.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.registry.api.registry; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.registry.api.Versions; - -public class ServiceCombVersion implements Versions { - - @Override - public Map loadVersion() { - Map map = new HashMap<>(); - map.put("ServiceComb", this.getClass().getPackage().getImplementationVersion()); - - return map; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/WatchAction.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/WatchAction.java deleted file mode 100644 index bc731f4722f..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/api/registry/WatchAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.registry.api.registry; - -import com.fasterxml.jackson.annotation.JsonValue; - -/** - * Created by on 2017/2/21. - */ -public enum WatchAction { - CREATE("CREATE"), - UPDATE("UPDATE"), - // When SC send an EXPIRE action, which means client should clean up all local instance cache and fetch again. - // This usually happens when SC adds new WHITE/BLACK rules or changes TAGS of instance - EXPIRE("EXPIRE"), - DELETE("DELETE"); - - private final String name; - - WatchAction(String name) { - this.name = name; - } - - @JsonValue - public String getName() { - return name; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/CacheEndpoint.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/CacheEndpoint.java deleted file mode 100644 index a36962811de..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/CacheEndpoint.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.registry.cache; - -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; - -public class CacheEndpoint { - // 所属的服务实例 - private final MicroserviceInstance instance; - - private final String endpoint; - - public CacheEndpoint(String endpoint, MicroserviceInstance instance) { - this.endpoint = endpoint; - this.instance = instance; - } - - public String getEndpoint() { - return endpoint; - } - - public MicroserviceInstance getInstance() { - return instance; - } - - public String toString() { - return endpoint; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCache.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCache.java deleted file mode 100644 index d6cf8757610..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCache.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * 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.registry.cache; - -import java.net.URI; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 缓存指定微服务的所有实例 - * 当实例状态变化时,需要重新创建InstanceCache,由外部控制 - */ -public class InstanceCache { - private static final Logger LOGGER = LoggerFactory.getLogger(InstanceCache.class); - - // 引入这个原子变量,是为了避免一个服务长期不用,缓存被删除,下次再初始化的初始版本号,有极小概率等于被删除前的版本号的问题 - // 如果相等,可能会导致其他没感知删除的模块,在更新流程上,遇到问题 - private static final AtomicInteger VERSION = new AtomicInteger(); - - private int cacheVersion; - - private String appId; - - private String microserviceName; - - // 1.0或1.0+或latest等等,只是规则,不一定表示一个确定的版本 - private String microserviceVersionRule; - - // key为instanceId - private Map instanceMap; - - private VersionedCache versionedCache; - - // 缓存CacheEndpoint - private volatile Map> transportMap; - - private Object lockObj = new Object(); - - /** - * 用于初始化场景 - */ - public InstanceCache(String appId, String microserviceName, String microserviceVersionRule, - Map instanceMap) { - cacheVersion = VERSION.getAndIncrement(); - this.appId = appId; - this.microserviceName = microserviceName; - this.microserviceVersionRule = microserviceVersionRule; - this.instanceMap = instanceMap; - this.versionedCache = new VersionedCache() - .name(microserviceVersionRule) - .autoCacheVersion() - .data(instanceMap); - } - - public VersionedCache getVersionedCache() { - return versionedCache; - } - - public boolean cacheChanged(InstanceCache newCache) { - return newCache != null - && newCache.instanceMap != null - && newCache.cacheVersion != cacheVersion; - } - - public Map> getOrCreateTransportMap() { - if (transportMap == null) { - synchronized (lockObj) { - if (transportMap == null) { - transportMap = createTransportMap(); - } - } - } - return transportMap; - } - - protected Map> createTransportMap() { - Map> transportMap = new HashMap<>(); - for (MicroserviceInstance instance : instanceMap.values()) { - // This is only used for service center, not change it now - if (instance.getStatus() != MicroserviceInstanceStatus.UP) { - continue; - } - for (String endpoint : instance.getEndpoints()) { - try { - URI uri = URI.create(endpoint); - String transportName = uri.getScheme(); - - List cacheEndpointList = transportMap.computeIfAbsent(transportName, k -> new ArrayList<>()); - cacheEndpointList.add(new CacheEndpoint(endpoint, instance)); - } catch (Exception e) { - LOGGER.warn("unrecognized address find, ignore " + endpoint); - } - } - } - return transportMap; - } - - public Map getInstanceMap() { - return instanceMap; - } - - public String getMicroserviceName() { - return microserviceName; - } - - public String getMicroserviceVersionRule() { - return microserviceVersionRule; - } - - public String getAppId() { - return appId; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCacheManager.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCacheManager.java deleted file mode 100644 index 7daa947900a..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCacheManager.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.registry.cache; - -import org.apache.servicecomb.foundation.common.cache.VersionedCache; - -public interface InstanceCacheManager { - InstanceCache getOrCreate(String appId, String microserviceName, String microserviceVersionRule); - - VersionedCache getOrCreateVersionedCache(String appId, String microserviceName, String microserviceVersionRule); -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCacheManagerNew.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCacheManagerNew.java deleted file mode 100644 index dbb28d96f84..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/InstanceCacheManagerNew.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.registry.cache; - -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.registry.consumer.AppManager; - -public class InstanceCacheManagerNew implements InstanceCacheManager { - private AppManager appManager; - - public InstanceCacheManagerNew(AppManager appManager) { - this.appManager = appManager; - } - - @Override - public InstanceCache getOrCreate(String appId, String microserviceName, String microserviceVersionRule) { - return appManager.getOrCreateMicroserviceVersionRule(appId, microserviceName, microserviceVersionRule) - .getInstanceCache(); - } - - @Override - public VersionedCache getOrCreateVersionedCache(String appId, String microserviceName, - String microserviceVersionRule) { - return appManager.getOrCreateMicroserviceVersionRule(appId, microserviceName, microserviceVersionRule) - .getVersionedCache(); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/MicroserviceInstanceCache.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/MicroserviceInstanceCache.java deleted file mode 100644 index 09e77023f02..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/cache/MicroserviceInstanceCache.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.registry.cache; - -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.util.concurrent.UncheckedExecutionException; - -/** - * 微服务实例缓存 key为:serviceId@instanceId 缓存limit:1000 缓存老化策略:30分钟没有访问就过期。 - * - */ -public class MicroserviceInstanceCache { - - private static final Logger logger = LoggerFactory.getLogger(MicroserviceInstanceCache.class); - - private static Cache instances = CacheBuilder.newBuilder() - .maximumSize(1000) - .expireAfterAccess(30, TimeUnit.MINUTES) - .build(); - - private static final Cache microservices = CacheBuilder.newBuilder() - .maximumSize(1000) - .expireAfterAccess(30, TimeUnit.MINUTES) - .build(); - - public static Microservice getOrCreate(String serviceId) { - try { - return microservices.get(serviceId, () -> { - Microservice microservice = DiscoveryManager.INSTANCE.getMicroservice(serviceId); - if (microservice == null) { - throw new IllegalArgumentException("service id not exists."); - } - return microservice; - }); - } catch (ExecutionException | UncheckedExecutionException e) { - logger.error("get microservice from cache failed, {}, {}", serviceId, e.getMessage()); - return null; - } - } - - public static MicroserviceInstance getOrCreate(String serviceId, String instanceId) { - try { - String key = String.format("%s@%s", serviceId, instanceId); - return instances.get(key, new Callable() { - - @Override - public MicroserviceInstance call() { - MicroserviceInstance instance = DiscoveryManager.INSTANCE.getMicroserviceInstance(serviceId, instanceId); - if (instance == null) { - throw new IllegalArgumentException("instance id not exists."); - } - return instance; - } - }); - } catch (ExecutionException | UncheckedExecutionException e) { - logger.error("get microservice instance from cache failed, {}, {}", String.format("%s@%s", serviceId, instanceId), - e.getMessage()); - return null; - } - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/AbstractPropertiesLoader.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/AbstractPropertiesLoader.java deleted file mode 100644 index 1944063d236..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/AbstractPropertiesLoader.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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.registry.config; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.registry.api.PropertyExtended; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Loading microservice properties - */ -public abstract class AbstractPropertiesLoader { - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPropertiesLoader.class); - - public Map loadProperties(Configuration configuration) { - Map propertiesMap = new HashMap<>(); - loadPropertiesFromConfigMap(configuration, propertiesMap); - loadPropertiesFromExtendedClass(configuration, propertiesMap); - - return propertiesMap; - } - - abstract protected Map readProperties(Configuration configuration); - - abstract protected String readPropertiesExtendedClass(Configuration configuration); - - private void loadPropertiesFromConfigMap(Configuration configuration, Map propertiesMap) { - propertiesMap.putAll(readProperties(configuration)); - } - - private void loadPropertiesFromExtendedClass(Configuration configuration, Map propertiesMap) { - String extendedPropertyClass = readPropertiesExtendedClass(configuration); - - if (StringUtils.isEmpty(extendedPropertyClass)) { - return; - } - - try { - Class classExternalProperty = Class.forName(extendedPropertyClass); - if (!PropertyExtended.class.isAssignableFrom(classExternalProperty)) { - String errMsg = String.format( - "Define propertyExtendedClass %s in yaml, but not implement the interface PropertyExtended.", - extendedPropertyClass); - LOGGER.error(errMsg); - throw new Error(errMsg); - } - - PropertyExtended instance = (PropertyExtended) classExternalProperty.newInstance(); - Map extendedPropertiesMap = instance.getExtendedProperties(); - if (extendedPropertiesMap != null && !extendedPropertiesMap.isEmpty()) { - propertiesMap.putAll(extendedPropertiesMap); - } - } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { - String errMsg = "Fail to create instance of class: " + extendedPropertyClass; - LOGGER.error(errMsg); - throw new Error(errMsg, e); - } - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/ConfigurePropertyUtils.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/ConfigurePropertyUtils.java deleted file mode 100644 index 7a9f38b6f5d..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/ConfigurePropertyUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.registry.config; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.StringUtils; -import org.apache.servicecomb.config.BootStrapProperties; -import org.apache.servicecomb.foundation.common.utils.ClassLoaderScopeContext; -import org.apache.servicecomb.registry.api.registry.BasePath; -import org.apache.servicecomb.registry.definition.DefinitionConst; - -import com.fasterxml.jackson.databind.type.TypeFactory; -import com.netflix.config.DynamicPropertyFactory; - -import io.vertx.core.json.jackson.DatabindCodec; - -public final class ConfigurePropertyUtils { - private ConfigurePropertyUtils() { - } - - /** - * 获取key包含prefix前缀的所有配置项 - */ - public static Map getPropertiesWithPrefix(String prefix) { - Object config = DynamicPropertyFactory.getBackingConfigurationSource(); - if (!Configuration.class.isInstance(config)) { - return new HashMap<>(); - } - - return getPropertiesWithPrefix((Configuration) config, prefix); - } - - // caller ensure configuration is valid - public static Map getPropertiesWithPrefix(Configuration configuration, String prefix) { - Map propertiesMap = new HashMap<>(); - - Iterator keysIterator = configuration.getKeys(prefix); - while (keysIterator.hasNext()) { - String key = keysIterator.next(); - propertiesMap.put(key.substring(prefix.length() + 1), String.valueOf(configuration.getProperty(key))); - } - return propertiesMap; - } - - public static List getMicroservicePaths(Configuration configuration) { - List configPaths = BootStrapProperties.readServicePaths(configuration); - List basePaths = DatabindCodec.mapper().convertValue( - configPaths, - TypeFactory.defaultInstance().constructCollectionType(List.class, BasePath.class) - ); - for (BasePath basePath : basePaths) { - basePath.setPath(buildPath(basePath.getPath())); - } - return basePaths; - } - - private static String buildPath(String path) { - String prefix = ClassLoaderScopeContext.getClassLoaderScopeProperty(DefinitionConst.URL_PREFIX); - if (StringUtils.isNotEmpty(prefix)) { - if (!path.startsWith(prefix)) { - path = prefix + path; - } - } - return path; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/MicroservicePropertiesLoader.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/MicroservicePropertiesLoader.java deleted file mode 100644 index 2ac8865df17..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/MicroservicePropertiesLoader.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.registry.config; - -import java.util.Map; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.config.BootStrapProperties; - -public final class MicroservicePropertiesLoader extends AbstractPropertiesLoader { - - public static final MicroservicePropertiesLoader INSTANCE = new MicroservicePropertiesLoader(); - - private MicroservicePropertiesLoader() { - } - - @Override - protected Map readProperties(Configuration configuration) { - return BootStrapProperties.readServiceProperties(configuration); - } - - @Override - protected String readPropertiesExtendedClass(Configuration configuration) { - return BootStrapProperties.readServiceExtendedClass(configuration); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/ServiceRegistryCommonConfig.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/ServiceRegistryCommonConfig.java deleted file mode 100644 index f307164c716..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/config/ServiceRegistryCommonConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.registry.config; - -import com.netflix.config.DynamicPropertyFactory; - -public class ServiceRegistryCommonConfig { - private static final String REGISTRY_EMPTY_PROTECTION = "servicecomb.service.registry.instance.empty.protection"; - - private static final String REGISTRY_FILTER_UP_INSTANCES = "servicecomb.service.registry.instance.useUpInstancesOnly"; - - public static boolean isEmptyInstanceProtectionEnabled() { - return - DynamicPropertyFactory.getInstance() - .getBooleanProperty(REGISTRY_EMPTY_PROTECTION, - true).get(); - } - - public static boolean useUpInstancesOnly() { - return - DynamicPropertyFactory.getInstance() - .getBooleanProperty(REGISTRY_FILTER_UP_INSTANCES, - false).get(); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/AppManager.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/AppManager.java deleted file mode 100644 index 720cd10413a..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/AppManager.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.registry.api.event.MicroserviceInstanceChangedEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.eventbus.EventBus; - -public class AppManager { - private static final Logger LOGGER = LoggerFactory.getLogger(AppManager.class); - - // key: appId - private Map apps = new ConcurrentHashMapEx<>(); - - public AppManager() { - getEventBus().register(this); - } - - public EventBus getEventBus() { - return EventManager.getEventBus(); - } - - public Map getApps() { - return apps; - } - - // microserviceName maybe normal name or alias name - public MicroserviceVersionRule getOrCreateMicroserviceVersionRule(String appId, String microserviceName, - String versionRule) { - MicroserviceManager microserviceManager = getOrCreateMicroserviceManager(appId); - - return microserviceManager.getOrCreateMicroserviceVersionRule(microserviceName, versionRule); - } - - public MicroserviceManager getOrCreateMicroserviceManager(String appId) { - return apps.computeIfAbsent(appId, id -> new MicroserviceManager(this, appId)); - } - - public CompletableFuture getOrCreateMicroserviceVersionsAsync(String appId - , String microserviceName) { - MicroserviceManager microserviceManager = getOrCreateMicroserviceManager(appId); - return microserviceManager.getOrCreateMicroserviceVersionsAsync(microserviceName); - } - - public MicroserviceVersions getOrCreateMicroserviceVersions(String appId, String microserviceName) { - MicroserviceManager microserviceManager = getOrCreateMicroserviceManager(appId); - return microserviceManager.getOrCreateMicroserviceVersions(microserviceName); - } - - public void onMicroserviceInstanceChanged(MicroserviceInstanceChangedEvent changedEvent) { - MicroserviceManager microserviceManager = apps.get(changedEvent.getKey().getAppId()); - if (microserviceManager == null) { - return; - } - - microserviceManager.onMicroserviceInstanceChanged(changedEvent); - } - - public void pullInstances() { - for (MicroserviceManager microserviceManager : apps.values()) { - microserviceManager.pullInstances(); - } - } - - public void safePullInstances() { - try { - pullInstances(); - } catch (Exception e) { - LOGGER.error("failed to pull instances.", e); - } - } - - public void markWaitingDelete(String appId, String microserviceName) { - Optional.ofNullable(apps.get(appId)) - .map(microserviceManager -> microserviceManager.getVersionsByName().get(microserviceName)) - .ifPresent(MicroserviceVersions::markWaitingDelete); - } -} \ No newline at end of file diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceInstancePing.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceInstancePing.java deleted file mode 100644 index 0f4e1fc9b3b..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceInstancePing.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.registry.consumer; - -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; - -/** - * SPI interface to ping microservice instance status in Instance Protection Mode, which means - * protection of instance removal and usually used in scenarios where instances are fixed and changed rarely. - */ -public interface MicroserviceInstancePing { - int getOrder(); - - /** - * check if this instance if valid to use - * @param instance - * @return - */ - boolean ping(MicroserviceInstance instance); -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceManager.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceManager.java deleted file mode 100644 index d8a91fee182..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceManager.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.vertx.executor.SinglePoolBlockingExecutor; -import org.apache.servicecomb.registry.api.event.MicroserviceInstanceChangedEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.vertx.core.Vertx; - -public class MicroserviceManager { - private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceManager.class); - - private AppManager appManager; - - private String appId; - - // key: microserviceName - private Map versionsByName = new ConcurrentHashMapEx<>(); - - private Object lock = new Object(); - - public MicroserviceManager(AppManager appManager, String appId) { - this.appManager = appManager; - this.appId = appId; - } - - public Map getVersionsByName() { - return versionsByName; - } - - /** - * update instance information triggered by first timeout pull - */ - public MicroserviceVersions getOrCreateMicroserviceVersions(String microserviceName) { - // do not use ConcurrentHashMap computeIfAbsent for versionsByName - // because: when create MicroserviceVersions, one creation may depend on another - // MicroserviceVersions. And pullInstances will create a new MicroserviceVersions. - // Calling ConcurrentHashMap computeIfAbsent inside will get deadlock. - MicroserviceVersions microserviceVersions = versionsByName.get(microserviceName); - if (microserviceVersions == null) { - synchronized (lock) { - microserviceVersions = versionsByName.get(microserviceName); - if (microserviceVersions == null) { - microserviceVersions = new MicroserviceVersions(appManager, appId, microserviceName); - microserviceVersions.pullInstances(); - versionsByName.put(microserviceName, microserviceVersions); - } - } - } - - tryRemoveInvalidMicroservice(microserviceVersions); - - return microserviceVersions; - } - - public CompletableFuture getOrCreateMicroserviceVersionsAsync(String microserviceName) { - MicroserviceVersions microserviceVersions = versionsByName.get(microserviceName); - if (microserviceVersions == null) { - if (Vertx.currentContext() == null) { - // not in event-loop, execute in current thread - return CompletableFuture.completedFuture(getOrCreateMicroserviceVersions(microserviceName)); - } else { - // execute in an single thread pool to make sure make less requests to service center - return CompletableFuture.supplyAsync(() -> getOrCreateMicroserviceVersions(microserviceName), - SinglePoolBlockingExecutor.create()); - } - } else { - // here do not need switch to another thread, can improve performance - tryRemoveInvalidMicroservice(microserviceVersions); - return CompletableFuture.completedFuture(microserviceVersions); - } - } - - private void tryRemoveInvalidMicroservice(MicroserviceVersions microserviceVersions) { - if (!microserviceVersions.isWaitingDelete()) { - return; - } - - // remove this microservice if it does not exist or not registered in order to get it back when access it again - String microserviceName = microserviceVersions.getMicroserviceName(); - if (versionsByName.remove(microserviceName) != null) { - microserviceVersions.destroy(); - LOGGER.info("remove microservice, appId={}, microserviceName={}.", appId, microserviceName); - } - } - - public MicroserviceVersionRule getOrCreateMicroserviceVersionRule(String microserviceName, - String versionRule) { - MicroserviceVersions microserviceVersions = getOrCreateMicroserviceVersions(microserviceName); - - return microserviceVersions.getOrCreateMicroserviceVersionRule(versionRule); - } - - /** - * update instance information triggered by scheduler - */ - public void pullInstances() { - synchronized (lock) { - for (MicroserviceVersions microserviceVersions : versionsByName.values()) { - microserviceVersions.pullInstances(); - - tryRemoveInvalidMicroservice(microserviceVersions); - } - } - } - - /** - * update instance information triggered by event - */ - public void onMicroserviceInstanceChanged(MicroserviceInstanceChangedEvent changedEvent) { - synchronized (lock) { - for (MicroserviceVersions microserviceVersions : versionsByName.values()) { - microserviceVersions.onMicroserviceInstanceChanged(changedEvent); - - tryRemoveInvalidMicroservice(microserviceVersions); - } - } - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java deleted file mode 100644 index 2aca65e41d2..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersion.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.Collection; -import java.util.List; - -import org.apache.servicecomb.foundation.common.VendorExtensions; -import org.apache.servicecomb.registry.api.event.CreateMicroserviceVersionEvent; -import org.apache.servicecomb.registry.api.event.DestroyMicroserviceVersionEvent; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.foundation.common.Version; - -public class MicroserviceVersion { - protected AppManager appManager; - - protected MicroserviceVersions microserviceVersions; - - // because of cross app invoke - // microserviceName not always equals microservice.serviceName - protected String microserviceName; - - protected Version version; - - protected Microservice microservice; - - protected Collection instances; - - private VendorExtensions vendorExtensions = new VendorExtensions(); - - public MicroserviceVersion(MicroserviceVersions microserviceVersions, String microserviceId, - String microserviceName, - Collection instances) { - Microservice microservice = DiscoveryManager.INSTANCE.getMicroservice(microserviceId); - if (microservice == null) { - throw new IllegalStateException( - String.format("failed to query by microserviceId '%s' from ServiceCenter.", microserviceId)); - } - - init(microserviceVersions, microservice, microserviceName, instances); - appManager.getEventBus().post(new CreateMicroserviceVersionEvent(this)); - } - - public MicroserviceVersion(MicroserviceVersions microserviceVersions, - Microservice microservice, String microserviceName, - Collection instances) { - init(microserviceVersions, microservice, microserviceName, instances); - appManager.getEventBus().post(new CreateMicroserviceVersionEvent(this)); - } - - protected void init(MicroserviceVersions microserviceVersions, Microservice microservice, - String microserviceName, - Collection instances) { - this.appManager = microserviceVersions.getAppManager(); - this.microserviceVersions = microserviceVersions; - this.microservice = microservice; - this.microserviceName = microserviceName; - this.instances = instances; - this.version = new Version(microservice.getVersion()); - } - - public MicroserviceVersions getMicroserviceVersions() { - return microserviceVersions; - } - - public Collection getInstances() { - return instances; - } - - public void setInstances(List instances) { - this.instances = instances; - } - - public String getMicroserviceName() { - return microserviceName; - } - - public String getMicroserviceId() { - return microservice.getServiceId(); - } - - public Microservice getMicroservice() { - return microservice; - } - - public Version getVersion() { - return version; - } - - public VendorExtensions getVendorExtensions() { - return vendorExtensions; - } - - public void destroy() { - appManager.getEventBus().post(new DestroyMicroserviceVersionEvent(this)); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersionRule.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersionRule.java deleted file mode 100644 index d123ffe07ef..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersionRule.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.foundation.common.utils.StringBuilderUtils; -import org.apache.servicecomb.registry.api.registry.Framework; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.InstanceCache; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.apache.servicecomb.registry.version.VersionRule; -import org.apache.servicecomb.registry.version.VersionRuleUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MicroserviceVersionRule { - private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceVersionRule.class); - - private final String appId; - - private final String microserviceName; - - private final VersionRule versionRule; - - // wrap variable data to make them atomic - private MicroserviceVersionRuleData data; - - public MicroserviceVersionRule(String appId, String microserviceName, String strVersionRule) { - this.appId = appId; - this.microserviceName = microserviceName; - this.versionRule = VersionRuleUtils.getOrCreate(strVersionRule); - - data = createEmptyData(); - } - - public String getAppId() { - return appId; - } - - public String getMicroserviceName() { - return microserviceName; - } - - public VersionRule getVersionRule() { - return versionRule; - } - - public T getLatestMicroserviceVersion() { - return data.getLatestMicroserviceVersion(); - } - - public Map getInstances() { - return data.instances; - } - - public InstanceCache getInstanceCache() { - return data.instanceCache; - } - - public VersionedCache getVersionedCache() { - return data.versionedCache; - } - - public MicroserviceVersionRuleData getData() { - return data; - } - - /** - * - * @param allVersions all versions even not belongs to this rule - * @param allInstances all instances even not belongs to this rule, related MicroserviceVersion always exists - */ - public void update(Map allVersions, Collection allInstances) { - if (allInstances == null) { - allInstances = Collections.emptyList(); - } - - if (DefinitionConst.VERSION_RULE_LATEST.equals(versionRule.getVersionRule())) { - data = createDataByLatestRule(allVersions, allInstances); - } else { - data = createDataByOtherRule(allVersions, allInstances); - } - - printData(data, allVersions.size(), allInstances.size()); - } - - private void printData(MicroserviceVersionRuleData data, int inputVersionCount, int inputInstanceCount) { - String latestVersion = data.latestVersion == null ? null : data.latestVersion.getVersion().getVersion(); - if (data.getInstances().isEmpty()) { - LOGGER.info( - "update instances to be empty caused by version rule, appId={}, microserviceName={}, versionRule={}" - + ", latestVersion={}, inputVersionCount={}, inputInstanceCount={}", - appId, microserviceName, versionRule.getVersionRule(), - latestVersion, inputVersionCount, inputInstanceCount); - return; - } - - StringBuilder sb = new StringBuilder(); - StringBuilderUtils - .appendLine(sb, - "update instances, appId=%s, microserviceName=%s, versionRule=%s" - + ", latestVersion=%s, inputVersionCount=%s, inputInstanceCount=%s", - appId, microserviceName, versionRule.getVersionRule(), - latestVersion, inputVersionCount, inputInstanceCount); - - int idx = 0; - for (MicroserviceInstance instance : data.getInstances().values()) { - MicroserviceVersion microserviceVersion = data.versions.get(instance.getServiceId()); - Microservice microservice = microserviceVersion.getMicroservice(); - Framework framework = microservice.getFramework(); - String frameworkName = framework == null ? "unknown" : framework.getName(); - String frameworkVersion = framework == null ? "unknown" : framework.getVersion(); - - StringBuilderUtils.appendLine(sb, - " %d.instanceId=%s, status=%s, version=%s, endpoints=%s, environment=%s, framework.name=%s, framework.version=%s", - idx, - instance.getInstanceId(), instance.getStatus(), microserviceVersion.getVersion(), instance.getEndpoints(), - microservice.getEnvironment(), frameworkName, frameworkVersion); - idx++; - } - - LOGGER.info(StringBuilderUtils.deleteLast(sb, 1).toString()); - } - - private void initData(MicroserviceVersionRuleData data) { - if (data.latestVersion == null) { - data.latestVersion = findLatest(data.versions, data.instances.values()); - } - - data.instanceCache = new InstanceCache(appId, microserviceName, versionRule.getVersionRule(), data.instances); - data.versionedCache = new VersionedCache() - .name(versionRule.getVersionRule()) - .autoCacheVersion() - .data(data.instances); - } - - private MicroserviceVersionRuleData createEmptyData() { - MicroserviceVersionRuleData data = new MicroserviceVersionRuleData(); - data.versions = Collections.emptyMap(); - data.instances = Collections.emptyMap(); - initData(data); - return data; - } - - private MicroserviceVersion findLatest(Map allVersions, - Collection allInstances) { - if (allInstances.isEmpty()) { - return allVersions.isEmpty() ? null : allVersions.values().stream() - .max(Comparator.comparing(MicroserviceVersion::getVersion)) - .get(); - } - - MicroserviceVersion latestVersion = null; - for (MicroserviceInstance instance : allInstances) { - // never to be null - MicroserviceVersion version = allVersions.get(instance.getServiceId()); - if (latestVersion == null || latestVersion.version.compareTo(version.version) < 0) { - latestVersion = version; - } - } - return latestVersion; - } - - private MicroserviceVersionRuleData createDataByLatestRule(Map allVersions, - Collection allInstances) { - // find latest - MicroserviceVersion latestVersion = findLatest(allVersions, allInstances); - if (latestVersion == null) { - return createEmptyData(); - } - - MicroserviceVersionRuleData data = new MicroserviceVersionRuleData(); - - String serviceId = latestVersion.getMicroservice().getServiceId(); - data.latestVersion = latestVersion; - data.versions = Collections.singletonMap(serviceId, latestVersion); - data.instances = allInstances.stream() - .filter(instance -> instance.getServiceId().equals(serviceId)) - .collect(Collectors.toMap(MicroserviceInstance::getInstanceId, Function.identity())); - data.instances = Collections.unmodifiableMap(data.instances); - - initData(data); - - return data; - } - - private MicroserviceVersionRuleData createDataByOtherRule(Map allVersions, - Collection allInstances) { - MicroserviceVersionRuleData data = new MicroserviceVersionRuleData(); - - // filter versions - data.versions = allVersions.values().stream() - .filter(v -> versionRule.isAccept(v.version)) - .collect(Collectors.toMap(MicroserviceVersion::getMicroserviceId, Function.identity())); - data.versions = Collections.unmodifiableMap(data.versions); - if (data.versions.isEmpty()) { - return createEmptyData(); - } - - // filter instances - data.instances = allInstances.stream() - .filter(instance -> data.versions.containsKey(instance.getServiceId())) - .collect(Collectors.toMap(MicroserviceInstance::getInstanceId, Function.identity())); - data.instances = Collections.unmodifiableMap(data.instances); - - initData(data); - - return data; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersionRuleData.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersionRuleData.java deleted file mode 100644 index 04371bce9fb..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersionRuleData.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.Map; - -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.InstanceCache; - -public class MicroserviceVersionRuleData { - // if instances is not empty, latestVersion is relate to instances - // if instances is empty, latestVersion is relate to versions - MicroserviceVersion latestVersion; - - // key is microserviceId - Map versions; - - // key is instanceId - Map instances; - - InstanceCache instanceCache; - - VersionedCache versionedCache; - - @SuppressWarnings("unchecked") - public T getLatestMicroserviceVersion() { - return (T) latestVersion; - } - - public Map getVersions() { - return versions; - } - - public Map getInstances() { - return instances; - } - - public InstanceCache getInstanceCache() { - return instanceCache; - } - - public VersionedCache getVersionedCache() { - return versionedCache; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersions.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersions.java deleted file mode 100644 index 7aaa49566cd..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/MicroserviceVersions.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; - -import org.apache.servicecomb.foundation.common.VendorExtensions; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.event.CreateMicroserviceEvent; -import org.apache.servicecomb.registry.api.event.DestroyMicroserviceEvent; -import org.apache.servicecomb.registry.api.event.MicroserviceInstanceChangedEvent; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstances; -import org.apache.servicecomb.registry.config.ServiceRegistryCommonConfig; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.apache.servicecomb.registry.definition.MicroserviceNameParser; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MicroserviceVersions { - private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceVersions.class); - - protected AppManager appManager; - - protected String appId; - - protected String shortName; - - protected String microserviceName; - - // revision and pulledInstances directly equals to SC's response - protected String revision = null; - - private List pulledInstances; - - private MicroserviceInstances lastPulledResult; - - // instances not always equals to pulledInstances - // in the future: - // pulledInstances means all instance - // instances means available instance - Collection instances; - - // key is service id - Map versions = new ConcurrentHashMapEx<>(); - - // key is version rule - Map versionRules = new ConcurrentHashMapEx<>(); - - // process pulled instances and create versionRule must be protected by lock - // otherwise maybe lost instance or version in versionRule - private final Object lock = new Object(); - - private long lastPullTime = 0; - - private boolean waitingDelete = false; - - private VendorExtensions vendorExtensions = new VendorExtensions(); - - public MicroserviceVersions(AppManager appManager, String appId, String microserviceName) { - this.appManager = appManager; - this.appId = appId; - this.microserviceName = microserviceName; - this.shortName = new MicroserviceNameParser(appId, microserviceName).getShortName(); - - appManager.getEventBus().post(new CreateMicroserviceEvent(this)); - - LOGGER.info("create MicroserviceVersions, appId={}, microserviceName={}.", - appId, - microserviceName); - } - - public boolean isWaitingDelete() { - return waitingDelete; - } - - public MicroserviceVersions markWaitingDelete() { - this.waitingDelete = true; - return this; - } - - public AppManager getAppManager() { - return appManager; - } - - public String getAppId() { - return appId; - } - - public String getMicroserviceName() { - return microserviceName; - } - - public String getShortName() { - return shortName; - } - - public Map getVersions() { - return versions; - } - - @SuppressWarnings("unchecked") - public T getVersion(String serviceId) { - return (T) versions.get(serviceId); - } - - public String getRevision() { - return revision; - } - - public void setRevision(String revision) { - this.revision = revision; - } - - public List getPulledInstances() { - return pulledInstances; - } - - public long getLastPullTime() { - return lastPullTime; - } - - public MicroserviceInstances getLastPulledResult() { - return lastPulledResult; - } - - public VendorExtensions getVendorExtensions() { - return vendorExtensions; - } - - public void pullInstances() { - lastPullTime = System.currentTimeMillis(); - MicroserviceInstances microserviceInstances = findServiceInstances(); - lastPulledResult = microserviceInstances; - if (microserviceInstances == null) { - // pulled failed, did not get anything - // will not do anything, consumers will use existing instances - return; - } - if (microserviceInstances.isMicroserviceNotExist()) { - // pulled failed, SC said target not exist - waitingDelete = true; - return; - } - - if (null != revision && revision.equals(microserviceInstances.getRevision())) { - return; - } - - pulledInstances = microserviceInstances.getInstancesResponse().getInstances(); - pulledInstances.sort(Comparator.comparing(MicroserviceInstance::getInstanceId)); - String rev = microserviceInstances.getRevision(); - - safeSetInstances(pulledInstances, rev); - } - - protected MicroserviceInstances findServiceInstances() { - return DiscoveryManager.INSTANCE.findServiceInstances(appId, - microserviceName, - DefinitionConst.VERSION_RULE_ALL, - revision); - } - - protected void safeSetInstances(List pulledInstances, String rev) { - try { - List filteredInstance = pulledInstances; - // 增加一个配置项只使用 `UP` 实例。 在使用 `TESTING` 进行拨测, 并且配置了 - // servicecomb.references.version-rule=latest 场景,需要保证不使用 - // `TESTING` 实例。 不能依赖 InstanceStatusDiscoveryFilter, 避免 - // 构建的 VersionRule 实例列表为空。 - if (ServiceRegistryCommonConfig.useUpInstancesOnly()) { - filteredInstance = pulledInstances.stream().filter(item -> MicroserviceInstanceStatus.UP == item.getStatus()) - .collect(Collectors.toList()); - } - setInstances(filteredInstance, rev); - } catch (Throwable e) { - waitingDelete = true; - LOGGER.error("Failed to setInstances, appId={}, microserviceName={}.", - getAppId(), - getMicroserviceName(), - e); - } - } - - static class MergedInstances { - // key is microserviceId - Map> microserviceIdMap = new HashMap<>(); - - // key is instanceId - Map instanceIdMap = new HashMap<>(); - - void addInstance(MicroserviceInstance instance) { - instanceIdMap.put(instance.getInstanceId(), instance); - microserviceIdMap - .computeIfAbsent(instance.getServiceId(), key -> new ArrayList<>()) - .add(instance); - } - } - - private void setInstances(List pulledInstances, String rev) { - synchronized (lock) { - MergedInstances mergedInstances = mergeInstances(pulledInstances, instances); - instances = mergedInstances.instanceIdMap.values(); - // clear cache - versions.entrySet().forEach(versionEntry -> versionEntry.getValue().setInstances(new ArrayList<>())); - for (Entry> entry : mergedInstances.microserviceIdMap.entrySet()) { - // ensure microserviceVersion exists - versions.computeIfAbsent(entry.getKey(), - microserviceId -> createMicroserviceVersion(microserviceId, entry.getValue())) - .setInstances(entry.getValue()); - } - - for (MicroserviceVersionRule microserviceVersionRule : versionRules.values()) { - microserviceVersionRule.update(versions, instances); - } - revision = rev; - } - } - - protected MicroserviceVersion createMicroserviceVersion(String microserviceId, List instances) { - return new MicroserviceVersion(this, microserviceId, microserviceName, instances); - } - - private MergedInstances mergeInstances(List pulledInstances, - Collection inUseInstances) { - MergedInstances mergedInstances = new MergedInstances(); - pulledInstances.stream().forEach(mergedInstances::addInstance); - MicroserviceInstancePing ping = SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class); - - if (pulledInstances.isEmpty() && inUseInstances != null && ServiceRegistryCommonConfig - .isEmptyInstanceProtectionEnabled()) { - - inUseInstances.stream().forEach(instance -> { - if (!mergedInstances.instanceIdMap.containsKey(instance.getInstanceId())) { - if (ping.ping(instance)) { - mergedInstances.addInstance(instance); - } - } - }); - } - - return mergedInstances; - } - - public MicroserviceVersionRule getOrCreateMicroserviceVersionRule(String versionRule) { - // do not use computeIfAbsent - MicroserviceVersionRule microserviceVersionRule = versionRules.get(versionRule); - if (microserviceVersionRule == null) { - synchronized (lock) { - microserviceVersionRule = versionRules.computeIfAbsent(versionRule, this::createAndInitMicroserviceVersionRule); - } - } - - return microserviceVersionRule; - } - - protected MicroserviceVersionRule createAndInitMicroserviceVersionRule(String strVersionRule) { - LOGGER.info("create MicroserviceVersionRule, appId={}, microserviceName={}, versionRule={}.", - appId, - microserviceName, - strVersionRule); - - MicroserviceVersionRule microserviceVersionRule = - new MicroserviceVersionRule(appId, microserviceName, strVersionRule); - microserviceVersionRule.update(versions, instances); - return microserviceVersionRule; - } - - public void onMicroserviceInstanceChanged(MicroserviceInstanceChangedEvent changedEvent) { - if (!isEventAccept(changedEvent)) { - return; - } - // pull instances always replace old instances, not append - // - // pull result and watch event sequence is not defined even inside SC. - // it's not safe to trust the event, so we just send a new pull request - // - // CREATE/UPDATE: - // if pull 1/2/3, and then add 4, but "add 4" received before pull result, will lost 4. - // DELETE: - // if pull 1/2/3, and then delete 3, but "delete 3" received before pull result, will have wrong 3. - // EXPIRE:: - // black/white config in SC changed, we must refresh all data from sc. - pullInstances(); - } - - protected boolean isEventAccept(MicroserviceInstanceChangedEvent changedEvent) { - return (appId.equals(changedEvent.getKey().getAppId()) && - microserviceName.equals(changedEvent.getKey().getServiceName())) || - microserviceName.equals( - changedEvent.getKey().getAppId() + DefinitionConst.APP_SERVICE_SEPARATOR + changedEvent.getKey() - .getServiceName()); - } - - public void destroy() { - for (MicroserviceVersion microserviceVersion : versions.values()) { - microserviceVersion.destroy(); - } - - appManager.getEventBus().post(new DestroyMicroserviceEvent(this)); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/SimpleMicroserviceInstancePing.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/SimpleMicroserviceInstancePing.java deleted file mode 100644 index 48fd1d6bb52..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/SimpleMicroserviceInstancePing.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.registry.consumer; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; - -import org.apache.servicecomb.foundation.common.net.IpPort; -import org.apache.servicecomb.foundation.common.net.NetUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; - -/** - * Simple implementation of .MicroserviceInstancePing using telnet - */ -public class SimpleMicroserviceInstancePing implements MicroserviceInstancePing { - @Override - public int getOrder() { - return 100; - } - - @Override - public boolean ping(MicroserviceInstance instance) { - if (instance.getEndpoints() != null && instance.getEndpoints().size() > 0) { - IpPort ipPort = NetUtils.parseIpPortFromURI(instance.getEndpoints().get(0)); - try (Socket s = new Socket()) { - s.connect(new InetSocketAddress(ipPort.getHostOrIp(), ipPort.getPort()), 3000); - return true; - } catch (IOException e) { - // ignore this error - } - } - return false; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java deleted file mode 100644 index dae01c73cce..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/consumer/StaticMicroserviceVersions.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.registry.consumer; - -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.FindInstancesResponse; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstances; -import org.apache.servicecomb.foundation.common.Version; -import org.apache.servicecomb.swagger.SwaggerUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.ImmutableMap; - -import io.swagger.models.Swagger; - -public class StaticMicroserviceVersions extends MicroserviceVersions { - private static final Logger LOGGER = LoggerFactory.getLogger(StaticMicroserviceVersions.class); - - protected final Microservice microservice = new Microservice(); - - protected final MicroserviceInstances microserviceInstances = new MicroserviceInstances(); - - public StaticMicroserviceVersions(AppManager appManager, String appId, String microserviceName) { - super(appManager, appId, microserviceName); - } - - public StaticMicroserviceVersions init(Class schemaIntfCls, String version, - List instances) { - return init(ImmutableMap.of(microserviceName, schemaIntfCls), version, instances); - } - - public StaticMicroserviceVersions init(Map> schemaByIdMap, String version, - List instances) { - createMicroservice(version); - addSchemas(schemaByIdMap); - addInstances(instances); - pullInstances(); - - return this; - } - - protected void createMicroservice(String version) { - String environment = RegistrationManager.INSTANCE.getMicroservice().getEnvironment(); - - microservice.setAppId(this.getAppId()); - microservice.setServiceName(this.getShortName()); - microservice.setVersion(new Version(version).getVersion()); - microservice.setServiceId(this.getAppId() + "-" - + environment + "-" - + this.getMicroserviceName() + "-" - + microservice.getVersion()); - microservice.setEnvironment(environment); - } - - protected void addSchemas(Map> schemaByIdMap) { - schemaByIdMap.forEach(this::addSchema); - } - - protected void addSchema(String schemaId, Class schemaClass) { - Swagger swagger = RegistrationManager.INSTANCE.getSwaggerLoader() - .registerSwagger(appId, shortName, schemaId, schemaClass); - String swaggerContent = SwaggerUtils.swaggerToString(swagger); - LOGGER.debug("generate swagger for 3rd party service [{}], swagger: {}", microserviceName, swaggerContent); - microservice.addSchema(schemaId, swaggerContent); - } - - protected void addInstances(List instances) { - for (int idx = 0; idx < instances.size(); idx++) { - MicroserviceInstance instance = instances.get(idx); - instance.setServiceId(microservice.getServiceId()); - instance.setInstanceId(microservice.getServiceId() + "-" + idx); - } - microserviceInstances.setMicroserviceNotExist(false); - microserviceInstances.setInstancesResponse(new FindInstancesResponse()); - microserviceInstances.getInstancesResponse().setInstances(instances); - } - - @Override - protected MicroserviceInstances findServiceInstances() { - // Only refreshed for the first time - microserviceInstances.setNeedRefresh(revision == null); - microserviceInstances.setRevision("1"); - return microserviceInstances; - } - - @Override - protected MicroserviceVersion createMicroserviceVersion(String microserviceId, List instances) { - return new MicroserviceVersion(this, microservice, microserviceName, instances); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/DefinitionConst.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/DefinitionConst.java index deedacd1bb6..528caaafde9 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/DefinitionConst.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/DefinitionConst.java @@ -33,11 +33,5 @@ public interface DefinitionConst { String INSTANCE_PUBKEY_PRO = "publickey"; - String REGISTER_URL_PREFIX = "servicecomb.service.registry.registerUrlPrefix"; - - String REGISTER_SERVICE_PATH = "servicecomb.service.registry.registerPath"; - - String REGISTRY_APP_ID = "default"; - - String REGISTRY_SERVICE_NAME = "SERVICECENTER"; + String REGISTER_URL_PREFIX = "servicecomb.registry.registerUrlPrefix"; } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/MicroserviceNameParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/MicroserviceNameParser.java index be1c92faaea..e99afdbf8be 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/MicroserviceNameParser.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/definition/MicroserviceNameParser.java @@ -17,25 +17,14 @@ package org.apache.servicecomb.registry.definition; /** - *
- *   1. if microserviceName format is app:name, then will ignore defaultAppId
- *     appId = app
- *     shortName = name
- *     microserviceName = app:name
- *   2. if microserviceName format is name
- *     appId = defaultAppId
- *     shortName = name
- *     microserviceName = name
- * 
+ * Parse application and microservice from join name. + * + * 1. microserviceName + * 2. application:microserviceName */ public class MicroserviceNameParser { private String appId; - // always not include appId - private String shortName; - - // inside app: equals to shortName - // cross app: appId:shortName private String microserviceName; public MicroserviceNameParser(String defaultAppId, String microserviceName) { @@ -43,27 +32,21 @@ public MicroserviceNameParser(String defaultAppId, String microserviceName) { } private void parseMicroserviceName(String defaultAppId, String microserviceName) { - this.microserviceName = microserviceName; - int idxAt = microserviceName.indexOf(DefinitionConst.APP_SERVICE_SEPARATOR); if (idxAt == -1) { this.appId = defaultAppId; - this.shortName = microserviceName; + this.microserviceName = microserviceName; return; } this.appId = microserviceName.substring(0, idxAt); - this.shortName = microserviceName.substring(idxAt + 1); + this.microserviceName = microserviceName.substring(idxAt + 1); } public String getAppId() { return appId; } - public String getShortName() { - return shortName; - } - public String getMicroserviceName() { return microserviceName; } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractDiscoveryFilter.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractDiscoveryFilter.java index 36e88770ee6..f274799c30e 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractDiscoveryFilter.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractDiscoveryFilter.java @@ -17,14 +17,25 @@ package org.apache.servicecomb.registry.discovery; -import java.util.HashMap; +import java.util.ArrayList; +import org.apache.servicecomb.config.DynamicProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; public abstract class AbstractDiscoveryFilter implements DiscoveryFilter { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDiscoveryFilter.class); + protected Boolean enabled; + + protected DynamicProperties dynamicProperties; + + @Autowired + public void setDynamicProperties(DynamicProperties dynamicProperties) { + this.dynamicProperties = dynamicProperties; + } + @Override public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode parent) { if (!parent.childrenInited()) { @@ -39,8 +50,8 @@ public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode p String childName = findChildName(context, parent); DiscoveryTreeNode node = parent.child(childName); if (node == null) { - LOGGER.warn("discovery filter {} return null.", this.getClass().getName()); - return new DiscoveryTreeNode().subName(parent, "empty").data(new HashMap<>()); + LOGGER.warn("discovery filter {}/{} return null.", this.getClass().getSimpleName(), childName); + return new DiscoveryTreeNode().subName(parent, "empty").data(new ArrayList<>()); } return node; } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractEndpointDiscoveryFilter.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractEndpointDiscoveryFilter.java index 1aa2d61558b..f4b464f0097 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractEndpointDiscoveryFilter.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractEndpointDiscoveryFilter.java @@ -17,12 +17,10 @@ package org.apache.servicecomb.registry.discovery; -import java.net.URI; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.foundation.common.net.URIEndpointObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +29,10 @@ public abstract class AbstractEndpointDiscoveryFilter implements DiscoveryFilter private static final String ALL_TRANSPORT = ""; + private static final String WEBSOCKET_TRANSPORT = "websocket"; + + private static final String REST_TRANSPORT = "rest"; + @Override public boolean isGroupingFilter() { return true; @@ -43,20 +45,23 @@ public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode p .computeIfAbsent(expectTransportName, etn -> createDiscoveryTreeNode(expectTransportName, context, parent)); } - @SuppressWarnings("unchecked") protected DiscoveryTreeNode createDiscoveryTreeNode(String expectTransportName, DiscoveryContext context, DiscoveryTreeNode parent) { List endpoints = new ArrayList<>(); - for (MicroserviceInstance instance : ((Map) parent.data()).values()) { + List instances = parent.data(); + for (StatefulDiscoveryInstance instance : instances) { for (String endpoint : instance.getEndpoints()) { try { - URI uri = URI.create(endpoint); - String transportName = uri.getScheme(); - if (!isTransportNameMatch(transportName, expectTransportName)) { + URIEndpointObject endpointObject = new URIEndpointObject(endpoint); + String transPortName = endpointObject.getSchema(); + if (endpointObject.isWebsocketEnabled() && WEBSOCKET_TRANSPORT.equals(expectTransportName)) { + transPortName = WEBSOCKET_TRANSPORT; + } + if (!isTransportNameMatch(transPortName, expectTransportName)) { continue; } - Object objEndpoint = createEndpoint(context, transportName, endpoint, instance); + Object objEndpoint = createEndpoint(context, transPortName, endpoint, instance); if (objEndpoint == null) { continue; } @@ -74,11 +79,14 @@ protected DiscoveryTreeNode createDiscoveryTreeNode(String expectTransportName, } protected boolean isTransportNameMatch(String transportName, String expectTransportName) { - return ALL_TRANSPORT.equals(expectTransportName) || transportName.equals(expectTransportName); + if (ALL_TRANSPORT.equals(expectTransportName)) { + return true; + } + return transportName.equals(expectTransportName); } protected abstract String findTransportName(DiscoveryContext context, DiscoveryTreeNode parent); protected abstract Object createEndpoint(DiscoveryContext context, String transportName, String endpoint, - MicroserviceInstance instance); + StatefulDiscoveryInstance instance); } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractGroupDiscoveryFilter.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractGroupDiscoveryFilter.java new file mode 100644 index 00000000000..b76d860903d --- /dev/null +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/AbstractGroupDiscoveryFilter.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.registry.discovery; + +public abstract class AbstractGroupDiscoveryFilter extends AbstractDiscoveryFilter { + @Override + public boolean isGroupingFilter() { + return true; + } + + protected abstract String groupsSizeParameter(); + + protected abstract String contextParameter(); + + protected abstract String groupPrefix(); + + @Override + protected String findChildName(DiscoveryContext context, DiscoveryTreeNode parent) { + Integer level = context.getContextParameter(contextParameter()); + Integer groups = parent.attribute(groupsSizeParameter()); + + String group; + if (level == null) { + group = groupPrefix() + 1; + if (groups > 1) { + context.pushRerunFilter(); + context.putContextParameter(contextParameter(), 1); + } + return group; + } + + level = level + 1; + group = groupPrefix() + level; + + if (level < groups) { + context.pushRerunFilter(); + context.putContextParameter(contextParameter(), level); + } + return group; + } +} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryContext.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryContext.java index b3b589955cd..7340c7dbf65 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryContext.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryContext.java @@ -24,13 +24,13 @@ public class DiscoveryContext { private Object inputParameters; - private Map contextParameters = new HashMap<>(); + private final Map contextParameters = new HashMap<>(); // some filter support rerun logic, eg:ZoneAware // instances grouping to self zone, other zone, and so on // first try self zone, after other filter(Isolation Filter), no instances are available // then try other zone - private Stack rerunStack = new Stack<>(); + private final Stack rerunStack = new Stack<>(); private DiscoveryTreeNode currentNode; diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryFilter.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryFilter.java index e0b395cd845..14b0cc44681 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryFilter.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryFilter.java @@ -17,16 +17,23 @@ package org.apache.servicecomb.registry.discovery; -// filter is stateless -public interface DiscoveryFilter { +import org.springframework.core.Ordered; + +/** + * Server list filters for DiscoveryTree. + * + * Implementation Notice: DiscoveryFilter is initialized using bean and instance shared for all + * microservices. If implementation has states, can put the states to DiscoveryContext or parent DiscoveryTreeNode. + */ +public interface DiscoveryFilter extends Ordered { default boolean enabled() { return true; } - int getOrder(); - - // grouping filter, means grouping instances to some groups - // eg: operation/ZoneAware/transport + /** + * grouping filter, means grouping instances to some groups + * eg: operation/ZoneAware/transport + */ default boolean isGroupingFilter() { return false; } diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTree.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTree.java index dfa05fd8d8a..c7b70f606b9 100644 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTree.java +++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTree.java @@ -17,23 +17,22 @@ package org.apache.servicecomb.registry.discovery; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.Iterator; +import java.util.Collections; import java.util.List; +import java.util.Map; import org.apache.servicecomb.foundation.common.cache.VersionedCache; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.registry.DiscoveryManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; /** - * help to understand DiscoveryTree *
  * DiscoveryTree is used to:
- * 1.get all instances by app/microserviceName/versionRule
+ * 1.get all instances by app/microserviceName
  * 2.filter all instances set, and output another set, the output set is instance or something else, this depend on filter set
  *
  * DiscoveryFilter have different types:
@@ -43,11 +42,9 @@
  * different types can composite in one filter
  *
  * features:
- * 1.every group combination(eg:1.0.0-2.0.0/1.0.0+/self/RESTful) relate to a loadBalancer instance
- * 2.if some filter output set is empty, DiscoveryTree can support try refilter logic
+ * 1.if some filter output set is empty, DiscoveryTree can support try refilter logic
  *   eg: if there is no available instances in self AZ, can refilter in other AZ
- *   red arrows in help to understand DiscoveryTree, show the refilter logic
- * 3.every filter must try to cache result, avoid calculate every time.
+ * 2.every filter must try to cache result, avoid calculate every time.
  *
  * usage:
  * 1.declare a field: DiscoveryTree discoveryTree = new DiscoveryTree();
@@ -76,75 +73,74 @@
 public class DiscoveryTree {
   private static final Logger LOGGER = LoggerFactory.getLogger(DiscoveryTree.class);
 
-  private volatile DiscoveryTreeNode root;
+  private final Map> root = new ConcurrentHashMapEx<>();
 
   private final Object lock = new Object();
 
-  private List filters = new ArrayList<>();
+  private List filters = Collections.emptyList();
 
-  public void loadFromSPI(Class cls) {
-    filters.addAll(SPIServiceUtils.getSortedService(cls));
-  }
+  private final DiscoveryManager discoveryManager;
 
-  public void addFilter(DiscoveryFilter filter) {
-    filters.add(filter);
+  public DiscoveryTree(DiscoveryManager discoveryManager) {
+    this.discoveryManager = discoveryManager;
   }
 
-  // group name are qualifiedName
-  // all leaf group will create a loadbalancer instance, groupName is loadBalancer key
-  public void sort() {
-    filters.sort(Comparator.comparingInt(DiscoveryFilter::getOrder));
+  @Autowired
+  public void setDiscoveryFilters(List filters) {
+    this.filters = filters;
+    log();
+  }
 
-    Iterator iterator = filters.iterator();
-    while (iterator.hasNext()) {
-      DiscoveryFilter filter = iterator.next();
-      if (!filter.enabled()) {
-        iterator.remove();
-      }
-      LOGGER.info("DiscoveryFilter {}, enabled {}.", filter.getClass().getName(), filter.enabled());
+  private void log() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("DiscoveryFilters(name, enabled, order, group):");
+    for (DiscoveryFilter filter : filters) {
+      sb.append("(").append(filter.getClass().getName()).append(",")
+          .append(filter.enabled()).append(",").append(filter.getOrder()).append(",")
+          .append(filter.isGroupingFilter()).append(")");
     }
+    LOGGER.info(sb.toString());
   }
 
-  protected boolean isMatch(VersionedCache existing, VersionedCache inputCache) {
+  boolean isMatch(VersionedCache existing, VersionedCache inputCache) {
     return existing != null && existing.isSameVersion(inputCache);
   }
 
-  protected boolean isExpired(VersionedCache existing, VersionedCache inputCache) {
+  boolean isExpired(VersionedCache existing, VersionedCache inputCache) {
     return existing == null || existing.isExpired(inputCache);
   }
 
-  public DiscoveryTreeNode discovery(DiscoveryContext context, String appId, String microserviceName,
-      String versionRule) {
-    VersionedCache instanceVersionedCache = DiscoveryManager.INSTANCE
-        .getInstanceCacheManager()
-        .getOrCreateVersionedCache(appId, microserviceName, versionRule);
+  public DiscoveryTreeNode discovery(DiscoveryContext context, String appId, String microserviceName) {
+    VersionedCache instanceVersionedCache = this.discoveryManager.getOrCreateVersionedCache(appId, microserviceName);
 
-    return discovery(context, instanceVersionedCache);
+    return discovery(appId, microserviceName, context, instanceVersionedCache);
   }
 
-  public DiscoveryTreeNode discovery(DiscoveryContext context, VersionedCache inputCache) {
-    DiscoveryTreeNode tmpRoot = getOrCreateRoot(inputCache);
+  DiscoveryTreeNode discovery(String appId, String microserviceName, DiscoveryContext context,
+      VersionedCache inputCache) {
+    DiscoveryTreeNode tmpRoot = getOrCreateRoot(appId, microserviceName, inputCache);
     DiscoveryTreeNode parent = tmpRoot.children()
         .computeIfAbsent(inputCache.name(), name -> new DiscoveryTreeNode().fromCache(inputCache));
     return doDiscovery(context, parent);
   }
 
-  protected DiscoveryTreeNode getOrCreateRoot(VersionedCache inputCache) {
-    DiscoveryTreeNode tmpRoot = root;
+  protected DiscoveryTreeNode getOrCreateRoot(String appId, String microserviceName, VersionedCache inputCache) {
+    DiscoveryTreeNode tmpRoot = root.computeIfAbsent(appId, k -> new ConcurrentHashMapEx<>()).get(microserviceName);
     if (isMatch(tmpRoot, inputCache)) {
       return tmpRoot;
     }
 
     synchronized (lock) {
-      if (isExpired(root, inputCache)) {
+      if (isExpired(tmpRoot, inputCache)) {
         // not initialized or inputCache newer than root, create new root
-        root = new DiscoveryTreeNode().cacheVersion(inputCache.cacheVersion());
-        return root;
+        tmpRoot = new DiscoveryTreeNode().cacheVersion(inputCache.cacheVersion());
+        root.get(appId).put(microserviceName, tmpRoot);
+        return tmpRoot;
       }
 
-      if (root.isSameVersion(inputCache)) {
+      if (tmpRoot.isSameVersion(inputCache)) {
         // reuse root directly
-        return root;
+        return tmpRoot;
       }
     }
 
@@ -154,12 +150,18 @@ protected DiscoveryTreeNode getOrCreateRoot(VersionedCache inputCache) {
     // 3) thread 1 go on, then root is newer than inputCache
     //    but if create old children in new version root, it's a wrong logic
     // so just create a temporary root for the inputCache, DO NOT assign to root
-    return new DiscoveryTreeNode().cacheVersion(inputCache.cacheVersion());
+    tmpRoot = new DiscoveryTreeNode().cacheVersion(inputCache.cacheVersion());
+    root.get(appId).put(microserviceName, tmpRoot);
+    return tmpRoot;
   }
 
   protected DiscoveryTreeNode doDiscovery(DiscoveryContext context, DiscoveryTreeNode parent) {
     for (int idx = 0; idx < filters.size(); ) {
       DiscoveryFilter filter = filters.get(idx);
+      if (!filter.enabled()) {
+        idx++;
+        continue;
+      }
       context.setCurrentNode(parent);
 
       DiscoveryTreeNode child = filter.discovery(context, parent);
@@ -183,7 +185,7 @@ protected DiscoveryTreeNode doDiscovery(DiscoveryContext context, DiscoveryTreeN
         }
 
         // no rerun support, go on even result is empty
-        // because maybe some filter use other mechanism to create a instance(eg:domain name)
+        // because maybe some filter use other mechanism to create an instance(eg:domain name)
       }
 
       parent = child;
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTreeNode.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTreeNode.java
index 3dda15f6c4b..e0f7c828c10 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTreeNode.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/DiscoveryTreeNode.java
@@ -25,7 +25,7 @@
 public class DiscoveryTreeNode extends VersionedCache {
   private volatile boolean childrenInited;
 
-  private int level;
+  private volatile int level;
 
   protected Map attributes = new ConcurrentHashMapEx<>();
 
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstancePing.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstancePing.java
new file mode 100644
index 00000000000..2aa45718194
--- /dev/null
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstancePing.java
@@ -0,0 +1,23 @@
+/*
+ * 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.registry.discovery;
+
+import org.springframework.core.Ordered;
+
+public interface InstancePing extends Ordered {
+  boolean ping(StatefulDiscoveryInstance instance);
+}
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstanceStatusDiscoveryFilter.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstanceStatusDiscoveryFilter.java
index 5e2886f7ea4..e7a4029bdeb 100644
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstanceStatusDiscoveryFilter.java
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/InstanceStatusDiscoveryFilter.java
@@ -17,17 +17,22 @@
 
 package org.apache.servicecomb.registry.discovery;
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.ArrayList;
+import java.util.List;
 
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus;
+import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus;
+import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.HistoryStatus;
+import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.IsolationStatus;
+import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.PingStatus;
 
-import com.netflix.config.DynamicPropertyFactory;
+public class InstanceStatusDiscoveryFilter extends AbstractGroupDiscoveryFilter {
+  public static final String PARAMETER = "status_level";
 
-public class InstanceStatusDiscoveryFilter extends AbstractDiscoveryFilter {
-  private static final String UP_INSTANCES = "upInstances";
+  public static final String GROUP_PREFIX = "status_group_";
+
+  public static final String GROUP_SIZE = "status_group_size";
+
+  public static final String SERVICECOMB_LOADBALANCE_FILTER_STATUS_ENABLED = "servicecomb.loadbalance.filter.status.enabled";
 
   @Override
   public int getOrder() {
@@ -36,35 +41,83 @@ public int getOrder() {
 
   @Override
   public boolean enabled() {
-    return DynamicPropertyFactory.getInstance()
-        .getBooleanProperty("servicecomb.loadbalance.filter.status.enabled", true).get();
+
+    if (enabled == null) {
+      enabled = dynamicProperties.getBooleanProperty(SERVICECOMB_LOADBALANCE_FILTER_STATUS_ENABLED,
+          value -> enabled = value,
+          true);
+    }
+    return enabled;
+  }
+
+  @Override
+  protected String groupsSizeParameter() {
+    return GROUP_SIZE;
   }
 
   @Override
-  public boolean isGroupingFilter() {
-    return true;
+  protected String contextParameter() {
+    return PARAMETER;
   }
 
   @Override
-  protected String findChildName(DiscoveryContext context, DiscoveryTreeNode parent) {
-    return UP_INSTANCES;
+  protected String groupPrefix() {
+    return GROUP_PREFIX;
   }
 
   @Override
   public void init(DiscoveryContext context, DiscoveryTreeNode parent) {
-    Map instances = parent.data();
-    Map filteredServers = new HashMap<>();
-    for (Entry instanceEntry : instances.entrySet()) {
-      MicroserviceInstance instance = instanceEntry.getValue();
-      if (MicroserviceInstanceStatus.UP == instance.getStatus()) {
-        filteredServers.put(instanceEntry.getKey(), instance);
+    List instances = parent.data();
+    List level0 = new ArrayList<>();
+    List level1 = new ArrayList<>();
+    List level2 = new ArrayList<>();
+    List level3 = new ArrayList<>();
+
+    int groups = 1;
+
+    for (StatefulDiscoveryInstance instance : instances) {
+      if (HistoryStatus.CURRENT == instance.getHistoryStatus() &&
+          MicroserviceInstanceStatus.UP == instance.getStatus() &&
+          PingStatus.OK == instance.getPingStatus() &&
+          IsolationStatus.NORMAL == instance.getIsolationStatus()) {
+        level0.add(instance);
+        continue;
+      }
+      if (HistoryStatus.CURRENT == instance.getHistoryStatus() &&
+          MicroserviceInstanceStatus.UP == instance.getStatus() &&
+          PingStatus.UNKNOWN == instance.getPingStatus() &&
+          IsolationStatus.NORMAL == instance.getIsolationStatus()) {
+        level1.add(instance);
+        continue;
+      }
+      if (HistoryStatus.HISTORY == instance.getHistoryStatus() &&
+          MicroserviceInstanceStatus.UP == instance.getStatus() &&
+          PingStatus.OK == instance.getPingStatus() &&
+          IsolationStatus.NORMAL == instance.getIsolationStatus()) {
+        level2.add(instance);
+        continue;
       }
+      level3.add(instance);
     }
 
-    if (filteredServers.isEmpty()) {
-      return;
+    if (!level0.isEmpty()) {
+      parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
+          .subName(parent, GROUP_PREFIX + groups).data(level0));
+      groups++;
     }
-    DiscoveryTreeNode child = new DiscoveryTreeNode().subName(parent, UP_INSTANCES).data(filteredServers);
-    parent.child(UP_INSTANCES, child);
+    if (!level1.isEmpty()) {
+      parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
+          .subName(parent, GROUP_PREFIX + groups).data(level1));
+      groups++;
+    }
+    if (!level2.isEmpty()) {
+      parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
+          .subName(parent, GROUP_PREFIX + groups).data(level2));
+      groups++;
+    }
+    parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode()
+        .subName(parent, GROUP_PREFIX + groups).data(level3));
+
+    parent.attribute(GROUP_SIZE, groups);
   }
 }
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/MicroserviceInstanceCache.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/MicroserviceInstanceCache.java
new file mode 100644
index 00000000000..4990b3d8f90
--- /dev/null
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/MicroserviceInstanceCache.java
@@ -0,0 +1,74 @@
+/*
+ * 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.registry.discovery;
+
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.foundation.common.cache.VersionedCache;
+import org.apache.servicecomb.registry.DiscoveryManager;
+import org.apache.servicecomb.registry.api.DiscoveryInstance;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+
+/**
+ * 在公钥认证场景,需要查询对端的实例信息。
+ *
+ * 微服务实例缓存 key 为:serviceId@instanceId 缓存limit:1000 缓存老化策略:30分钟没有访问就过期。
+ *
+ */
+public class MicroserviceInstanceCache {
+
+  private static final Logger logger = LoggerFactory.getLogger(MicroserviceInstanceCache.class);
+
+  private static final Cache instances = CacheBuilder.newBuilder()
+      .maximumSize(1000)
+      .expireAfterAccess(30, TimeUnit.MINUTES)
+      .build();
+
+  private final DiscoveryManager discoveryManager;
+
+  public MicroserviceInstanceCache(DiscoveryManager discoveryManager) {
+    this.discoveryManager = discoveryManager;
+  }
+
+  public DiscoveryInstance getOrCreate(String application, String serviceName) {
+    try {
+      String key = String.format("%s@%s", application, serviceName);
+      return instances.get(key, () -> {
+        VersionedCache instances = discoveryManager.getOrCreateVersionedCache(application, serviceName);
+        List statefulDiscoveryInstances = instances.data();
+        if (CollectionUtils.isEmpty(statefulDiscoveryInstances)) {
+          throw new IllegalArgumentException("instance id not exists.");
+        }
+        return statefulDiscoveryInstances.get(0);
+      });
+    } catch (ExecutionException | UncheckedExecutionException e) {
+      logger.error("get microservice instance from cache failed, {}, {}",
+          String.format("%s@%s", application, serviceName),
+          e.getMessage());
+      return null;
+    }
+  }
+}
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/StatefulDiscoveryInstance.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/StatefulDiscoveryInstance.java
new file mode 100644
index 00000000000..394b2b03ccc
--- /dev/null
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/StatefulDiscoveryInstance.java
@@ -0,0 +1,183 @@
+/*
+ * 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.registry.discovery;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.servicecomb.registry.api.AbstractDiscoveryInstance;
+import org.apache.servicecomb.registry.api.DataCenterInfo;
+import org.apache.servicecomb.registry.api.DiscoveryInstance;
+import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus;
+
+/**
+ * Wrapper class for DiscoveryInstance with states like: isolation, health, metrics and so on.
+ */
+public class StatefulDiscoveryInstance extends AbstractDiscoveryInstance {
+  public enum IsolationStatus {
+    NORMAL,
+    ISOLATED
+  }
+
+  public enum PingStatus {
+    UNKNOWN,
+    OK,
+    FAIL
+  }
+
+  public enum HistoryStatus {
+    CURRENT,
+    HISTORY
+  }
+
+  private final DiscoveryInstance discoveryInstance;
+
+  private IsolationStatus isolationStatus = IsolationStatus.NORMAL;
+
+  private long isolatedTime;
+
+  private long isolateDuration;
+
+  private PingStatus pingStatus = PingStatus.UNKNOWN;
+
+  private long pingTime = System.currentTimeMillis();
+
+  private HistoryStatus historyStatus = HistoryStatus.CURRENT;
+
+  public StatefulDiscoveryInstance(DiscoveryInstance discoveryInstance) {
+    this.discoveryInstance = discoveryInstance;
+  }
+
+  public IsolationStatus getIsolationStatus() {
+    return isolationStatus;
+  }
+
+  public void setIsolationStatus(
+      IsolationStatus isolationStatus) {
+    this.isolationStatus = isolationStatus;
+  }
+
+  public PingStatus getPingStatus() {
+    return pingStatus;
+  }
+
+  public void setPingStatus(PingStatus pingStatus) {
+    this.pingStatus = pingStatus;
+  }
+
+  public HistoryStatus getHistoryStatus() {
+    return historyStatus;
+  }
+
+  public void setHistoryStatus(HistoryStatus historyStatus) {
+    this.historyStatus = historyStatus;
+  }
+
+  public long getIsolatedTime() {
+    return isolatedTime;
+  }
+
+  public void setIsolatedTime(long isolatedTime) {
+    this.isolatedTime = isolatedTime;
+  }
+
+  public long getIsolateDuration() {
+    return isolateDuration;
+  }
+
+  public void setIsolateDuration(long isolateDuration) {
+    this.isolateDuration = isolateDuration;
+  }
+
+  public long getPingTime() {
+    return pingTime;
+  }
+
+  public void setPingTime(long pingTime) {
+    this.pingTime = pingTime;
+  }
+
+  @Override
+  public MicroserviceInstanceStatus getStatus() {
+    return this.discoveryInstance.getStatus();
+  }
+
+  @Override
+  public String getRegistryName() {
+    return this.discoveryInstance.getRegistryName();
+  }
+
+  @Override
+  public String getEnvironment() {
+    return this.discoveryInstance.getEnvironment();
+  }
+
+  @Override
+  public String getApplication() {
+    return this.discoveryInstance.getApplication();
+  }
+
+  @Override
+  public String getServiceName() {
+    return this.discoveryInstance.getServiceName();
+  }
+
+  @Override
+  public String getAlias() {
+    return this.discoveryInstance.getAlias();
+  }
+
+  @Override
+  public String getVersion() {
+    return this.discoveryInstance.getVersion();
+  }
+
+  @Override
+  public DataCenterInfo getDataCenterInfo() {
+    return this.discoveryInstance.getDataCenterInfo();
+  }
+
+  @Override
+  public String getDescription() {
+    return this.discoveryInstance.getDescription();
+  }
+
+  @Override
+  public Map getProperties() {
+    return this.discoveryInstance.getProperties();
+  }
+
+  @Override
+  public Map getSchemas() {
+    return this.discoveryInstance.getSchemas();
+  }
+
+  @Override
+  public List getEndpoints() {
+    return this.discoveryInstance.getEndpoints();
+  }
+
+  @Override
+  public String getInstanceId() {
+    return this.discoveryInstance.getInstanceId();
+  }
+
+  @Override
+  public String getServiceId() {
+    return this.discoveryInstance.getServiceId();
+  }
+}
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/TelnetInstancePing.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/TelnetInstancePing.java
new file mode 100644
index 00000000000..07967579a3b
--- /dev/null
+++ b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/discovery/TelnetInstancePing.java
@@ -0,0 +1,58 @@
+/*
+ * 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.registry.discovery;
+
+import java.net.InetSocketAddress;
+import java.net.Socket;
+
+import org.apache.servicecomb.foundation.common.net.IpPort;
+import org.apache.servicecomb.foundation.common.net.NetUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.CollectionUtils;
+
+public class TelnetInstancePing implements InstancePing {
+  private static final Logger LOGGER = LoggerFactory.getLogger(TelnetInstancePing.class);
+
+  @Override
+  public boolean ping(StatefulDiscoveryInstance instance) {
+    if (CollectionUtils.isEmpty(instance.getEndpoints())) {
+      return false;
+    }
+
+    for (String endpoint : instance.getEndpoints()) {
+      IpPort ipPort = NetUtils.parseIpPortFromURI(endpoint);
+      try (Socket s = new Socket()) {
+        s.connect(new InetSocketAddress(ipPort.getHostOrIp(), ipPort.getPort()), 3000);
+        return true;
+      } catch (Exception e) {
+        LOGGER.warn("ping instance {}/{}/{}/{} endpoint {} failed",
+            instance.getApplication(),
+            instance.getServiceName(),
+            instance.getRegistryName(),
+            instance.getInstanceId(), endpoint);
+      }
+    }
+
+    return false;
+  }
+
+  @Override
+  public int getOrder() {
+    return 10000;
+  }
+}
diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/swagger/SwaggerLoader.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/swagger/SwaggerLoader.java
deleted file mode 100644
index 5be72294a18..00000000000
--- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/swagger/SwaggerLoader.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 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.registry.swagger;
-
-import java.net.URI;
-import java.net.URL;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
-import org.apache.servicecomb.foundation.common.utils.JvmUtils;
-import org.apache.servicecomb.foundation.common.utils.ResourceUtil;
-import org.apache.servicecomb.registry.DiscoveryManager;
-import org.apache.servicecomb.registry.RegistrationManager;
-import org.apache.servicecomb.registry.api.registry.Microservice;
-import org.apache.servicecomb.registry.api.registry.MicroserviceInstance;
-import org.apache.servicecomb.registry.definition.MicroserviceNameParser;
-import org.apache.servicecomb.swagger.SwaggerUtils;
-import org.apache.servicecomb.swagger.generator.SwaggerGenerator;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
-import com.google.common.hash.Hashing;
-
-import io.swagger.models.Swagger;
-
-public class SwaggerLoader {
-  private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerLoader.class);
-
-  // first key : appId
-  // second key: microservice short name
-  // third key : schemaId
-  private Map>> apps = new ConcurrentHashMapEx<>();
-
-  public SwaggerLoader() {
-  }
-
-  // result length is 64
-  public static String calcSchemaSummary(String schemaContent) {
-    return Hashing.sha256().newHasher().putString(schemaContent, Charsets.UTF_8).hash().toString();
-  }
-
-  /**
-   * 
-   * register swaggers in the location to current microservice
-   * Scenes for contract first mode:
-   *  1.consumer
-   *    manager manage some product, can only know product microservice names after deploy
-   *    and can only register swagger after product registered
-   *    in fact, consumers can load swagger from ServiceCenter
-   *    so for consumer, this logic is not necessary, just keep it for compatible
-   *  2.producer
-   *    deploy to different microservice name in different product
-   *    can register swaggers in BootListener.onBeforeProducerProvider
-   * 
- * @param swaggersLocation eg. "test/schemas", will load all test/schemas/*.yaml - */ - public void registerSwaggersInLocation(String swaggersLocation) { - String microserviceName = RegistrationManager.INSTANCE.getMicroservice().getServiceName(); - registerSwaggersInLocation(microserviceName, swaggersLocation); - } - - public void registerSwaggersInLocation(String microserviceName, String swaggersLocation) { - LOGGER.info("register schemas in location [{}], microserviceName=[{}]", swaggersLocation, microserviceName); - try { - List resourceUris = ResourceUtil.findResourcesBySuffix(swaggersLocation, ".yaml"); - if (resourceUris.isEmpty()) { - LOGGER.error("register swagger in not exist location: \"{}\".", swaggersLocation); - return; - } - for (URI uri : resourceUris) { - URL url = uri.toURL(); - Swagger swagger = SwaggerUtils.parseAndValidateSwagger(url); - String schemaId = FilenameUtils.getBaseName(url.getPath()); - registerSwagger(microserviceName, schemaId, swagger); - } - } catch (Throwable e) { - throw new IllegalStateException(String.format( - "failed to register swaggers, microserviceName=%s, location=%s.", microserviceName, swaggersLocation), - e); - } - } - - public void registerSwagger(String microserviceName, String schemaId, Swagger swagger) { - MicroserviceNameParser parser = new MicroserviceNameParser( - RegistrationManager.INSTANCE.getMicroservice().getAppId(), microserviceName); - registerSwagger(parser.getAppId(), parser.getShortName(), schemaId, swagger); - } - - public Swagger registerSwagger(String appId, String shortName, String schemaId, Class cls) { - Swagger swagger = SwaggerGenerator.generate(cls); - registerSwagger(appId, shortName, schemaId, swagger); - return swagger; - } - - public void registerSwagger(String appId, String shortName, String schemaId, Swagger swagger) { - apps.computeIfAbsent(appId, k -> new ConcurrentHashMapEx<>()) - .computeIfAbsent(shortName, k -> new ConcurrentHashMapEx<>()) - .put(schemaId, swagger); - LOGGER.info("register swagger appId={}, name={}, schemaId={}.", appId, shortName, schemaId); - } - - public void unregisterSwagger(String appId, String shortName, String schemaId) { - apps.getOrDefault(appId, Collections.emptyMap()) - .getOrDefault(shortName, Collections.emptyMap()) - .remove(schemaId); - } - - public Swagger loadSwagger(Microservice microservice, Collection instances, String schemaId) { - Swagger swagger = loadLocalSwagger(microservice.getAppId(), microservice.getServiceName(), schemaId); - if (swagger != null) { - return swagger; - } - - return loadFromRemote(microservice, instances, schemaId); - } - - public Swagger loadLocalSwagger(String appId, String shortName, String schemaId) { - LOGGER.info("try to load schema locally, appId=[{}], serviceName=[{}], schemaId=[{}]", - appId, shortName, schemaId); - Swagger swagger = loadFromMemory(appId, shortName, schemaId); - if (swagger != null) { - LOGGER.info("load schema from memory"); - return swagger; - } - - return loadFromResource(appId, shortName, schemaId); - } - - @VisibleForTesting - public Swagger loadFromMemory(String appId, String shortName, String schemaId) { - return Optional.ofNullable(apps.get(appId)) - .map(microservices -> microservices.get(shortName)) - .map(schemas -> schemas.get(schemaId)) - .orElse(null); - } - - private Swagger loadFromResource(String appId, String shortName, String schemaId) { - if (appId.equals(RegistrationManager.INSTANCE.getMicroservice().getAppId())) { - Swagger swagger = loadFromResource(String.format("microservices/%s/%s.yaml", shortName, schemaId)); - if (swagger != null) { - return swagger; - } - } - - return loadFromResource(String.format("applications/%s/%s/%s.yaml", appId, shortName, schemaId)); - } - - private Swagger loadFromResource(String path) { - URL url = JvmUtils.findClassLoader().getResource(path); - if (url == null) { - return null; - } - - LOGGER.info("load schema from path [{}]", path); - return SwaggerUtils.parseAndValidateSwagger(url); - } - - private Swagger loadFromRemote(Microservice microservice, Collection instances, - String schemaId) { - String schemaContent = DiscoveryManager.INSTANCE.getSchema(microservice.getServiceId(), instances, schemaId); - if (schemaContent != null) { - LOGGER.info( - "load schema from service center, appId={}, microserviceName={}, version={}, serviceId={}, schemaId={}.", - microservice.getAppId(), - microservice.getServiceName(), - microservice.getVersion(), - microservice.getServiceId(), - schemaId); - LOGGER.debug(schemaContent); - return SwaggerUtils.parseAndValidateSwagger(schemaContent); - } - - LOGGER.warn("no schema in local, and can not get schema from service center, " - + "appId={}, microserviceName={}, version={}, serviceId={}, schemaId={}.", - microservice.getAppId(), - microservice.getServiceName(), - microservice.getVersion(), - microservice.getServiceId(), - schemaId); - - return null; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java deleted file mode 100644 index b5a3458ab40..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRule.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; - -public abstract class VersionRule { - private final String versionRule; - - public VersionRule(String versionRule) { - this.versionRule = versionRule; - } - - public String getVersionRule() { - return versionRule; - } - - // equals isMatch except "latest" rule - public boolean isAccept(Version version) { - return isMatch(version, null); - } - - // latestVersion is only required for "latest" rule - // it's ugly, but simpler - public abstract boolean isMatch(Version version, Version latestVersion); - - @Override - public String toString() { - return versionRule; - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java deleted file mode 100644 index 80eecbbf3e6..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleFixedParser.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; - -// fixed, this should be the last parser -// will not check version format -public class VersionRuleFixedParser implements VersionRuleParser { - class FixedVersionRule extends VersionRule { - private final Version version; - - public FixedVersionRule(String versionRule, Version version) { - super(versionRule); - - this.version = version; - } - - public boolean isMatch(Version version, Version latestVersion) { - return this.version.equals(version); - } - } - - @Override - public VersionRule parse(String strVersionRule) { - Version version = new Version(strVersionRule); - return new FixedVersionRule(version.getVersion(), version); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java deleted file mode 100644 index 2714611fd75..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleLatestParser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; -import org.apache.servicecomb.registry.definition.DefinitionConst; - -public class VersionRuleLatestParser implements VersionRuleParser { - class LatestVersionRule extends VersionRule { - public LatestVersionRule(String versionRule) { - super(versionRule); - } - - @Override - public boolean isAccept(Version version) { - return true; - } - - public boolean isMatch(Version version, Version latestVersion) { - return version.equals(latestVersion); - } - } - - @Override - public VersionRule parse(String strVersionRule) { - if (!DefinitionConst.VERSION_RULE_LATEST.equals(strVersionRule)) { - return null; - } - - return new LatestVersionRule(strVersionRule); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleParser.java deleted file mode 100644 index 29bdd1c10fc..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleParser.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.registry.version; - -public interface VersionRuleParser { - // if can not parse, then return null - VersionRule parse(String strVersionRule); -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java deleted file mode 100644 index 0fcb889c624..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleRangeParser.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; - -// 1.0.0-2.0.0 -public class VersionRuleRangeParser implements VersionRuleParser { - class RangeVersionRule extends VersionRule { - private final Version from; - - private final Version to; - - public RangeVersionRule(String versionRule, Version from, Version to) { - super(versionRule); - - this.from = from; - this.to = to; - } - - public boolean isMatch(Version version, Version latestVersion) { - return version.compareTo(from) >= 0 && version.compareTo(to) < 0; - } - } - - @Override - public VersionRule parse(String strVersionRule) { - int pos = strVersionRule.indexOf('-'); - if (pos <= 0 || pos == strVersionRule.length() - 1) { - return null; - } - - Version from = new Version(strVersionRule.substring(0, pos)); - Version to = new Version(strVersionRule.substring(pos + 1)); - return new RangeVersionRule(from.getVersion() + "-" + to.getVersion(), from, to); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java deleted file mode 100644 index 6d1bdd698d6..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleStartFromParser.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; - -// 1.0.0+ -public class VersionRuleStartFromParser implements VersionRuleParser { - class StartFromVersionRule extends VersionRule { - private final Version from; - - public StartFromVersionRule(String versionRule, Version from) { - super(versionRule); - - this.from = from; - } - - public boolean isMatch(Version version, Version latestVersion) { - return version.compareTo(from) >= 0; - } - } - - @Override - public VersionRule parse(String strVersionRule) { - int pos = strVersionRule.indexOf('+'); - if (pos <= 0 || pos != strVersionRule.length() - 1) { - return null; - } - - Version from = new Version(strVersionRule.substring(0, pos)); - return new StartFromVersionRule(from.getVersion() + "+", from); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleUtils.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleUtils.java deleted file mode 100644 index ea63d66c4fb..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionRuleUtils.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.registry.version; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; - -public final class VersionRuleUtils { - private static List parsers = new ArrayList<>(); - - private static Map versionRuleCache = new ConcurrentHashMapEx<>(); - - static { - parsers.add(new VersionRuleLatestParser()); - parsers.add(new VersionRuleStartFromParser()); - parsers.add(new VersionRuleRangeParser()); - parsers.add(new VersionRuleFixedParser()); - } - - //1.0 - //1.0.0+ - //1.0.0-2.0.0 - //latest - public static VersionRule getOrCreate(String strVersionRule) { - Objects.requireNonNull(strVersionRule); - - return versionRuleCache.computeIfAbsent(strVersionRule, VersionRuleUtils::create); - } - - public static VersionRule create(String strVersionRule) { - strVersionRule = strVersionRule.trim(); - for (VersionRuleParser parser : parsers) { - VersionRule versionRule = parser.parse(strVersionRule); - if (versionRule != null) { - return versionRule; - } - } - - throw new IllegalStateException("never run to here"); - } -} diff --git a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java b/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java deleted file mode 100644 index 8706a3d9f99..00000000000 --- a/foundations/foundation-registry/src/main/java/org/apache/servicecomb/registry/version/VersionUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.registry.version; - -import java.util.Map; -import java.util.Objects; - -import org.apache.servicecomb.foundation.common.Version; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; - -public final class VersionUtils { - private static Map versionCache = new ConcurrentHashMapEx<>(); - - public static Version getOrCreate(String strVersion) { - Objects.requireNonNull(strVersion); - - return versionCache.computeIfAbsent(strVersion, Version::new); - } -} diff --git a/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Versions b/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Versions deleted file mode 100644 index faf43b019b7..00000000000 --- a/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.api.Versions +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.registry.api.registry.ServiceCombVersion diff --git a/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.consumer.MicroserviceInstancePing b/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.consumer.MicroserviceInstancePing index 8493c8a6e17..56169c4507c 100644 --- a/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.consumer.MicroserviceInstancePing +++ b/foundations/foundation-registry/src/main/resources/META-INF/services/org.apache.servicecomb.registry.consumer.MicroserviceInstancePing @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.registry.consumer.SimpleMicroserviceInstancePing \ No newline at end of file +org.apache.servicecomb.registry.consumer.SimpleMicroserviceInstancePing diff --git a/foundations/foundation-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/foundations/foundation-registry/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..8296569485a --- /dev/null +++ b/foundations/foundation-registry/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.servicecomb.registry.RegistryConfiguration diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/TestDiscoveryManager.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/TestDiscoveryManager.java new file mode 100644 index 00000000000..bd50cc85748 --- /dev/null +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/TestDiscoveryManager.java @@ -0,0 +1,212 @@ +/* + * 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.registry; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.foundation.common.cache.VersionedCache; +import org.apache.servicecomb.registry.api.AbstractDiscoveryInstance; +import org.apache.servicecomb.registry.api.DataCenterInfo; +import org.apache.servicecomb.registry.api.Discovery; +import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.HistoryStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.IsolationStatus; +import org.apache.servicecomb.registry.discovery.TelnetInstancePing; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class TestDiscoveryManager { + + @Test + public void test_initial_service_list_correct() { + MyDiscovery discovery1 = Mockito.spy(new MyDiscovery()); + MyDiscoveryInstance instance1 = Mockito.mock(MyDiscoveryInstance.class); + DiscoveryManager discoveryManager = new DiscoveryManager(List.of(discovery1), List.of(new TelnetInstancePing())); + Mockito.when(discovery1.findServiceInstances("app", "service")) + .thenReturn(List.of(instance1)); + Mockito.when(instance1.getInstanceId()).thenReturn("instance1"); + //first read + VersionedCache versionedCache = discoveryManager.getOrCreateVersionedCache("app", "service"); + List result = versionedCache.data(); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("instance1", result.get(0).getInstanceId()); + Assertions.assertEquals(HistoryStatus.CURRENT, result.get(0).getHistoryStatus()); + // second read + versionedCache = discoveryManager.getOrCreateVersionedCache("app", "service"); + result = versionedCache.data(); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("instance1", result.get(0).getInstanceId()); + Assertions.assertEquals(HistoryStatus.CURRENT, result.get(0).getHistoryStatus()); + } + + @Test + public void test_initial_empty_service_list_correct() { + MyDiscovery discovery1 = Mockito.spy(new MyDiscovery()); + DiscoveryManager discoveryManager = new DiscoveryManager(List.of(discovery1), List.of(new TelnetInstancePing())); + Mockito.when(discovery1.findServiceInstances("app", "service")) + .thenReturn(Collections.emptyList()); + //first read + VersionedCache versionedCache = discoveryManager.getOrCreateVersionedCache("app", "service"); + List result = versionedCache.data(); + Assertions.assertEquals(0, result.size()); + // second read + discoveryManager.getOrCreateVersionedCache("app", "service"); + result = versionedCache.data(); + Assertions.assertEquals(0, result.size()); + } + + @Test + public void test_isolate_service_instance_correct() { + MyDiscovery discovery1 = Mockito.spy(new MyDiscovery()); + MyDiscoveryInstance instance1 = Mockito.mock(MyDiscoveryInstance.class); + DiscoveryManager discoveryManager = new DiscoveryManager(List.of(discovery1), List.of(new TelnetInstancePing())); + Mockito.when(discovery1.findServiceInstances("app", "service")) + .thenReturn(List.of(instance1)); + Mockito.when(instance1.getInstanceId()).thenReturn("instance1"); + Mockito.when(instance1.getApplication()).thenReturn("app"); + Mockito.when(instance1.getServiceName()).thenReturn("service"); + + VersionedCache versionedCache = discoveryManager.getOrCreateVersionedCache("app", "service"); + List result = versionedCache.data(); + discoveryManager.onInstanceIsolated(result.get(0), 10000L); + versionedCache = discoveryManager.getOrCreateVersionedCache("app", "service"); + result = versionedCache.data(); + Assertions.assertEquals(1, result.size()); + Assertions.assertEquals("instance1", result.get(0).getInstanceId()); + Assertions.assertEquals(HistoryStatus.CURRENT, result.get(0).getHistoryStatus()); + Assertions.assertEquals(IsolationStatus.ISOLATED, result.get(0).getIsolationStatus()); + } + + static class MyDiscovery implements Discovery { + + @Override + public String name() { + return "my"; + } + + @Override + public boolean enabled(String application, String serviceName) { + return true; + } + + @Override + public List findServiceInstances(String application, String serviceName) { + return null; + } + + @Override + public List findServices(String application) { + return null; + } + + @Override + public void setInstanceChangedListener(InstanceChangedListener instanceChangedListener) { + + } + + @Override + public void init() { + + } + + @Override + public void run() { + + } + + @Override + public void destroy() { + + } + + @Override + public boolean enabled() { + return true; + } + } + + static class MyDiscoveryInstance extends AbstractDiscoveryInstance { + @Override + public MicroserviceInstanceStatus getStatus() { + return null; + } + + @Override + public String getRegistryName() { + return null; + } + + @Override + public String getEnvironment() { + return null; + } + + @Override + public String getApplication() { + return null; + } + + @Override + public String getServiceName() { + return null; + } + + @Override + public String getAlias() { + return null; + } + + @Override + public String getVersion() { + return null; + } + + @Override + public DataCenterInfo getDataCenterInfo() { + return null; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public Map getProperties() { + return null; + } + + @Override + public Map getSchemas() { + return null; + } + + @Override + public List getEndpoints() { + return null; + } + + @Override + public String getInstanceId() { + return null; + } + } +} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/api/registry/TestServiceCombVersion.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/api/registry/TestServiceCombVersion.java deleted file mode 100644 index 2ae6ee0192c..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/api/registry/TestServiceCombVersion.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.registry.api.registry; - -import org.junit.Assert; -import org.junit.Test; - -public class TestServiceCombVersion { - @Test - public void testServiceCombVersion() { - ServiceCombVersion version = new ServiceCombVersion(); - // this.getClass().getPackage().getImplementationVersion() - // is not stable, may get null or 2.0.1-SNAPSHOT - Assert.assertTrue(version.loadVersion().toString().contains("ServiceComb")); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/config/TestAbstractPropertiesLoader.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/config/TestAbstractPropertiesLoader.java deleted file mode 100644 index be5a48c8f10..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/config/TestAbstractPropertiesLoader.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.registry.config; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.config.BootStrapProperties; -import org.junit.Assert; -import org.junit.Test; - -import com.netflix.config.DynamicConfiguration; - -public class TestAbstractPropertiesLoader { - @Test - public void testExtendedClassCompatible() { - Configuration configuration = new DynamicConfiguration(); - configuration.setProperty(BootStrapProperties.CONFIG_SERVICE_EXTENDED_CLASS, "invalidClass"); - - AbstractPropertiesLoader loader = MicroservicePropertiesLoader.INSTANCE; - try { - loader.loadProperties(configuration); - Assert.fail("Must throw exception"); - } catch (Error e) { - Assert.assertEquals(ClassNotFoundException.class, e.getCause().getClass()); - Assert.assertEquals("invalidClass", e.getCause().getMessage()); - } - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractDiscoveryFilter.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractDiscoveryFilter.java index 456743fa747..987ec0a0be1 100644 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractDiscoveryFilter.java +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractDiscoveryFilter.java @@ -17,11 +17,8 @@ package org.apache.servicecomb.registry.discovery; -import org.apache.servicecomb.registry.discovery.AbstractDiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestAbstractDiscoveryFilter { int initCallCount; @@ -71,9 +68,9 @@ private void doDiscovery() { public void discoveryInited() { doDiscovery(); - Assert.assertEquals(1, childrenInitedCallCount); - Assert.assertEquals(0, initCallCount); - Assert.assertSame(child, result); + Assertions.assertEquals(1, childrenInitedCallCount); + Assertions.assertEquals(0, initCallCount); + Assertions.assertSame(child, result); } @Test @@ -81,9 +78,9 @@ public void discoveryNotInitedOnce() { inited[0] = false; doDiscovery(); - Assert.assertEquals(2, childrenInitedCallCount); - Assert.assertEquals(0, initCallCount); - Assert.assertSame(child, result); + Assertions.assertEquals(2, childrenInitedCallCount); + Assertions.assertEquals(0, initCallCount); + Assertions.assertSame(child, result); } @Test @@ -92,8 +89,8 @@ public void discoveryNotInitedTwice() { inited[1] = false; doDiscovery(); - Assert.assertEquals(2, childrenInitedCallCount); - Assert.assertEquals(1, initCallCount); - Assert.assertSame(child, result); + Assertions.assertEquals(2, childrenInitedCallCount); + Assertions.assertEquals(1, initCallCount); + Assertions.assertSame(child, result); } } diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractTransportDiscoveryFilter.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractTransportDiscoveryFilter.java index c1f8da8d1cb..4a0c04140e4 100644 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractTransportDiscoveryFilter.java +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestAbstractTransportDiscoveryFilter.java @@ -19,18 +19,15 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; import java.util.UUID; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.discovery.AbstractEndpointDiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestAbstractTransportDiscoveryFilter { class AbstractEndpointDiscoveryFilterForTest extends AbstractEndpointDiscoveryFilter { @@ -46,7 +43,7 @@ protected String findTransportName(DiscoveryContext context, DiscoveryTreeNode p @Override protected Object createEndpoint(DiscoveryContext context, String transportName, String endpoint, - MicroserviceInstance instance) { + StatefulDiscoveryInstance instance) { if (disableCreate) { return null; } @@ -69,31 +66,31 @@ protected Object createEndpoint(DiscoveryContext context, String transportName, @Test public void isGroupingFilter() { - Assert.assertTrue(filter.isGroupingFilter()); + Assertions.assertTrue(filter.isGroupingFilter()); } @Test public void isTransportNameMatch_expectAll() { - Assert.assertTrue(filter.isTransportNameMatch("any", "")); + Assertions.assertTrue(filter.isTransportNameMatch("any", "")); } @Test public void isTransportNameMatch_equals() { - Assert.assertTrue(filter.isTransportNameMatch("rest", "rest")); + Assertions.assertTrue(filter.isTransportNameMatch("rest", "rest")); } @Test public void isTransportNameMatch_notEquals() { - Assert.assertFalse(filter.isTransportNameMatch("rest", "highway")); + Assertions.assertFalse(filter.isTransportNameMatch("rest", "highway")); } @Test public void discoveryNotExist() { transportName = "notExist"; - parent.data(Collections.emptyMap()); + parent.data(Collections.emptyList()); result = filter.discovery(context, parent); - Assert.assertTrue(result.isEmpty()); + Assertions.assertTrue(result.isEmpty()); } @Test @@ -103,82 +100,86 @@ public void discoveryExist() { parent.child(transportName, child); result = filter.discovery(context, parent); - Assert.assertSame(child, result); + Assertions.assertSame(child, result); } - private MicroserviceInstance createInstance(String... schemas) { + private StatefulDiscoveryInstance createInstance(String... schemas) { String id = UUID.randomUUID().toString(); - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId(id); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance = new StatefulDiscoveryInstance(discoveryInstance); + List endpoints = new ArrayList<>(); for (int idx = 0; idx < schemas.length; idx++) { String schema = schemas[idx]; - instance.getEndpoints().add(String.format("%s://%s:%d", schema, id, 8080 + idx)); + endpoints.add(String.format("%s://%s:%d", schema, id, 8080 + idx)); } + Mockito.when(discoveryInstance.getInstanceId()).thenReturn(id); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(endpoints); return instance; } - private Map createMicroserviceInstances(String name, - MicroserviceInstance... instances) { - Map map = new LinkedHashMap<>(); - for (MicroserviceInstance instance : instances) { - map.put(instance.getInstanceId(), instance); + private List createMicroserviceInstances(StatefulDiscoveryInstance... instances) { + List result = new ArrayList<>(); + for (StatefulDiscoveryInstance instance : instances) { + result.add(instance); } - return map; + return result; } @Test public void createDiscoveryTree_oneTransport() { - MicroserviceInstance instance1 = createInstance("a", "b"); - MicroserviceInstance instance2 = createInstance("b"); - Map instances = createMicroserviceInstances("name", instance1, instance2); + StatefulDiscoveryInstance instance1 = createInstance("a", "b"); + StatefulDiscoveryInstance instance2 = createInstance("b"); + List instances = createMicroserviceInstances(instance1, instance2); parent.data(instances); result = filter.createDiscoveryTreeNode("a", context, parent); - Assert.assertEquals("parent/a", result.name()); - Assert.assertThat(result.collectionData(), Matchers.contains(instance1.getEndpoints().get(0))); + Assertions.assertEquals("parent/a", result.name()); + MatcherAssert.assertThat(result.collectionData(), + Matchers.contains(instance1.getEndpoints().get(0))); } @Test public void createDiscoveryTree_allTransport() { - MicroserviceInstance instance1 = createInstance("a", "b"); - MicroserviceInstance instance2 = createInstance("b"); - Map instances = createMicroserviceInstances("name", instance1, instance2); + StatefulDiscoveryInstance instance1 = createInstance("a", "b"); + StatefulDiscoveryInstance instance2 = createInstance("b"); + List instances = createMicroserviceInstances(instance1, instance2); parent.data(instances); result = filter.createDiscoveryTreeNode("", context, parent); - Assert.assertEquals("parent/", result.name()); + Assertions.assertEquals("parent/", result.name()); List expect = new ArrayList<>(); expect.addAll(instance1.getEndpoints()); expect.addAll(instance2.getEndpoints()); - Assert.assertThat(result.collectionData(), Matchers.contains(expect.toArray())); + MatcherAssert.assertThat(result.collectionData(), Matchers.contains(expect.toArray())); } @Test public void createDiscoveryTree_ignoreInvalid() { - MicroserviceInstance instance1 = createInstance("a", "b"); - MicroserviceInstance instance2 = createInstance(""); - Map instances = createMicroserviceInstances("name", instance1, instance2); + StatefulDiscoveryInstance instance1 = createInstance("a", "b"); + StatefulDiscoveryInstance instance2 = createInstance(""); + List instances = createMicroserviceInstances(instance1, instance2); parent.data(instances); result = filter.createDiscoveryTreeNode("", context, parent); - Assert.assertEquals("parent/", result.name()); - Assert.assertThat(result.collectionData(), Matchers.contains(instance1.getEndpoints().toArray())); + Assertions.assertEquals("parent/", result.name()); + MatcherAssert.assertThat(result.collectionData(), + Matchers.contains(instance1.getEndpoints().toArray())); } @Test public void createEndpointNull() { disableCreate = true; - MicroserviceInstance instance1 = createInstance("a", "b"); - Map instances = createMicroserviceInstances("name", instance1); + StatefulDiscoveryInstance instance1 = createInstance("a", "b"); + List instances = createMicroserviceInstances(instance1); parent.data(instances); result = filter.createDiscoveryTreeNode("", context, parent); - Assert.assertEquals("parent/", result.name()); - Assert.assertThat(result.collectionData(), Matchers.empty()); + Assertions.assertEquals("parent/", result.name()); + MatcherAssert.assertThat(result.collectionData(), Matchers.empty()); } } diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryContext.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryContext.java index faae6f330bf..53c9d026c6f 100644 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryContext.java +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryContext.java @@ -17,10 +17,8 @@ package org.apache.servicecomb.registry.discovery; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestDiscoveryContext { DiscoveryContext context = new DiscoveryContext(); @@ -30,7 +28,7 @@ public void inputParameters() { Object inputParameters = new Object(); context.setInputParameters(inputParameters); - Assert.assertSame(inputParameters, context.getInputParameters()); + Assertions.assertSame(inputParameters, context.getInputParameters()); } @Test @@ -39,19 +37,19 @@ public void contextParameters() { Object value = new Object(); context.putContextParameter(name, value); - Assert.assertSame(value, context.getContextParameter(name)); - Assert.assertNull(context.getContextParameter("notExist")); + Assertions.assertSame(value, context.getContextParameter(name)); + Assertions.assertNull(context.getContextParameter("notExist")); } @Test public void rerun() { - Assert.assertNull(context.popRerunFilter()); + Assertions.assertNull(context.popRerunFilter()); DiscoveryTreeNode node = new DiscoveryTreeNode(); context.setCurrentNode(node); context.pushRerunFilter(); - Assert.assertSame(node, context.popRerunFilter()); - Assert.assertNull(context.popRerunFilter()); + Assertions.assertSame(node, context.popRerunFilter()); + Assertions.assertNull(context.popRerunFilter()); } } diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTree.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTree.java index d07813bf968..d726d1b59c0 100644 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTree.java +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTree.java @@ -18,127 +18,82 @@ package org.apache.servicecomb.registry.discovery; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; -import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.config.DynamicProperties; import org.apache.servicecomb.foundation.common.cache.VersionedCache; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryTree; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.apache.servicecomb.registry.cache.InstanceCacheManager; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mocked; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestDiscoveryTree { - @Before - public void before() { - ConfigUtil.installDynamicConfig(); - } - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - - DiscoveryTree discoveryTree = new DiscoveryTree(); - - List filters = Deencapsulation.getField(discoveryTree, "filters"); - DiscoveryContext context = new DiscoveryContext(); DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent"); DiscoveryTreeNode result; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void loadFromSPI(@Mocked DiscoveryFilter f1, @Mocked DiscoveryFilter f2) { - Class cls = DiscoveryFilter.class; - new Expectations(SPIServiceUtils.class) { - { - SPIServiceUtils.getSortedService(cls); - result = Arrays.asList(f1, f2); - } - }; - - discoveryTree.loadFromSPI(cls); + @BeforeEach + public void before() { - Assert.assertThat(filters, Matchers.contains(f1, f2)); } - @Test - public void sort(@Mocked DiscoveryFilter f1, @Mocked DiscoveryFilter f2, @Mocked DiscoveryFilter f3) { - new Expectations() { - { - f1.getOrder(); - result = -1; - f1.enabled(); - result = true; - f2.getOrder(); - result = 0; - f2.enabled(); - result = true; - f3.getOrder(); - result = 0; - f3.enabled(); - result = false; - } - }; - discoveryTree.addFilter(f3); - discoveryTree.addFilter(f2); - discoveryTree.addFilter(f1); - discoveryTree.sort(); - - Assert.assertThat(filters, Matchers.contains(f1, f2)); + @AfterEach + public void tearDown() { } @Test public void isMatch_existingNull() { - Assert.assertFalse(discoveryTree.isMatch(null, null)); + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); + Assertions.assertFalse(discoveryTree.isMatch(null, null)); } @Test public void isMatch_yes() { + DiscoveryTree discoveryTree = new DiscoveryTree(new DiscoveryManager(Collections.emptyList(), + List.of(new TelnetInstancePing()))); parent.cacheVersion(1); - Assert.assertTrue(discoveryTree.isMatch(new DiscoveryTreeNode().cacheVersion(1), parent)); + Assertions.assertTrue(discoveryTree.isMatch(new DiscoveryTreeNode().cacheVersion(1), parent)); } @Test public void isMatch_no() { + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); parent.cacheVersion(0); - Assert.assertFalse(discoveryTree.isExpired(new DiscoveryTreeNode().cacheVersion(1), parent)); + Assertions.assertFalse(discoveryTree.isExpired(new DiscoveryTreeNode().cacheVersion(1), parent)); } @Test public void isExpired_existingNull() { - Assert.assertTrue(discoveryTree.isExpired(null, null)); + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); + Assertions.assertTrue(discoveryTree.isExpired(null, null)); } @Test public void isExpired_yes() { + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); parent.cacheVersion(1); - Assert.assertTrue(discoveryTree.isExpired(new DiscoveryTreeNode().cacheVersion(0), parent)); + Assertions.assertTrue(discoveryTree.isExpired(new DiscoveryTreeNode().cacheVersion(0), parent)); } @Test public void isExpired_no() { + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); parent.cacheVersion(0); - Assert.assertFalse(discoveryTree.isExpired(new DiscoveryTreeNode().cacheVersion(0), parent)); + Assertions.assertFalse(discoveryTree.isExpired(new DiscoveryTreeNode().cacheVersion(0), parent)); } static class DiscoveryFilterForTest implements DiscoveryFilter { @@ -170,45 +125,34 @@ public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode p @Test public void filterNormal() { + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); parent.name("1.0.0-2.0.0"); - discoveryTree.addFilter(new DiscoveryFilterForTest("g1")); - discoveryTree.addFilter(new DiscoveryFilterForTest(null)); - discoveryTree.addFilter(new DiscoveryFilterForTest("g2")); - discoveryTree.addFilter(new DiscoveryFilterForTest(null)); - - result = discoveryTree.discovery(context, parent); + discoveryTree.setDiscoveryFilters(Arrays.asList(new DiscoveryFilterForTest("g1"), + new DiscoveryFilterForTest(null), new DiscoveryFilterForTest("g2"), + new DiscoveryFilterForTest(null))); + result = discoveryTree.discovery("app", "service", context, parent); - Assert.assertEquals("1.0.0-2.0.0/g1/g2", result.name()); + Assertions.assertEquals("1.0.0-2.0.0/g1/g2", result.name()); } @Test - public void easyDiscovery(@Mocked InstanceCacheManager instanceCacheManager) { - new Expectations(DiscoveryManager.class) { - { - DiscoveryManager.INSTANCE.getInstanceCacheManager(); - result = instanceCacheManager; - instanceCacheManager.getOrCreateVersionedCache(anyString, anyString, anyString); - result = parent; - } - }; - - result = discoveryTree.discovery(context, null, null, null); - Assert.assertEquals(parent.name(), result.name()); - Assert.assertEquals(parent.cacheVersion(), result.cacheVersion()); + public void easyDiscovery() { + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + Mockito.when(discoveryManager.getOrCreateVersionedCache("app", "svc")).thenReturn(parent); + + result = discoveryTree.discovery(context, "app", "svc"); + Assertions.assertEquals(parent.name(), result.name()); + Assertions.assertEquals(parent.cacheVersion(), result.cacheVersion()); } @Test - public void discovery_filterReturnNull(@Mocked InstanceCacheManager instanceCacheManager) { - new Expectations(DiscoveryManager.class) { - { - DiscoveryManager.INSTANCE.getInstanceCacheManager(); - result = instanceCacheManager; - instanceCacheManager.getOrCreateVersionedCache(anyString, anyString, anyString); - result = parent; - } - }; - + public void discovery_filterReturnNull() { + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + Mockito.when(discoveryManager.getOrCreateVersionedCache("app", "service")).thenReturn(parent); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); DiscoveryFilter filter = new DiscoveryFilter() { @Override public int getOrder() { @@ -220,19 +164,18 @@ public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode p return null; } }; - discoveryTree.addFilter(filter); + discoveryTree.setDiscoveryFilters(Arrays.asList(filter)); - expectedException.expect(ServiceCombException.class); - expectedException.expectMessage(Matchers.is(filter.getClass().getName() + " discovery return null.")); - - result = discoveryTree.discovery(context, null, null, null); + ServiceCombException exception = Assertions.assertThrows(ServiceCombException.class, + () -> result = discoveryTree.discovery(context, "app", "service")); + Assertions.assertEquals(filter.getClass().getName() + " discovery return null.", exception.getMessage()); } @Test public void filterRerun() { parent.name("1.0.0-2.0.0"); - discoveryTree.addFilter(new DiscoveryFilterForTest("g1") { + DiscoveryFilterForTest f1 = new DiscoveryFilterForTest("g1") { @Override public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode parent) { if (context.getContextParameter("step") == null) { @@ -243,8 +186,8 @@ public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode p return new DiscoveryTreeNode().name(groupName).data("second"); } - }); - discoveryTree.addFilter(new DiscoveryFilterForTest(null) { + }; + DiscoveryFilterForTest f2 = new DiscoveryFilterForTest(null) { @Override public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode parent) { if ("first".equals(parent.data())) { @@ -253,50 +196,84 @@ public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode p return new DiscoveryTreeNode().data(parent.data()); } - }); - - result = discoveryTree.discovery(context, parent); - - Assert.assertEquals("second", result.data()); - } - - @Test - public void avoidConcurrentProblem() { - Deencapsulation.setField(discoveryTree, "root", parent.cacheVersion(1)); - Assert.assertTrue(parent.children().isEmpty()); - - discoveryTree.discovery(context, new VersionedCache().cacheVersion(0).name("input")); - Assert.assertTrue(parent.children().isEmpty()); - } - - @Test - public void getOrCreateRoot_match() { - Deencapsulation.setField(discoveryTree, "root", parent); - - DiscoveryTreeNode root = discoveryTree.getOrCreateRoot(parent); + }; + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); + discoveryTree.setDiscoveryFilters(Arrays.asList(f1, f2)); + result = discoveryTree.discovery("app", "service", context, parent); - Assert.assertSame(parent, root); + Assertions.assertEquals("second", result.data()); } @Test - public void getOrCreateRoot_expired() { - Deencapsulation.setField(discoveryTree, "root", parent); - - VersionedCache inputCache = new VersionedCache().cacheVersion(parent.cacheVersion() + 1); - DiscoveryTreeNode root = discoveryTree.getOrCreateRoot(inputCache); - - Assert.assertEquals(inputCache.cacheVersion(), root.cacheVersion()); - Assert.assertSame(Deencapsulation.getField(discoveryTree, "root"), root); + @SuppressWarnings("unchecked") + public void test_multi_service_discovery_correct() { + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + DiscoveryContext discoveryContext = new DiscoveryContext(); + + List service1 = Arrays.asList("s11", "s12"); + Mockito.when(discoveryManager.getOrCreateVersionedCache("app", "service1")) + .thenReturn(new VersionedCache().name("0+").data(service1)); + DiscoveryTreeNode result = discoveryTree.discovery(discoveryContext, "app", "service1"); + Assertions.assertArrayEquals(service1.toArray(new String[0]), + ((List) result.data()).toArray(new String[0])); + + List service2 = Arrays.asList("s21", "s22"); + Mockito.when(discoveryManager.getOrCreateVersionedCache("app", "service2")) + .thenReturn(new VersionedCache().name("0+").data(service2)); + result = discoveryTree.discovery(discoveryContext, "app", "service2"); + Assertions.assertArrayEquals(service2.toArray(new String[0]), + ((List) result.data()).toArray(new String[0])); + + result = discoveryTree.discovery(discoveryContext, "app", "service1"); + Assertions.assertArrayEquals(service1.toArray(new String[0]), + ((List) result.data()).toArray(new String[0])); } @Test - public void getOrCreateRoot_tempRoot() { - Deencapsulation.setField(discoveryTree, "root", parent); - - VersionedCache inputCache = new VersionedCache().cacheVersion(parent.cacheVersion() - 1); - DiscoveryTreeNode root = discoveryTree.getOrCreateRoot(inputCache); + @SuppressWarnings("unchecked") + public void test_one_service_concurrent_correct() throws Exception { + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + DiscoveryContext discoveryContext = new DiscoveryContext(); + InstanceStatusDiscoveryFilter filter = new InstanceStatusDiscoveryFilter(); + DynamicProperties dynamicProperties = Mockito.mock(DynamicProperties.class); + Mockito.when(dynamicProperties.getBooleanProperty(Mockito.eq("servicecomb.loadbalance.filter.status.enabled"), + Mockito.any(), + Mockito.eq(true))) + .thenReturn(true); + filter.setDynamicProperties(dynamicProperties); + discoveryTree.setDiscoveryFilters(List.of(filter)); + + StatefulDiscoveryInstance instance1 = Mockito.mock(StatefulDiscoveryInstance.class); + StatefulDiscoveryInstance instance2 = Mockito.mock(StatefulDiscoveryInstance.class); + + VersionedCache expects0 = new VersionedCache().autoCacheVersion().name("0+") + .data(Arrays.asList(instance1, instance2)); + VersionedCache[] expects999 = new VersionedCache[999]; + for (int i = 0; i < 999; i++) { + expects999[i] = new VersionedCache().name("0+") + .data(Arrays.asList(instance1, instance2)).cacheVersion(i + 1); + } + Mockito.when(discoveryManager.getOrCreateVersionedCache("app", "service1")) + .thenReturn(expects0, expects999); + + CountDownLatch countDownLatch = new CountDownLatch(1000); + AtomicInteger success = new AtomicInteger(0); + for (int i = 0; i < 10; i++) { + new Thread(() -> { + for (int j = 0; j < 100; j++) { + DiscoveryTreeNode result = discoveryTree.discovery(discoveryContext, "app", "service1"); + if (((List) result.data()).size() == 2) { + success.getAndIncrement(); + } + countDownLatch.countDown(); + } + }).start(); + } - Assert.assertEquals(inputCache.cacheVersion(), root.cacheVersion()); - Assert.assertNotSame(Deencapsulation.getField(discoveryTree, "root"), root); + countDownLatch.await(3000, TimeUnit.MILLISECONDS); + Assertions.assertEquals(1000, success.get()); } } diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTreeNode.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTreeNode.java index e450a870955..0dcd4ff99ac 100644 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTreeNode.java +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestDiscoveryTreeNode.java @@ -21,33 +21,32 @@ import java.util.Map; import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestDiscoveryTreeNode { DiscoveryTreeNode node = new DiscoveryTreeNode(); @Test public void childrenInited() { - Assert.assertFalse(node.childrenInited()); + Assertions.assertFalse(node.childrenInited()); node.childrenInited(true); - Assert.assertTrue(node.childrenInited()); + Assertions.assertTrue(node.childrenInited()); } @Test public void level() { node.level(1); - Assert.assertEquals(1, node.level()); + Assertions.assertEquals(1, node.level()); } @Test public void attribute() { node.attribute("k1", "v1"); - Assert.assertEquals("v1", node.attribute("k1")); + Assertions.assertEquals("v1", node.attribute("k1")); } @Test @@ -55,7 +54,7 @@ public void children() { Map children = new HashMap<>(); node.children(children); - Assert.assertSame(children, node.children()); + Assertions.assertSame(children, node.children()); } @Test @@ -63,7 +62,7 @@ public void child() { DiscoveryTreeNode child = new DiscoveryTreeNode().name("child"); node.child(child.name(), child); - Assert.assertSame(child, node.child(child.name())); + Assertions.assertSame(child, node.child(child.name())); } @Test @@ -72,8 +71,8 @@ public void fromCache() { VersionedCache other = new VersionedCache().cacheVersion(1).name("cache").data(data); node.fromCache(other); - Assert.assertEquals(1, node.cacheVersion()); - Assert.assertEquals("cache", node.name()); - Assert.assertSame(data, node.data()); + Assertions.assertEquals(1, node.cacheVersion()); + Assertions.assertEquals("cache", node.name()); + Assertions.assertSame(data, node.data()); } } diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestInstanceStatusDiscoveryFilter.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestInstanceStatusDiscoveryFilter.java new file mode 100644 index 00000000000..8e7307098b9 --- /dev/null +++ b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/discovery/TestInstanceStatusDiscoveryFilter.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.registry.discovery; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.HistoryStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.IsolationStatus; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance.PingStatus; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class TestInstanceStatusDiscoveryFilter { + @Test + public void test_all_group_correct_init() { + InstanceStatusDiscoveryFilter filter = new InstanceStatusDiscoveryFilter(); + DiscoveryTreeNode parent = new DiscoveryTreeNode(); + List instances = new ArrayList<>(); + StatefulDiscoveryInstance instance1 = Mockito.mock(StatefulDiscoveryInstance.class); + Mockito.when(instance1.getHistoryStatus()).thenReturn(HistoryStatus.CURRENT); + Mockito.when(instance1.getStatus()).thenReturn(MicroserviceInstanceStatus.UP); + Mockito.when(instance1.getPingStatus()).thenReturn(PingStatus.OK); + Mockito.when(instance1.getIsolationStatus()).thenReturn(IsolationStatus.NORMAL); + StatefulDiscoveryInstance instance2 = Mockito.mock(StatefulDiscoveryInstance.class); + Mockito.when(instance2.getHistoryStatus()).thenReturn(HistoryStatus.CURRENT); + Mockito.when(instance2.getStatus()).thenReturn(MicroserviceInstanceStatus.UP); + Mockito.when(instance2.getPingStatus()).thenReturn(PingStatus.UNKNOWN); + Mockito.when(instance2.getIsolationStatus()).thenReturn(IsolationStatus.NORMAL); + StatefulDiscoveryInstance instance3 = Mockito.mock(StatefulDiscoveryInstance.class); + Mockito.when(instance3.getHistoryStatus()).thenReturn(HistoryStatus.HISTORY); + Mockito.when(instance3.getStatus()).thenReturn(MicroserviceInstanceStatus.UP); + Mockito.when(instance3.getPingStatus()).thenReturn(PingStatus.OK); + Mockito.when(instance3.getIsolationStatus()).thenReturn(IsolationStatus.NORMAL); + StatefulDiscoveryInstance instance4 = Mockito.mock(StatefulDiscoveryInstance.class); + Mockito.when(instance4.getHistoryStatus()).thenReturn(HistoryStatus.CURRENT); + Mockito.when(instance4.getStatus()).thenReturn(MicroserviceInstanceStatus.UP); + Mockito.when(instance4.getPingStatus()).thenReturn(PingStatus.FAIL); + Mockito.when(instance4.getIsolationStatus()).thenReturn(IsolationStatus.NORMAL); + instances.addAll(Arrays.asList(instance1, instance2, instance3, instance4)); + + parent.name("parent"); + parent.data(instances); + filter.init(new DiscoveryContext(), parent); + + List level0 = parent + .child(InstanceStatusDiscoveryFilter.GROUP_PREFIX + 1) + .data(); + Assertions.assertEquals(1, level0.size()); + List level1 = parent + .child(InstanceStatusDiscoveryFilter.GROUP_PREFIX + 2) + .data(); + Assertions.assertEquals(1, level1.size()); + Assertions.assertEquals(1, level1.size()); + List level2 = parent + .child(InstanceStatusDiscoveryFilter.GROUP_PREFIX + 3) + .data(); + Assertions.assertEquals(1, level2.size()); + List level3 = parent + .child(InstanceStatusDiscoveryFilter.GROUP_PREFIX + 4) + .data(); + Assertions.assertEquals(1, level3.size()); + + Assertions.assertEquals(null, parent + .child(InstanceStatusDiscoveryFilter.GROUP_PREFIX + 5)); + } +} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java deleted file mode 100644 index 1eb629dc03f..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersion.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestVersion { - Version version; - - short s1 = 1; - - short s2 = 2; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void constructFromStringNormalOnlyMajor() { - version = new Version("1"); - Assert.assertEquals("1.0.0.0", version.getVersion()); - Assert.assertEquals(1, version.getMajor()); - Assert.assertEquals(0, version.getMinor()); - Assert.assertEquals(0, version.getPatch()); - } - - @Test - public void constructFromStringNormalOnlyMajorMinor() { - version = new Version("1.1"); - Assert.assertEquals("1.1.0.0", version.getVersion()); - Assert.assertEquals(1, version.getMajor()); - Assert.assertEquals(1, version.getMinor()); - Assert.assertEquals(0, version.getPatch()); - } - - @Test - public void constructFromStringOnlyMajorMinorPatch() { - version = new Version("1.1.1"); - Assert.assertEquals("1.1.1.0", version.getVersion()); - Assert.assertEquals(1, version.getMajor()); - Assert.assertEquals(1, version.getMinor()); - Assert.assertEquals(1, version.getPatch()); - Assert.assertEquals(0, version.getBuild()); - } - - @Test - public void constructFromStringNormal() { - version = new Version("1.1.1.1"); - Assert.assertEquals("1.1.1.1", version.getVersion()); - Assert.assertEquals(1, version.getMajor()); - Assert.assertEquals(1, version.getMinor()); - Assert.assertEquals(1, version.getPatch()); - Assert.assertEquals(1, version.getBuild()); - } - - @Test - public void constructFromStringInvalidNull() { - expectedException.expect(NullPointerException.class); - - version = new Version(null); - } - - @Test - public void constructFromStringInvalidEmpty() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Invalid major \"\", version \"\".")); - expectedException.expectCause(Matchers.instanceOf(NumberFormatException.class)); - - version = new Version(""); - } - - @Test - public void constructFromStringInvalidMajorNegative() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("major \"-1\" can not be negative, version \"-1\".")); - - version = new Version("-1"); - } - - @Test - public void constructFromStringInvalidMajorDot() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Invalid minor \"\", version \"1.\".")); - expectedException.expectCause(Matchers.instanceOf(NumberFormatException.class)); - - version = new Version("1."); - } - - @Test - public void constructFromStringInvalidMinorNegative() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("minor \"-1\" can not be negative, version \"1.-1\".")); - - version = new Version("1.-1"); - } - - @Test - public void constructFromStringInvalidMinorDot() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Invalid patch \"\", version \"1.1.\".")); - expectedException.expectCause(Matchers.instanceOf(NumberFormatException.class)); - - version = new Version("1.1."); - } - - @Test - public void constructFromStringInvalidPatchNegative() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("patch \"-1\" can not be negative, version \"1.1.-1\".")); - - version = new Version("1.1.-1"); - } - - @Test - public void constructFromStringInvalidPatchDot() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Invalid build \"\", version \"1.1.1.\".")); - expectedException.expectCause(Matchers.instanceOf(NumberFormatException.class)); - - version = new Version("1.1.1."); - } - - @Test - public void constructFromStringInvalidBuildNegative() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("build \"-1\" can not be negative, version \"1.1.1.-1\".")); - - version = new Version("1.1.1.-1"); - } - - @Test - public void constructFromStringInvalidTooManyPart() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Invalid version \"1.1.1.1.\".")); - version = new Version("1.1.1.1."); - } - - @Test - public void constructFromNumber() { - version = new Version(s1, s1, s1, s1); - Assert.assertEquals("1.1.1.1", version.getVersion()); - Assert.assertEquals(1, version.getMajor()); - Assert.assertEquals(1, version.getMinor()); - Assert.assertEquals(1, version.getPatch()); - Assert.assertEquals(1, version.getPatch()); - } - - @Test - public void testToString() { - version = new Version(s1, s1, s1, s1); - Assert.assertEquals("1.1.1.1", version.toString()); - } - - @Test - public void testHashCode() { - version = new Version(s1, s1, s1, s1); - Assert.assertEquals(version.getVersion().hashCode(), version.hashCode()); - } - - @Test - public void testEquals() { - version = new Version(s1, s1, s1, s1); - - Assert.assertTrue(version.equals(version)); - Assert.assertTrue(version.equals(new Version(s1, s1, s1, s1))); - Assert.assertFalse(version.equals(null)); - } - - @Test - public void compareTo() { - version = new Version(s1, s1, s1, s1); - - Assert.assertEquals(0, version.compareTo(version)); - Assert.assertEquals(0, version.compareTo(new Version(s1, s1, s1, s1))); - - Assert.assertEquals(-1, version.compareTo(new Version(s1, s1, s2, s1))); - Assert.assertEquals(-1, version.compareTo(new Version(s1, s2, s1, s1))); - Assert.assertEquals(-1, version.compareTo(new Version(s2, s1, s1, s1))); - - Assert.assertEquals(1, version.compareTo(new Version((short) 0, - Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE))); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java deleted file mode 100644 index 6726de57488..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRule.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; -import org.junit.Assert; -import org.junit.Test; - -public class TestVersionRule { - class VersionRuleForTest extends VersionRule { - public VersionRuleForTest(String versionRule) { - super(versionRule); - } - - @Override - public boolean isMatch(Version version, Version latestVersion) { - return true; - } - } - - VersionRule versionRule = new VersionRuleForTest("abc"); - - @Test - public void isAccept() { - Assert.assertTrue(versionRule.isAccept(null)); - } - - @Test - public void getVersionRule() { - Assert.assertEquals("abc", versionRule.getVersionRule()); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleFixedParser.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleFixedParser.java deleted file mode 100644 index 079d6cb75cd..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleFixedParser.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.registry.version; - -import org.junit.Assert; -import org.junit.Test; - -public class TestVersionRuleFixedParser { - VersionRule versionRule; - - VersionRuleParser parser = new VersionRuleFixedParser(); - - @Test - public void parseNormal() { - versionRule = parser.parse("1"); - Assert.assertEquals("1.0.0.0", versionRule.getVersionRule()); - } - - @Test - public void isMatch() { - versionRule = parser.parse("1"); - Assert.assertTrue(versionRule.isMatch(VersionConst.v1, null)); - Assert.assertFalse(versionRule.isMatch(VersionConst.v2, null)); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleLatestParser.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleLatestParser.java deleted file mode 100644 index f12c648ec89..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleLatestParser.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.junit.Assert; -import org.junit.Test; - -public class TestVersionRuleLatestParser { - VersionRuleParser parser = new VersionRuleLatestParser(); - - VersionRule versionRule = parser.parse(DefinitionConst.VERSION_RULE_LATEST); - - @Test - public void parseInvalue() { - Assert.assertNull(parser.parse("")); - } - - @Test - public void parseNormal() { - Assert.assertEquals(DefinitionConst.VERSION_RULE_LATEST, versionRule.getVersionRule()); - } - - @Test - public void isAccept() { - Assert.assertTrue(versionRule.isAccept(null)); - } - - @Test - public void isMatch() { - Assert.assertTrue(versionRule.isMatch(VersionConst.v1, VersionConst.v1)); - Assert.assertFalse(versionRule.isMatch(VersionConst.v2, VersionConst.v1)); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleRangeParser.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleRangeParser.java deleted file mode 100644 index 768c7a61dae..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleRangeParser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.registry.version; - -import org.junit.Assert; -import org.junit.Test; - -public class TestVersionRuleRangeParser { - VersionRuleParser parser = new VersionRuleRangeParser(); - - VersionRule versionRule = parser.parse("1-2"); - - @Test - public void parseInvalid() { - Assert.assertNull(parser.parse("")); - Assert.assertNull(parser.parse("-")); - Assert.assertNull(parser.parse("1-")); - } - - @Test - public void parseNormal() { - Assert.assertEquals("1.0.0.0-2.0.0.0", versionRule.getVersionRule()); - } - - @Test - public void isMatch() { - Assert.assertFalse(versionRule.isMatch(VersionConst.v0, null)); - Assert.assertTrue(versionRule.isMatch(VersionConst.v1, null)); - Assert.assertTrue(versionRule.isMatch(VersionConst.v1Max, null)); - Assert.assertFalse(versionRule.isMatch(VersionConst.v2, null)); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleStartFromParser.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleStartFromParser.java deleted file mode 100644 index 75ac9005093..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleStartFromParser.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.registry.version; - -import org.junit.Assert; -import org.junit.Test; - -public class TestVersionRuleStartFromParser { - VersionRuleParser parser = new VersionRuleStartFromParser(); - - VersionRule versionRule = parser.parse("1+"); - - @Test - public void parseInvalid() { - Assert.assertNull(parser.parse("")); - Assert.assertNull(parser.parse("+")); - Assert.assertNull(parser.parse("1+1")); - } - - @Test - public void parseNormal() { - Assert.assertEquals("1.0.0.0+", versionRule.getVersionRule()); - } - - @Test - public void isMatch() { - Assert.assertFalse(versionRule.isMatch(VersionConst.v0, null)); - Assert.assertTrue(versionRule.isMatch(VersionConst.v1, null)); - Assert.assertTrue(versionRule.isMatch(VersionConst.v1Max, null)); - Assert.assertTrue(versionRule.isMatch(VersionConst.v2, null)); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleUtils.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleUtils.java deleted file mode 100644 index 5ff8fc860cf..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionRuleUtils.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.apache.servicecomb.registry.version.VersionRule; -import org.apache.servicecomb.registry.version.VersionRuleFixedParser.FixedVersionRule; -import org.apache.servicecomb.registry.version.VersionRuleLatestParser.LatestVersionRule; -import org.apache.servicecomb.registry.version.VersionRuleRangeParser.RangeVersionRule; -import org.apache.servicecomb.registry.version.VersionRuleStartFromParser.StartFromVersionRule; -import org.apache.servicecomb.registry.version.VersionRuleUtils; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class TestVersionRuleUtils { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Test - public void fixed() { - VersionRule versionRule = VersionRuleUtils.getOrCreate("1"); - Assert.assertThat(versionRule, Matchers.instanceOf(FixedVersionRule.class)); - Assert.assertSame(versionRule, VersionRuleUtils.getOrCreate("1")); - } - - @Test - public void latest() { - VersionRule versionRule = VersionRuleUtils.getOrCreate(DefinitionConst.VERSION_RULE_LATEST); - Assert.assertThat(versionRule, Matchers.instanceOf(LatestVersionRule.class)); - Assert.assertSame(versionRule, VersionRuleUtils.getOrCreate(DefinitionConst.VERSION_RULE_LATEST)); - } - - @Test - public void range() { - VersionRule versionRule = VersionRuleUtils.getOrCreate("1-2"); - Assert.assertThat(versionRule, Matchers.instanceOf(RangeVersionRule.class)); - Assert.assertSame(versionRule, VersionRuleUtils.getOrCreate("1-2")); - } - - @Test - public void startFrom() { - VersionRule versionRule = VersionRuleUtils.getOrCreate("1+"); - Assert.assertThat(versionRule, Matchers.instanceOf(StartFromVersionRule.class)); - Assert.assertSame(versionRule, VersionRuleUtils.getOrCreate("1+")); - } - - @Test - public void invalid() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Invalid major \"\", version \"\".")); - - VersionRuleUtils.getOrCreate(""); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java deleted file mode 100644 index 1dd8e850781..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/TestVersionUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.registry.version; - -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.servicecomb.foundation.common.Version; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import mockit.Deencapsulation; - -public class TestVersionUtils { - @Before - public void setup() { - Deencapsulation.setField(VersionUtils.class, "versionCache", new ConcurrentHashMap<>()); - } - - @After - public void teardown() { - Deencapsulation.setField(VersionUtils.class, "versionCache", new ConcurrentHashMap<>()); - } - - @Test - public void getOrCreate() { - Version v = VersionUtils.getOrCreate("1.0.0"); - - Assert.assertEquals("1.0.0.0", v.getVersion()); - Assert.assertSame(v, VersionUtils.getOrCreate("1.0.0")); - } -} diff --git a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java b/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java deleted file mode 100644 index f8df0570e54..00000000000 --- a/foundations/foundation-registry/src/test/java/org/apache/servicecomb/registry/version/VersionConst.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.registry.version; - -import org.apache.servicecomb.foundation.common.Version; - -public interface VersionConst { - Version v0 = new Version((short) 0, (short) 0, (short) 0, (short) 0); - - Version v1 = new Version("1"); - - Version v1Max = new Version((short) 1, Short.MAX_VALUE, Short.MAX_VALUE, Short.MAX_VALUE); - - Version v2 = new Version("2"); -} diff --git a/foundations/foundation-registry/src/test/resources/log4j2.xml b/foundations/foundation-registry/src/test/resources/log4j2.xml new file mode 100644 index 00000000000..3125ebd11e4 --- /dev/null +++ b/foundations/foundation-registry/src/test/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/foundations/foundation-spi/pom.xml b/foundations/foundation-spi/pom.xml index 1e3847f31aa..aa38214b3ee 100644 --- a/foundations/foundation-spi/pom.xml +++ b/foundations/foundation-spi/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb foundations - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT foundation-spi Java Chassis::Foundations::SSL @@ -35,5 +35,10 @@ org.springframework spring-core + + org.jmockit + jmockit + test + diff --git a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderLoader.java b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderLoader.java index 39e0bfa1a5d..668e77faa38 100644 --- a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderLoader.java +++ b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderLoader.java @@ -29,6 +29,10 @@ public class AuthHeaderLoader { private static final AuthHeaderLoader INSTANCE = new AuthHeaderLoader(); + private AuthHeaderLoader() { + + } + public static AuthHeaderLoader getInstance() { return INSTANCE; } diff --git a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderProvider.java b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderProvider.java index 313c19ee5ba..0e036e21a58 100644 --- a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderProvider.java +++ b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/AuthHeaderProvider.java @@ -21,11 +21,21 @@ import java.util.Map; public interface AuthHeaderProvider { - default Map authHeaders() { + /** + * Obtain RBAC authentication request header, host is the key of cache + * + * @param host engine address ip + * @return auth headers + */ + default Map authHeaders(String host) { return new HashMap<>(0); } default Map getSignAuthHeaders(SignRequest request) { - return authHeaders(); + String host = ""; + if (request != null && request.getEndpoint() != null) { + host = request.getEndpoint().getHost(); + } + return authHeaders(host); } } diff --git a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/SignRequest.java b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/SignRequest.java index 116d5570f58..a41aaf571b5 100644 --- a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/SignRequest.java +++ b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/auth/SignRequest.java @@ -37,7 +37,7 @@ public class SignRequest { /** * Map of the headers included in this request */ - private Map headers = new HashMap<>(); + private final Map headers = new HashMap<>(); /** * The service endpoint to which this request should be sent @@ -58,7 +58,7 @@ public class SignRequest { * The datetime in milliseconds for which the signature needs to be * computed. */ - private long signingDateTimeMilli = System.currentTimeMillis(); + private final long signingDateTimeMilli = System.currentTimeMillis(); /** * The scope of the signature. diff --git a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIOrder.java b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIOrder.java index b9fc016ee17..adaf18de073 100644 --- a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIOrder.java +++ b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIOrder.java @@ -17,7 +17,9 @@ package org.apache.servicecomb.foundation.common.utils; -public interface SPIOrder { +import org.springframework.core.Ordered; + +public interface SPIOrder extends Ordered { default int getOrder() { return 0; } diff --git a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIServiceUtils.java b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIServiceUtils.java index ea8a0bc12ea..abd2dcab32e 100644 --- a/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIServiceUtils.java +++ b/foundations/foundation-spi/src/main/java/org/apache/servicecomb/foundation/common/utils/SPIServiceUtils.java @@ -76,11 +76,12 @@ public static List loadSortedService(Class serviceType) { .map(Entry::getValue) .collect(Collectors.toList()); - LOGGER.info("Found SPI service {}, count={}.", serviceType.getName(), services.size()); + StringBuilder info = new StringBuilder(); for (int idx = 0; idx < services.size(); idx++) { T service = services.get(idx); - LOGGER.info(" {}. {}.", idx, service.getClass().getName()); + info.append("{").append(idx).append(",").append(service.getClass().getSimpleName()).append("}"); } + LOGGER.info("Found SPI service {}, services={}.", serviceType.getSimpleName(), info); return services; } diff --git a/foundations/foundation-spi/src/test/java/org/apache/servicecomb/foundation/common/utils/TestSPIServiceUtils.java b/foundations/foundation-spi/src/test/java/org/apache/servicecomb/foundation/common/utils/TestSPIServiceUtils.java index 6b26ff9e882..040c840718f 100644 --- a/foundations/foundation-spi/src/test/java/org/apache/servicecomb/foundation/common/utils/TestSPIServiceUtils.java +++ b/foundations/foundation-spi/src/test/java/org/apache/servicecomb/foundation/common/utils/TestSPIServiceUtils.java @@ -22,17 +22,20 @@ import java.util.Map; import java.util.ServiceLoader; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnJre; +import org.junit.jupiter.api.condition.JRE; +import org.mockito.Mockito; import org.springframework.core.Ordered; import mockit.Deencapsulation; import mockit.Expectations; -import mockit.Mocked; /** - * Test SPIServiceUtils + * Test SPIServiceUtils * * */ @@ -40,30 +43,33 @@ public class TestSPIServiceUtils { @Test public void testGetTargetServiceNull() { SPIServiceDef0 service = SPIServiceUtils.getTargetService(SPIServiceDef0.class); - Assert.assertNull(service); + Assertions.assertNull(service); } @Test public void testGetTargetServiceNotNull() { SPIServiceDef service = SPIServiceUtils.getTargetService(SPIServiceDef.class); - Assert.assertTrue(SPIServiceDef.class.isInstance(service)); + Assertions.assertNotNull(service); - Assert.assertSame(service, SPIServiceUtils.getTargetService(SPIServiceDef.class)); + Assertions.assertSame(service, SPIServiceUtils.getTargetService(SPIServiceDef.class)); } @Test public void testGetTargetService_special_null() { - Assert.assertNull(SPIServiceUtils.getTargetService(SPIServiceDef0.class, SPIServiceDef0Impl.class)); + Assertions.assertNull(SPIServiceUtils.getTargetService(SPIServiceDef0.class, SPIServiceDef0Impl.class)); } @Test public void testGetTargetService_special_notNull() { SPIServiceDef service = SPIServiceUtils.getTargetService(SPIServiceDef.class, SPIServiceDefImpl.class); - Assert.assertTrue(SPIServiceDefImpl.class.isInstance(service)); + Assertions.assertNotNull(service); } @Test - public void testSort(@Mocked Ordered o1, @Mocked Ordered o2) { + @EnabledOnJre(JRE.JAVA_8) + public void testSort() { + Ordered o1 = Mockito.mock(Ordered.class); + Ordered o2 = Mockito.mock(Ordered.class); Map map = new LinkedHashMap<>(); map.put("a", o1); map.put("b", o2); @@ -81,9 +87,9 @@ public void testSort(@Mocked Ordered o1, @Mocked Ordered o2) { } }; - Assert.assertThat(SPIServiceUtils.getSortedService(Ordered.class), Matchers.contains(o1, o2)); - Assert.assertThat(SPIServiceUtils.getAllService(Ordered.class), Matchers.contains(o1, o2)); - Assert.assertThat(SPIServiceUtils.getPriorityHighestService(Ordered.class), Matchers.is(o1)); + MatcherAssert.assertThat(SPIServiceUtils.getSortedService(Ordered.class), Matchers.contains(o1, o2)); + MatcherAssert.assertThat(SPIServiceUtils.getAllService(Ordered.class), Matchers.contains(o1, o2)); + MatcherAssert.assertThat(SPIServiceUtils.getPriorityHighestService(Ordered.class), Matchers.is(o1)); Map, List> cache = Deencapsulation.getField(SPIServiceUtils.class, "cache"); cache.clear(); @@ -91,7 +97,7 @@ public void testSort(@Mocked Ordered o1, @Mocked Ordered o2) { @Test public void getPriorityHighestService_null() { - Assert.assertNull(SPIServiceUtils.getPriorityHighestService(SPIServiceDef0.class)); + Assertions.assertNull(SPIServiceUtils.getPriorityHighestService(SPIServiceDef0.class)); } interface PriorityIntf { @@ -100,7 +106,7 @@ interface PriorityIntf { int getOrder(); } - public class PriorityImpl implements PriorityIntf { + public static class PriorityImpl implements PriorityIntf { private final String name; private final int order; @@ -123,13 +129,14 @@ public int getOrder() { @Override public String toString() { return "PriorityImpl{" + - "name='" + name + '\'' + - ", order=" + order + - '}'; + "name='" + name + '\'' + + ", order=" + order + + '}'; } } @Test + @EnabledOnJre(JRE.JAVA_8) public void getPriorityHighestServices() { Map instances = new LinkedHashMap<>(); instances.putIfAbsent("1", new PriorityImpl("n1", 0)); @@ -148,8 +155,8 @@ public void getPriorityHighestServices() { } }; - Assert.assertThat(SPIServiceUtils.getPriorityHighestServices(inst -> inst.getName(), PriorityIntf.class), - Matchers.containsInAnyOrder(instances.get("2"), instances.get("5"))); + MatcherAssert.assertThat(SPIServiceUtils.getPriorityHighestServices(PriorityIntf::getName, PriorityIntf.class), + Matchers.containsInAnyOrder(instances.get("2"), instances.get("5"))); Map, List> cache = Deencapsulation.getField(SPIServiceUtils.class, "cache"); cache.clear(); diff --git a/foundations/foundation-spi/src/test/resources/META-INF/services/org.apache.servicecomb.foundation.common.utils.SPIServiceDef b/foundations/foundation-spi/src/test/resources/META-INF/services/org.apache.servicecomb.foundation.common.utils.SPIServiceDef index eebf462d01b..7d8b6d492a4 100644 --- a/foundations/foundation-spi/src/test/resources/META-INF/services/org.apache.servicecomb.foundation.common.utils.SPIServiceDef +++ b/foundations/foundation-spi/src/test/resources/META-INF/services/org.apache.servicecomb.foundation.common.utils.SPIServiceDef @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.foundation.common.utils.SPIServiceDefImpl \ No newline at end of file +org.apache.servicecomb.foundation.common.utils.SPIServiceDefImpl diff --git a/foundations/foundation-ssl/pom.xml b/foundations/foundation-ssl/pom.xml index 13d2b187a99..3cf7cdcb485 100644 --- a/foundations/foundation-ssl/pom.xml +++ b/foundations/foundation-ssl/pom.xml @@ -21,19 +21,19 @@ org.apache.servicecomb foundations - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT foundation-ssl Java Chassis::Foundations::SSL - com.netflix.archaius - archaius-core + org.springframework + spring-context - commons-configuration - commons-configuration + org.apache.commons + commons-lang3 org.slf4j @@ -44,8 +44,13 @@ netty-tcnative-boringssl-static - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core test @@ -53,5 +58,10 @@ foundation-config test + + org.jmockit + jmockit + test + diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/CertificateUtil.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/CertificateUtil.java index 2091adba8c5..8fcf41af10a 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/CertificateUtil.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/CertificateUtil.java @@ -126,7 +126,7 @@ public static Set getCN(X509Certificate cert) { Object key = list.get(0); Object value = list.get(1); if (key instanceof Integer && value instanceof String) { - int intKey = ((Integer) key).intValue(); + int intKey = (Integer) key; String strValue = (String) value; if (intKey == SUBALTNAME_DNSNAME || intKey == SUBALTNAME_IPADDRESS) { names.add(strValue); diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtil.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtil.java index 525cf913e99..0666365a2f0 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtil.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtil.java @@ -87,8 +87,7 @@ public static CRL[] createCRL(String crlfile) { CertificateFactory cf = CertificateFactory.getInstance("X.509"); is = new FileInputStream(crlfile); Collection c = cf.generateCRLs(is); - CRL[] crls = (CRL[]) c.toArray(new CRL[c.size()]); - return crls; + return (CRL[]) c.toArray(new CRL[0]); } catch (CertificateException e) { throw new IllegalArgumentException("bad cert file."); } catch (FileNotFoundException e) { @@ -124,8 +123,7 @@ public static TrustManager[] createTrustManagers(final KeyStore keystore) { TrustManagerFactory tmfactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmfactory.init(keystore); - TrustManager[] trustmanagers = tmfactory.getTrustManagers(); - return trustmanagers; + return tmfactory.getTrustManagers(); } catch (Exception e) { throw new IllegalArgumentException("Bad trust store." + e.getMessage()); diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLCustom.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLCustom.java index bec5467927b..4c116649d84 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLCustom.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLCustom.java @@ -45,9 +45,9 @@ public String getFullPath(String filename) { public static SSLCustom createSSLCustom(String name) { try { if (name != null && !name.isEmpty()) { - return (SSLCustom) Class.forName(name).newInstance(); + return (SSLCustom) Class.forName(name).getDeclaredConstructor().newInstance(); } - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + } catch (ReflectiveOperationException e) { LOG.warn("init SSLCustom class failed, name is " + name); } return defaultSSLCustom(); diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLManager.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLManager.java index 82c28f724ce..b7136f7752e 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLManager.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLManager.java @@ -34,6 +34,9 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.X509ExtendedTrustManager; +import org.apache.commons.lang3.StringUtils; + + /** * 根据传递的SSLOption构造SSL上下文。请参考JSSE获取相关API的层次参考。 * @@ -168,7 +171,7 @@ public static SSLServerSocket createSSLServerSocket(SSLOption option, setClientAuth(option, socket); return socket; } catch (UnknownHostException e) { - throw new IllegalArgumentException("unkown host"); + throw new IllegalArgumentException("unknown host"); } catch (IOException e) { throw new IllegalArgumentException("unable create socket"); } @@ -182,7 +185,7 @@ public static SSLSocket createSSLSocket(SSLOption option, SSLCustom custom) { (SSLSocket) factory.createSocket(); socket.setEnabledProtocols(option.getProtocols().split(",")); String[] supported = socket.getSupportedCipherSuites(); - String[] enabled = option.getCiphers().split(","); + String[] enabled = option.getCiphers().split("\\s*,\\s*"); socket.setEnabledCipherSuites(getEnabledCiphers(supported, enabled)); return socket; } catch (UnknownHostException e) { @@ -214,10 +217,14 @@ private static String[] getEnabledCiphers(String[] supported, return r; } - public static String[] getEnabledCiphers(String enabledCiphers) { + public static String[] getEnabledCiphers(SSLOption sslOption) { SSLOption option = new SSLOption(); - option.setProtocols("TLSv1.2"); - option.setCiphers(enabledCiphers); + if (StringUtils.isNotEmpty(sslOption.getProtocols())) { + option.setProtocols(sslOption.getProtocols()); + } else { + option.setProtocols("TLSv1.2"); + } + option.setCiphers(sslOption.getCiphers()); SSLCustom custom = SSLCustom.defaultSSLCustom(); SSLSocket socket = createSSLSocket(option, custom); return socket.getEnabledCipherSuites(); diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOption.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOption.java index 648246636e7..19160bb3927 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOption.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOption.java @@ -24,12 +24,10 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; -import java.nio.charset.Charset; -import java.util.List; +import java.nio.charset.StandardCharsets; import java.util.Properties; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicPropertyFactory; +import org.springframework.core.env.Environment; /** * SSL配置选项。 @@ -49,7 +47,7 @@ public final class SSLOption { DEFAULT_OPTION.setCheckCNHost(false); DEFAULT_OPTION.setCheckCNWhite(false); DEFAULT_OPTION.setCheckCNWhiteFile("white.list"); - DEFAULT_OPTION.setAllowRenegociate(true); + DEFAULT_OPTION.setAllowRenegotiate(true); DEFAULT_OPTION.setStorePath("internal"); DEFAULT_OPTION.setTrustStore("trust.jks"); DEFAULT_OPTION.setTrustStoreType("JKS"); @@ -74,7 +72,7 @@ public final class SSLOption { private String checkCNWhiteFile; - private boolean allowRenegociate; + private boolean allowRenegotiate; private String clientAuth; @@ -128,8 +126,8 @@ public void setCheckCNWhiteFile(String checkCNWhiteFile) { this.checkCNWhiteFile = checkCNWhiteFile; } - public void setAllowRenegociate(boolean allowRenegociate) { - this.allowRenegociate = allowRenegociate; + public void setAllowRenegotiate(boolean allowRenegotiate) { + this.allowRenegotiate = allowRenegotiate; } public void setStorePath(String storePath) { @@ -188,8 +186,8 @@ public String getCheckCNWhiteFile() { return checkCNWhiteFile; } - public boolean isAllowRenegociate() { - return allowRenegociate; + public boolean isAllowRenegotiate() { + return allowRenegotiate; } public String getStorePath() { @@ -253,30 +251,11 @@ public static SSLOption build(InputStream inputStream) { return option; } - private static String listToString(Object[] lists) { - StringBuilder sb = new StringBuilder(); - sb.append(lists[0]); - for (int i = 1; i < lists.length; i++) { - sb.append(","); - sb.append(lists[i]); - } - return sb.toString(); - } - - public static String getStringProperty(ConcurrentCompositeConfiguration configSource, String defaultValue, + public static String getStringProperty(Environment environment, String defaultValue, String... keys) { String property = null; for (String key : keys) { - if (configSource != null) { - Object v = configSource.getProperty(key); - if (v instanceof List) { - property = listToString(((List) v).toArray()); - } else { - property = (String) configSource.getProperty(key); - } - } else { - property = DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); - } + property = environment.getProperty(key); if (property != null) { break; } @@ -289,17 +268,11 @@ public static String getStringProperty(ConcurrentCompositeConfiguration configSo } } - private static boolean getBooleanProperty(ConcurrentCompositeConfiguration configSource, boolean defaultValue, + private static boolean getBooleanProperty(Environment environment, boolean defaultValue, String... keys) { String property = null; for (String key : keys) { - if (configSource != null) { - if (configSource.getProperty(key) != null) { - return configSource.getBoolean(key); - } - } else { - property = DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); - } + property = environment.getProperty(key); if (property != null) { break; } @@ -312,83 +285,79 @@ private static boolean getBooleanProperty(ConcurrentCompositeConfiguration confi } } - public static SSLOption buildFromYaml(String tag, ConcurrentCompositeConfiguration configSource) { + public static SSLOption build(String tag, Environment environment) { SSLOption option = new SSLOption(); - option.engine = getStringProperty(configSource, + option.engine = getStringProperty(environment, DEFAULT_OPTION.getEngine(), "ssl." + tag + ".engine", "ssl.engine"); option.protocols = - getStringProperty(configSource, + getStringProperty(environment, DEFAULT_OPTION.getProtocols(), "ssl." + tag + ".protocols", "ssl.protocols"); option.ciphers = - getStringProperty(configSource, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers"); + getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers"); option.authPeer = - getBooleanProperty(configSource, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer"); + getBooleanProperty(environment, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer"); option.checkCNHost = - getBooleanProperty(configSource, + getBooleanProperty(environment, DEFAULT_OPTION.isCheckCNHost(), "ssl." + tag + ".checkCN.host", "ssl.checkCN.host"); option.checkCNWhite = - getBooleanProperty(configSource, + getBooleanProperty(environment, DEFAULT_OPTION.isCheckCNWhite(), "ssl." + tag + ".checkCN.white", "ssl.checkCN.white"); - option.checkCNWhiteFile = getStringProperty(configSource, + option.checkCNWhiteFile = getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".checkCN.white.file", "ssl.checkCN.white.file"); - option.allowRenegociate = getBooleanProperty(configSource, - DEFAULT_OPTION.isAllowRenegociate(), - "ssl." + tag + ".allowRenegociate", - "ssl.allowRenegociate"); + option.allowRenegotiate = getBooleanProperty(environment, + DEFAULT_OPTION.isAllowRenegotiate(), + "ssl." + tag + ".allowRenegotiate", + "ssl.allowRenegotiate"); option.storePath = - getStringProperty(configSource, + getStringProperty(environment, DEFAULT_OPTION.getStorePath(), "ssl." + tag + ".storePath", "ssl.storePath"); option.clientAuth = - getStringProperty(configSource, + getStringProperty(environment, DEFAULT_OPTION.getClientAuth(), "ssl." + tag + ".storePath", "ssl.clientAuth"); option.trustStore = - getStringProperty(configSource, + getStringProperty(environment, DEFAULT_OPTION.getTrustStore(), "ssl." + tag + ".trustStore", "ssl.trustStore"); - option.trustStoreType = getStringProperty(configSource, + option.trustStoreType = getStringProperty(environment, DEFAULT_OPTION.getTrustStoreType(), "ssl." + tag + ".trustStoreType", "ssl.trustStoreType"); - option.trustStoreValue = getStringProperty(configSource, + option.trustStoreValue = getStringProperty(environment, DEFAULT_OPTION.getTrustStoreValue(), "ssl." + tag + ".trustStoreValue", "ssl.trustStoreValue"); option.keyStore = - getStringProperty(configSource, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore"); + getStringProperty(environment, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore"); option.keyStoreType = - getStringProperty(configSource, + getStringProperty(environment, DEFAULT_OPTION.getKeyStoreType(), "ssl." + tag + ".keyStoreType", "ssl.keyStoreType"); - option.keyStoreValue = getStringProperty(configSource, + option.keyStoreValue = getStringProperty(environment, DEFAULT_OPTION.getKeyStoreValue(), "ssl." + tag + ".keyStoreValue", "ssl.keyStoreValue"); - option.crl = getStringProperty(configSource, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl"); + option.crl = getStringProperty(environment, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl"); option.sslCustomClass = - getStringProperty(configSource, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass"); + getStringProperty(environment, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass"); return option; } - public static SSLOption buildFromYaml(String tag) { - return buildFromYaml(tag, null); - } - private void fromProperty(Properties props) { this.protocols = propString(props, "ssl.protocols"); this.ciphers = propString(props, "ssl.ciphers"); @@ -396,7 +365,7 @@ private void fromProperty(Properties props) { this.checkCNHost = propBoolean(props, "ssl.checkCN.host"); this.checkCNWhite = propBoolean(props, "ssl.checkCN.white"); this.checkCNWhiteFile = propString(props, "ssl.checkCN.white.file"); - this.allowRenegociate = propBoolean(props, "ssl.allowRenegociate"); + this.allowRenegotiate = propBoolean(props, "ssl.allowRenegotiate"); this.storePath = propString(props, "ssl.storePath"); this.clientAuth = propString(props, "ssl.clientAuth", false); this.trustStore = propString(props, "ssl.trustStore"); @@ -434,7 +403,7 @@ private void load(InputStream inputStream) { Reader reader = null; try { reader = - new InputStreamReader(inputStream, Charset.forName("UTF-8")); + new InputStreamReader(inputStream, StandardCharsets.UTF_8); props.load(reader); fromProperty(props); } catch (IOException e) { @@ -459,7 +428,8 @@ private void load(InputStream inputStream) { } } - private void load(String path) { + // visible for testing + void load(String path) { try { load(new FileInputStream(path)); } catch (FileNotFoundException e) { diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOptionFactory.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOptionFactory.java index a6b55c8d96f..49cdb3ab15b 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOptionFactory.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLOptionFactory.java @@ -17,11 +17,11 @@ package org.apache.servicecomb.foundation.ssl; -import com.netflix.config.ConcurrentCompositeConfiguration; +import org.springframework.core.env.Environment; public interface SSLOptionFactory { - static SSLOptionFactory createSSLOptionFactory(String tag, ConcurrentCompositeConfiguration configSource) { - String name = SSLOption.getStringProperty(configSource, + static SSLOptionFactory createSSLOptionFactory(String tag, Environment environment) { + String name = SSLOption.getStringProperty(environment, null, "ssl." + tag + ".sslOptionFactory", "ssl.sslOptionFactory"); @@ -31,8 +31,8 @@ static SSLOptionFactory createSSLOptionFactory(String tag, ConcurrentCompositeCo static SSLOptionFactory createSSLOptionFactory(String className) { if (className != null && !className.isEmpty()) { try { - return (SSLOptionFactory) Class.forName(className).newInstance(); - } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { + return (SSLOptionFactory) Class.forName(className).getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { throw new IllegalStateException("Failed to create SSLOptionFactory.", e); } } diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLSocketFactoryExt.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLSocketFactoryExt.java index 79e2dc5011d..e0cc0f24d8d 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLSocketFactoryExt.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/SSLSocketFactoryExt.java @@ -30,11 +30,11 @@ * */ public class SSLSocketFactoryExt extends SSLSocketFactory { - private SSLSocketFactory sslSocketFactory; + private final SSLSocketFactory sslSocketFactory; - private String[] ciphers; + private final String[] ciphers; - private String[] protos; + private final String[] protos; public SSLSocketFactoryExt(SSLSocketFactory factory, String[] ciphers, String[] protos) { this.sslSocketFactory = factory; diff --git a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/TrustManagerExt.java b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/TrustManagerExt.java index 6137b1f68b3..597894571c5 100644 --- a/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/TrustManagerExt.java +++ b/foundations/foundation-ssl/src/main/java/org/apache/servicecomb/foundation/ssl/TrustManagerExt.java @@ -50,11 +50,11 @@ public class TrustManagerExt extends X509ExtendedTrustManager { private static final int WHITE_SIZE = 1024; - private X509ExtendedTrustManager trustManager; + private final X509ExtendedTrustManager trustManager; - private SSLOption option; + private final SSLOption option; - private SSLCustom custom; + private final SSLCustom custom; public TrustManagerExt(X509ExtendedTrustManager manager, SSLOption option, SSLCustom custom) { @@ -189,14 +189,14 @@ private void checkCNHost(X509Certificate[] chain, String ip) throws CertificateE } } } catch (SocketException e) { - throw new CertificateException("Get local adrress fail."); + throw new CertificateException("Get local address fail."); } } else if (cnValid(cns, ipTmp)) { return; } - LOG.error("CN does not match IP: e=" + cns.toString() + LOG.error("CN does not match IP: e=" + cns + ",t=" + ip); - throw new CertificateException("CN does not match IP: e=" + cns.toString() + throw new CertificateException("CN does not match IP: e=" + cns + ",t=" + ip); } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/CertificateUtilTest.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/CertificateUtilTest.java index 0285b8b3183..118df056a7c 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/CertificateUtilTest.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/CertificateUtilTest.java @@ -35,15 +35,16 @@ import javax.security.auth.x500.X500Principal; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; import mockit.Expectations; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class CertificateUtilTest { - class MyX509Certificate extends X509Certificate { + @SuppressWarnings("deprecation") + static class MyX509Certificate extends X509Certificate { private static final long serialVersionUID = -3585440601605666278L; public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { @@ -199,7 +200,7 @@ public void testGetCN(@Mocked X500Principal aX500Principal, @Mocked MyX509Certif MyX509Certificate xxmyX509Certificate = new MyX509Certificate(); Set strExpect = CertificateUtil.getCN(xxmyX509Certificate); - Assert.assertEquals(true, strExpect.contains("Test1234")); + Assertions.assertTrue(strExpect.contains("Test1234")); } @Test @@ -218,9 +219,9 @@ public void testGetCNException(@Mocked X500Principal aX500Principal, try { Set strExpect = CertificateUtil.getCN(xxmyX509Certificate); - Assert.assertEquals(strExpect.size(), 0); + Assertions.assertEquals(strExpect.size(), 0); } catch (IllegalArgumentException e) { - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } } @@ -255,7 +256,7 @@ public void testFindOwner(@Mocked X500Principal aX500Principal1, @Mocked X500Pri xxmyX509Certificate[1] = myX509Certificate2; X509Certificate aX509Certificate = CertificateUtil.findOwner(xxmyX509Certificate); - Assert.assertNull(aX509Certificate); + Assertions.assertNull(aX509Certificate); } @Test @@ -290,9 +291,9 @@ public void testFindRootCAException(@Mocked X500Principal aX500Principal1, @Mock try { X509Certificate aX509Certificate = CertificateUtil.findOwner(xxmyX509Certificate); - Assert.assertNull(aX509Certificate); + Assertions.assertNull(aX509Certificate); } catch (IllegalArgumentException e) { - Assert.assertEquals("bad certificate chain: no root CA.", e.getMessage()); + Assertions.assertEquals("bad certificate chain: no root CA.", e.getMessage()); } } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtilTest.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtilTest.java index a4531ac6ab1..54955139087 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtilTest.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/KeyStoreUtilTest.java @@ -26,12 +26,12 @@ import java.security.cert.CertificateFactory; import java.util.Collection; -import org.junit.Assert; import org.junit.Test; -import org.mockito.Mockito; +import org.junit.jupiter.api.Assertions; import mockit.Mock; import mockit.MockUp; +import org.mockito.Mockito; public class KeyStoreUtilTest { final String strFilePath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); @@ -45,7 +45,7 @@ public void testCreateKeyStoreException() { try { KeyStoreUtil.createKeyStore(storename, storetype, storevalue); } catch (IllegalArgumentException e) { - Assert.assertEquals("Bad key store or value.testType not found", e.getMessage()); + Assertions.assertEquals("Bad key store or value.testType not found", e.getMessage()); } } @@ -58,16 +58,14 @@ public void testCreateKeyStoreException2() { try { KeyStoreUtil.createKeyStore(storename, storetype, storevalue); } catch (IllegalArgumentException e) { - Assert.assertEquals("Bad key store or value.DerInputStream.getLength(): lengthTag=109, too big.", + Assertions.assertEquals("Bad key store or value.DerInputStream.getLength(): lengthTag=109, too big.", e.getMessage()); } } - @SuppressWarnings("unused") @Test public void testCreateKeyManagersException() { KeyStore keystore; - char[] keyvalue; String storename = strFilePath + "/ssl/server.p12"; String storetype = "PKCS12"; @@ -79,8 +77,9 @@ public void testCreateKeyManagersException() { try { KeyStoreUtil.createKeyManagers(keystore, storeKeyValue); } catch (IllegalArgumentException e) { - Assert.assertEquals("Bad key store.Get Key failed: null", - e.getMessage()); + Assertions.assertEquals("Bad key store.Get Key failed:" + + " Cannot read the array length because \"password\" is null", + e.getMessage()); } } @@ -91,11 +90,11 @@ public void testCreateCRL() { boolean validAssert = true; try { CRL[] crl = KeyStoreUtil.createCRL(crlfile); - Assert.assertNull(crl); + Assertions.assertNull(crl); } catch (Exception e) { validAssert = false; } - Assert.assertTrue(validAssert); + Assertions.assertTrue(validAssert); } @Test @@ -105,7 +104,7 @@ public void testCreateCRLException() { try { new MockUp() { @Mock - public final CertificateFactory getInstance(String type) throws CertificateException { + public CertificateFactory getInstance(String type) throws CertificateException { throw new CertificateException(); } }; @@ -114,7 +113,7 @@ public final CertificateFactory getInstance(String type) throws CertificateExcep } catch (Exception e) { validAssert = false; } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } @Test @@ -124,7 +123,7 @@ public void testExceptionFileNotFound() { try { new MockUp() { @Mock - public final CertificateFactory getInstance( + public CertificateFactory getInstance( String type) throws CertificateException, FileNotFoundException { throw new FileNotFoundException(); } @@ -132,9 +131,9 @@ public final CertificateFactory getInstance( KeyStoreUtil.createCRL(crlfile); } catch (Exception e) { validAssert = false; - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } @Test @@ -144,23 +143,23 @@ public void testExceptionCRLException() { try { new MockUp() { @Mock - public final CertificateFactory getInstance(String type) throws CertificateException, CRLException { + public CertificateFactory getInstance(String type) throws CertificateException, CRLException { throw new CRLException(); } }; KeyStoreUtil.createCRL(crlfile); } catch (Exception e) { validAssert = false; - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } private void mockGenerateCRLs() { new MockUp() { @SuppressWarnings("unchecked") @Mock - public final Collection generateCRLs(InputStream inStream) throws CRLException { + public Collection generateCRLs(InputStream inStream) throws CRLException { return Mockito.mock(Collection.class); } }; diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLManagerTest.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLManagerTest.java index fb2d3d4f2f1..71758fa3cff 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLManagerTest.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLManagerTest.java @@ -27,16 +27,14 @@ import java.security.NoSuchAlgorithmException; import java.util.Enumeration; -import javax.net.ssl.HandshakeCompletedEvent; -import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; -import org.junit.Assert; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import mockit.Expectations; import mockit.Mock; @@ -50,7 +48,7 @@ public class SSLManagerTest { public void testSSLManagerServerAndClient(final @Mocked NetworkInterface nif) throws Exception { final InetAddress ia = Inet4Address.getByName("10.57.65.225"); final Enumeration interfaces = new Enumeration() { - int count = 1; + final int count = 1; int cur = 0; @@ -70,7 +68,7 @@ public NetworkInterface nextElement() { }; final Enumeration ias = new Enumeration() { - int count = 1; + final int count = 1; int cur = 0; @@ -120,57 +118,50 @@ public char[] decode(char[] encrypted) { } }; final SSLServerSocket serverSocket = SSLManager.createSSLServerSocket(option, custom); - Assert.assertTrue(serverSocket.getNeedClientAuth()); + Assertions.assertTrue(serverSocket.getNeedClientAuth()); serverSocket.bind(new InetSocketAddress("127.0.0.1", 8886)); String[] protos = serverSocket.getEnabledCipherSuites(); String[] protosExpected = - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" + "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" .split(","); - Assert.assertArrayEquals(protos, protosExpected); + Assertions.assertArrayEquals(protos, protosExpected); String[] ciphers = serverSocket.getEnabledCipherSuites(); String[] ciphersExpected = - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" + "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" .split(","); - Assert.assertArrayEquals(ciphers, ciphersExpected); - Assert.assertEquals(serverSocket.getNeedClientAuth(), true); + Assertions.assertArrayEquals(ciphers, ciphersExpected); + Assertions.assertTrue(serverSocket.getNeedClientAuth()); SSLOption clientoption = SSLOption.build(DIR + "/client.ssl.properties"); SSLSocket clientsocket = SSLManager.createSSLSocket(clientoption, custom); String[] clientprotos = clientsocket.getEnabledCipherSuites(); String[] clientprotosExpected = - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" + "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" .split(","); - Assert.assertArrayEquals(clientprotos, clientprotosExpected); + Assertions.assertArrayEquals(clientprotos, clientprotosExpected); String[] clientciphers = clientsocket.getEnabledCipherSuites(); String[] clientciphersExpected = - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" + "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA" .split(","); - Assert.assertArrayEquals(clientciphers, clientciphersExpected); - Assert.assertEquals(clientsocket.getNeedClientAuth(), false); + Assertions.assertArrayEquals(clientciphers, clientciphersExpected); + Assertions.assertFalse(clientsocket.getNeedClientAuth()); boolean validAssert = true; try { clientsocket.connect(new InetSocketAddress("127.0.0.1", 8886)); - new Thread() { - public void run() { + new Thread(() -> { - try { - SSLSocket s = (SSLSocket) serverSocket.accept(); - s.addHandshakeCompletedListener(new HandshakeCompletedListener() { + try { + SSLSocket s = (SSLSocket) serverSocket.accept(); + s.addHandshakeCompletedListener(arg0 -> { - @Override - public void handshakeCompleted(HandshakeCompletedEvent arg0) { - - } - }); - s.getOutputStream().write(new byte[] {0, 1}); - } catch (IOException e) { - e.printStackTrace(); - // this should not happen, do a false assert - Assert.assertEquals(false, true); - } + }); + s.getOutputStream().write(new byte[] {0, 1}); + } catch (IOException e) { + e.printStackTrace(); + Assertions.fail("this should not happen"); } - }.start(); + }).start(); clientsocket.startHandshake(); clientsocket.close(); @@ -181,7 +172,7 @@ public void handshakeCompleted(HandshakeCompletedEvent arg0) { e.printStackTrace(); validAssert = false; } - Assert.assertTrue(validAssert); + Assertions.assertTrue(validAssert); } @Test @@ -201,8 +192,8 @@ public char[] decode(char[] encrypted) { SSLEngine aSSLEngine = SSLManager.createSSLEngine(option, custom); // if client mode may not decided at initialization. Different JDK is different, do not check it. - // Assert.assertEquals(false, aSSLEngine.getUseClientMode()); - Assert.assertTrue(aSSLEngine.getNeedClientAuth()); + // Assertions.assertEquals(false, aSSLEngine.getUseClientMode()); + Assertions.assertTrue(aSSLEngine.getNeedClientAuth()); } @Test @@ -224,9 +215,9 @@ public char[] decode(char[] encrypted) { SSLEngine aSSLEngine = SSLManager.createSSLEngine(option, custom); // if client mode may not decided at initialization. Different JDK is different, do not check it. - // Assert.assertEquals(false, aSSLEngine.getUseClientMode()); - Assert.assertFalse(aSSLEngine.getNeedClientAuth()); - Assert.assertFalse(aSSLEngine.getWantClientAuth()); + // Assertions.assertEquals(false, aSSLEngine.getUseClientMode()); + Assertions.assertFalse(aSSLEngine.getNeedClientAuth()); + Assertions.assertFalse(aSSLEngine.getWantClientAuth()); } @Test @@ -247,8 +238,8 @@ public char[] decode(char[] encrypted) { int port = 39093; String peerHost = "host1"; SSLEngine aSSLEngine = SSLManager.createSSLEngine(option, custom, peerHost, port); - Assert.assertNotNull(aSSLEngine); - Assert.assertEquals("host1", aSSLEngine.getPeerHost()); + Assertions.assertNotNull(aSSLEngine); + Assertions.assertEquals("host1", aSSLEngine.getPeerHost()); } @Test @@ -258,7 +249,7 @@ public void testCreateSSLContextResource() { SSLCustom custom = SSLCustom.defaultSSLCustom(); SSLContext context = SSLManager.createSSLContext(option, custom); - Assert.assertNotNull(context); + Assertions.assertNotNull(context); } @Test @@ -279,16 +270,16 @@ public char[] decode(char[] encrypted) { new MockUp() { @Mock - public final SSLContext getInstance(String type) throws NoSuchAlgorithmException { + public SSLContext getInstance(String type) throws NoSuchAlgorithmException { throw new NoSuchAlgorithmException(); } }; try { SSLManager.createSSLContext(option, custom); - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -310,16 +301,16 @@ public char[] decode(char[] encrypted) { new MockUp() { @Mock - public final SSLContext getInstance(String type) throws KeyManagementException { + public SSLContext getInstance(String type) throws KeyManagementException { throw new KeyManagementException(); } }; try { SSLManager.createSSLContext(option, custom); - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -341,7 +332,7 @@ public char[] decode(char[] encrypted) { new MockUp() { @Mock - public final SSLContext getInstance(String type) throws UnknownHostException { + public SSLContext getInstance(String type) throws UnknownHostException { throw new UnknownHostException(); } }; @@ -349,9 +340,9 @@ public final SSLContext getInstance(String type) throws UnknownHostException { try { SSLManager.createSSLServerSocket(option, custom); - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -373,16 +364,16 @@ public char[] decode(char[] encrypted) { new MockUp() { @Mock - public final SSLContext getInstance(String type) throws IOException { + public SSLContext getInstance(String type) throws IOException { throw new IOException(); } }; try { SSLManager.createSSLServerSocket(option, custom); - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -404,16 +395,16 @@ public char[] decode(char[] encrypted) { new MockUp() { @Mock - public final SSLContext getInstance(String type) throws UnknownHostException { + public SSLContext getInstance(String type) throws UnknownHostException { throw new UnknownHostException(); } }; try { SSLManager.createSSLSocket(option, custom); - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -435,16 +426,16 @@ public char[] decode(char[] encrypted) { new MockUp() { @Mock - public final SSLContext getInstance(String type) throws IOException { + public SSLContext getInstance(String type) throws IOException { throw new IOException(); } }; try { SSLManager.createSSLSocket(option, custom); - Assert.assertNotNull(null); + Assertions.assertNotNull(null); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -464,12 +455,15 @@ public char[] decode(char[] encrypted) { }; SSLSocketFactory aSSLSocketFactory = SSLManager.createSSLSocketFactory(option, custom); - Assert.assertNotNull(aSSLSocketFactory.getDefaultCipherSuites()[0]); + Assertions.assertNotNull(aSSLSocketFactory.getDefaultCipherSuites()[0]); } @Test public void testGetSupportedCiphers() { - String[] ciphers = SSLManager.getEnabledCiphers("TLS_RSA_WITH_AES_128_GCM_SHA256"); - Assert.assertEquals(ciphers[0], "TLS_RSA_WITH_AES_128_GCM_SHA256"); + SSLOption option = new SSLOption(); + option.setCiphers("TLS_RSA_WITH_AES_128_GCM_SHA256"); + option.setProtocols("TLSv1.2"); + String[] ciphers = SSLManager.getEnabledCiphers(option); + Assertions.assertEquals(ciphers[0], "TLS_RSA_WITH_AES_128_GCM_SHA256"); } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLOptionTest.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLOptionTest.java index 70726a12794..ae91fcbb697 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLOptionTest.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/SSLOptionTest.java @@ -17,8 +17,6 @@ package org.apache.servicecomb.foundation.ssl; -import static org.apache.servicecomb.config.archaius.sources.ConfigSourceMaker.yamlConfigSource; - import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -26,31 +24,38 @@ import java.net.URL; import java.util.Properties; -import org.apache.commons.configuration.SystemConfiguration; -import org.apache.servicecomb.config.ConfigUtil; -import org.junit.AfterClass; -import org.junit.Assert; +import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.ConcurrentMapConfiguration; -import com.netflix.config.ConfigurationManager; -import com.netflix.config.DynamicConfiguration; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.FixedDelayPollingScheduler; - -import mockit.Deencapsulation; import mockit.Mock; import mockit.MockUp; public class SSLOptionTest { private static final String DIR = Thread.currentThread().getContextClassLoader().getResource("").getPath(); - @AfterClass - public static void tearDown() throws Exception { - Deencapsulation.setField(ConfigurationManager.class, "instance", null); - Deencapsulation.setField(ConfigurationManager.class, "customConfigurationInstalled", false); - Deencapsulation.setField(DynamicPropertyFactory.class, "config", null); + Environment environment = Mockito.mock(Environment.class); + + @Before + public void setUp() throws Exception { + Mockito.when(environment.getProperty("ssl.protocols")).thenReturn("TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello"); + Mockito.when(environment.getProperty("ssl.ciphers")).thenReturn( + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"); + Mockito.when(environment.getProperty("ssl.authPeer")).thenReturn("true"); + Mockito.when(environment.getProperty("ssl.checkCN.host")).thenReturn("true"); + Mockito.when(environment.getProperty("ssl.checkCN.white")).thenReturn("true"); + Mockito.when(environment.getProperty("ssl.checkCN.white.file")).thenReturn("white.list"); + Mockito.when(environment.getProperty("ssl.allowRenegotiate")).thenReturn("false"); + Mockito.when(environment.getProperty("ssl.storePath")).thenReturn("internal"); + Mockito.when(environment.getProperty("ssl.trustStore")).thenReturn("trust.jks"); + Mockito.when(environment.getProperty("ssl.trustStoreType")).thenReturn("JKS"); + Mockito.when(environment.getProperty("ssl.trustStoreValue")).thenReturn("Changeme_123"); + Mockito.when(environment.getProperty("ssl.keyStore")).thenReturn("server.p12"); + Mockito.when(environment.getProperty("ssl.keyStoreType")).thenReturn("PKCS12"); + Mockito.when(environment.getProperty("ssl.keyStoreValue")).thenReturn("Changeme_123"); + Mockito.when(environment.getProperty("ssl.crl")).thenReturn("revoke.crl"); } @Test @@ -60,270 +65,245 @@ public void testSSLOption() { String protocols = option.getProtocols(); option.setProtocols(protocols); - Assert.assertEquals("TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello", protocols); + Assertions.assertEquals("TLSv1.3,TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello", protocols); String ciphers = option.getCiphers(); option.setCiphers(ciphers); - Assert.assertEquals( - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SH" + Assertions.assertEquals( + "TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SH" + "A,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA", ciphers); boolean authPeer = option.isAuthPeer(); option.setAuthPeer(authPeer); - Assert.assertEquals(true, authPeer); + Assertions.assertTrue(authPeer); boolean checkCNHost = option.isCheckCNHost(); option.setCheckCNHost(checkCNHost); - Assert.assertEquals(true, checkCNHost); + Assertions.assertTrue(checkCNHost); boolean checkCNWhite = option.isCheckCNWhite(); option.setCheckCNWhite(checkCNWhite); - Assert.assertEquals(true, checkCNWhite); + Assertions.assertTrue(checkCNWhite); String checkCNWhiteFile = option.getCheckCNWhiteFile(); option.setCheckCNWhiteFile(checkCNWhiteFile); - Assert.assertEquals("white.list", checkCNWhiteFile); + Assertions.assertEquals("white.list", checkCNWhiteFile); - boolean allowRenegociate = option.isAllowRenegociate(); - option.setAllowRenegociate(allowRenegociate); - Assert.assertEquals(false, allowRenegociate); + boolean allowRenegotiate = option.isAllowRenegotiate(); + option.setAllowRenegotiate(allowRenegotiate); + Assertions.assertFalse(allowRenegotiate); String storePath = option.getStorePath(); option.setStorePath(storePath); - Assert.assertEquals("internal", storePath); + Assertions.assertEquals("internal", storePath); String trustStore = option.getTrustStore(); option.setTrustStore(trustStore); - Assert.assertEquals("trust.jks", trustStore); + Assertions.assertEquals("trust.jks", trustStore); String trustStoreType = option.getTrustStoreType(); option.setTrustStoreType(trustStoreType); - Assert.assertEquals("JKS", trustStoreType); + Assertions.assertEquals("JKS", trustStoreType); String trustStoreValue = option.getTrustStoreValue(); option.setTrustStoreValue(trustStoreValue); - Assert.assertEquals("Changeme_123", trustStoreValue); + Assertions.assertEquals("Changeme_123", trustStoreValue); String keyStore = option.getKeyStore(); option.setKeyStore(keyStore); - Assert.assertEquals("server.p12", keyStore); + Assertions.assertEquals("server.p12", keyStore); String keyStoreType = option.getKeyStoreType(); option.setKeyStoreType(keyStoreType); - Assert.assertEquals("PKCS12", keyStoreType); + Assertions.assertEquals("PKCS12", keyStoreType); String keyStoreValue = option.getKeyStoreValue(); option.setKeyStoreValue(keyStoreValue); - Assert.assertEquals("Changeme_123", keyStoreValue); + Assertions.assertEquals("Changeme_123", keyStoreValue); String crl = option.getCrl(); option.setCrl(crl); - Assert.assertEquals("revoke.crl", crl); + Assertions.assertEquals("revoke.crl", crl); } @Test public void testSSLOptionYaml() { - // configuration from yaml files: default microservice.yaml - DynamicConfiguration configFromYamlFile = - new DynamicConfiguration(yamlConfigSource(), new FixedDelayPollingScheduler()); - // configuration from system properties - ConcurrentMapConfiguration configFromSystemProperties = - new ConcurrentMapConfiguration(new SystemConfiguration()); - - // create a hierarchy of configuration that makes - // 1) dynamic configuration source override system properties - ConcurrentCompositeConfiguration finalConfig = new ConcurrentCompositeConfiguration(); - finalConfig.addConfiguration(configFromSystemProperties, "systemEnvConfig"); - finalConfig.addConfiguration(configFromYamlFile, "configFromYamlFile"); - ConfigurationManager.install(finalConfig); - - SSLOption option = SSLOption.buildFromYaml("server"); + Mockito.when(environment.getProperty("ssl.server.sslCustomClass")).thenReturn("wwrong"); + SSLOption option = SSLOption.build("server", environment); String protocols = option.getProtocols(); option.setProtocols(protocols); - Assert.assertEquals("TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello", protocols); + Assertions.assertEquals("TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello", protocols); String ciphers = option.getCiphers(); option.setCiphers(ciphers); - Assert.assertEquals( - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SH" - + - "A,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA", + Assertions.assertEquals("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", ciphers); boolean authPeer = option.isAuthPeer(); option.setAuthPeer(authPeer); - Assert.assertEquals(true, authPeer); + Assertions.assertTrue(authPeer); boolean checkCNHost = option.isCheckCNHost(); option.setCheckCNHost(checkCNHost); - Assert.assertEquals(true, checkCNHost); + Assertions.assertTrue(checkCNHost); boolean checkCNWhite = option.isCheckCNWhite(); option.setCheckCNWhite(checkCNWhite); - Assert.assertEquals(true, checkCNWhite); + Assertions.assertTrue(checkCNWhite); String checkCNWhiteFile = option.getCheckCNWhiteFile(); option.setCheckCNWhiteFile(checkCNWhiteFile); - Assert.assertEquals("white.list", checkCNWhiteFile); + Assertions.assertEquals("white.list", checkCNWhiteFile); - boolean allowRenegociate = option.isAllowRenegociate(); - option.setAllowRenegociate(allowRenegociate); - Assert.assertEquals(false, allowRenegociate); + boolean allowRenegotiate = option.isAllowRenegotiate(); + option.setAllowRenegotiate(allowRenegotiate); + Assertions.assertFalse(allowRenegotiate); String storePath = option.getStorePath(); option.setStorePath(storePath); - Assert.assertEquals("internal", storePath); + Assertions.assertEquals("internal", storePath); String trustStore = option.getTrustStore(); option.setTrustStore(trustStore); - Assert.assertEquals("trust.jks", trustStore); + Assertions.assertEquals("trust.jks", trustStore); String trustStoreType = option.getTrustStoreType(); option.setTrustStoreType(trustStoreType); - Assert.assertEquals("JKS", trustStoreType); + Assertions.assertEquals("JKS", trustStoreType); String trustStoreValue = option.getTrustStoreValue(); option.setTrustStoreValue(trustStoreValue); - Assert.assertEquals("Changeme_123", trustStoreValue); + Assertions.assertEquals("Changeme_123", trustStoreValue); String keyStore = option.getKeyStore(); option.setKeyStore(keyStore); - Assert.assertEquals("server.p12", keyStore); + Assertions.assertEquals("server.p12", keyStore); String keyStoreType = option.getKeyStoreType(); option.setKeyStoreType(keyStoreType); - Assert.assertEquals("PKCS12", keyStoreType); + Assertions.assertEquals("PKCS12", keyStoreType); String keyStoreValue = option.getKeyStoreValue(); option.setKeyStoreValue(keyStoreValue); - Assert.assertEquals("Changeme_123", keyStoreValue); + Assertions.assertEquals("Changeme_123", keyStoreValue); String crl = option.getCrl(); option.setCrl(crl); - Assert.assertEquals("revoke.crl", crl); + Assertions.assertEquals("revoke.crl", crl); option.setSslCustomClass("123"); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); - Assert.assertArrayEquals(custom.decode("123".toCharArray()), "123".toCharArray()); + Assertions.assertArrayEquals(custom.decode("123".toCharArray()), "123".toCharArray()); } @Test public void testSSLOptionYamlOption2() throws Exception { - System.setProperty("ssl.protocols", "TLSv1.2"); - ConcurrentCompositeConfiguration finalConfig = ConfigUtil.createLocalConfig(); + Mockito.when(environment.getProperty("ssl.protocols")).thenReturn("TLSv1.2"); - SSLOption option = SSLOption.buildFromYaml("server", finalConfig); + SSLOption option = SSLOption.build("server", environment); String protocols = option.getProtocols(); option.setProtocols(protocols); - Assert.assertEquals("TLSv1.2", protocols); + Assertions.assertEquals("TLSv1.2", protocols); System.clearProperty("ssl.protocols"); } @Test - public void testSSLOptionYamlOptionWithProperyFalse() throws Exception { - System.setProperty("ssl.authPeer", "false"); - ConcurrentCompositeConfiguration finalConfig = ConfigUtil.createLocalConfig(); + public void testSSLOptionYamlOptionWithPropertyFalse() throws Exception { + Mockito.when(environment.getProperty("ssl.authPeer")).thenReturn("false"); - SSLOption option = SSLOption.buildFromYaml("server", finalConfig); + SSLOption option = SSLOption.build("server", environment); boolean authPeer = option.isAuthPeer(); option.setAuthPeer(authPeer); - Assert.assertEquals(false, authPeer); + Assertions.assertFalse(authPeer); System.getProperties().remove("ssl.authPeer"); } @Test - public void testSSLOptionYamlOptionWithProperyTrue() throws Exception { - System.setProperty("ssl.authPeer", "true"); - ConcurrentCompositeConfiguration finalConfig = ConfigUtil.createLocalConfig(); - - SSLOption option = SSLOption.buildFromYaml("server", finalConfig); + public void testSSLOptionYamlOptionWithPropertyTrue() throws Exception { + SSLOption option = SSLOption.build("server", environment); boolean authPeer = option.isAuthPeer(); option.setAuthPeer(authPeer); - Assert.assertEquals(true, authPeer); + Assertions.assertTrue(authPeer); System.getProperties().remove("ssl.authPeer"); } @Test public void testSSLOptionYamlOption() throws Exception { - ConcurrentCompositeConfiguration finalConfig = ConfigUtil.createLocalConfig(); - - SSLOption option = SSLOption.buildFromYaml("server", finalConfig); + SSLOption option = SSLOption.build("server", environment); String protocols = option.getProtocols(); option.setProtocols(protocols); - Assert.assertEquals("TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello", protocols); + Assertions.assertEquals("TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello", protocols); String ciphers = option.getCiphers(); option.setCiphers(ciphers); - Assert.assertEquals( - "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SH" - + - "A,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA", + Assertions.assertEquals( + "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", ciphers); boolean authPeer = option.isAuthPeer(); option.setAuthPeer(authPeer); - Assert.assertEquals(true, authPeer); + Assertions.assertTrue(authPeer); boolean checkCNHost = option.isCheckCNHost(); option.setCheckCNHost(checkCNHost); - Assert.assertEquals(true, checkCNHost); + Assertions.assertTrue(checkCNHost); boolean checkCNWhite = option.isCheckCNWhite(); option.setCheckCNWhite(checkCNWhite); - Assert.assertEquals(true, checkCNWhite); + Assertions.assertTrue(checkCNWhite); String checkCNWhiteFile = option.getCheckCNWhiteFile(); option.setCheckCNWhiteFile(checkCNWhiteFile); - Assert.assertEquals("white.list", checkCNWhiteFile); + Assertions.assertEquals("white.list", checkCNWhiteFile); - boolean allowRenegociate = option.isAllowRenegociate(); - option.setAllowRenegociate(allowRenegociate); - Assert.assertEquals(false, allowRenegociate); + boolean allowRenegotiate = option.isAllowRenegotiate(); + option.setAllowRenegotiate(allowRenegotiate); + Assertions.assertFalse(allowRenegotiate); String storePath = option.getStorePath(); option.setStorePath(storePath); - Assert.assertEquals("internal", storePath); + Assertions.assertEquals("internal", storePath); String trustStore = option.getTrustStore(); option.setTrustStore(trustStore); - Assert.assertEquals("trust.jks", trustStore); + Assertions.assertEquals("trust.jks", trustStore); String trustStoreType = option.getTrustStoreType(); option.setTrustStoreType(trustStoreType); - Assert.assertEquals("JKS", trustStoreType); + Assertions.assertEquals("JKS", trustStoreType); String trustStoreValue = option.getTrustStoreValue(); option.setTrustStoreValue(trustStoreValue); - Assert.assertEquals("Changeme_123", trustStoreValue); + Assertions.assertEquals("Changeme_123", trustStoreValue); String keyStore = option.getKeyStore(); option.setKeyStore(keyStore); - Assert.assertEquals("server.p12", keyStore); + Assertions.assertEquals("server.p12", keyStore); String keyStoreType = option.getKeyStoreType(); option.setKeyStoreType(keyStoreType); - Assert.assertEquals("PKCS12", keyStoreType); + Assertions.assertEquals("PKCS12", keyStoreType); String keyStoreValue = option.getKeyStoreValue(); option.setKeyStoreValue(keyStoreValue); - Assert.assertEquals("Changeme_123", keyStoreValue); + Assertions.assertEquals("Changeme_123", keyStoreValue); String crl = option.getCrl(); option.setCrl(crl); - Assert.assertEquals("revoke.crl", crl); + Assertions.assertEquals("revoke.crl", crl); option.setSslCustomClass("123"); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); - Assert.assertArrayEquals(custom.decode("123".toCharArray()), "123".toCharArray()); + Assertions.assertArrayEquals(custom.decode("123".toCharArray()), "123".toCharArray()); } @SuppressWarnings("unused") @@ -332,7 +312,7 @@ public void testSSLOptionNull() { try { SSLOption option = SSLOption.build(DIR + "/servers.ssl.properties"); } catch (IllegalArgumentException e) { - Assert.assertEquals("Bad file name.", e.getMessage()); + Assertions.assertEquals("Bad file name.", e.getMessage()); } } @@ -347,9 +327,9 @@ public String getCanonicalPath() throws IOException { try { SSLOption option = SSLOption.build(DIR + "/server.ssl.properties"); - Assert.assertNotNull(option); + Assertions.assertNotNull(option); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -364,12 +344,12 @@ public synchronized void load(Reader reader) throws IOException { boolean validAssert = true; try { SSLOption option = SSLOption.build(DIR + "/server.ssl.properties"); - Assert.assertEquals("revoke.crl", option.getCrl()); + Assertions.assertEquals("revoke.crl", option.getCrl()); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); validAssert = false; } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } @Test @@ -380,9 +360,9 @@ public void testBuildInputStream() { InputStream inputStream = url.openStream(); SSLOption option = SSLOption.build(inputStream); - Assert.assertNotNull(option); + Assertions.assertNotNull(option); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); } } @@ -391,11 +371,11 @@ public void testPrivateMethodException() { SSLOption option = new SSLOption(); boolean validAssert = true; try { - Deencapsulation.invoke(option, "load", "test"); + option.load("test"); } catch (Exception e) { - Assert.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); + Assertions.assertEquals("java.lang.IllegalArgumentException", e.getClass().getName()); validAssert = false; } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLOptionFactory.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLOptionFactory.java index c18c4dad3ce..1d3b1b8b229 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLOptionFactory.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLOptionFactory.java @@ -17,13 +17,10 @@ package org.apache.servicecomb.foundation.ssl; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.netflix.config.ConcurrentCompositeConfiguration; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import mockit.Expectations; import mockit.Mock; @@ -31,39 +28,38 @@ import mockit.Mocked; public class TestSSLOptionFactory { - @Rule - public ExpectedException expectedException = ExpectedException.none(); + Environment environment = Mockito.mock(Environment.class); @Test public void testSSLOptionFactory() { - SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory("cc", null); - Assert.assertEquals(factory, null); + SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory("cc", environment); + Assertions.assertNull(factory); } @Test public void testSSLOptionFactoryWrong(@Mocked SSLOption option) { new Expectations() { { - SSLOption.getStringProperty((ConcurrentCompositeConfiguration) any, anyString, (String[]) any); + SSLOption.getStringProperty((Environment) any, anyString, (String[]) any); result = "wrong"; } }; - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage(Matchers.is("Failed to create SSLOptionFactory.")); - SSLOptionFactory.createSSLOptionFactory("cc", null); + IllegalStateException exception = Assertions.assertThrows(IllegalStateException.class, + () -> SSLOptionFactory.createSSLOptionFactory("cc", null)); + Assertions.assertEquals("Failed to create SSLOptionFactory.", exception.getMessage()); } @Test - public void testSSLOptionFactoryCorrent() { + public void testSSLOptionFactoryCurrent() { new MockUp() { @Mock - public String getStringProperty(ConcurrentCompositeConfiguration configSource, String defaultValue, + public String getStringProperty(Environment environment, String defaultValue, String... keys) { return "org.apache.servicecomb.foundation.ssl.MyOptionFactory"; } }; - SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory("cc", null); - Assert.assertEquals(factory.createSSLOption().getProtocols(), "TLSv1.2"); + SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory("cc", environment); + Assertions.assertEquals(factory.createSSLOption().getProtocols(), "TLSv1.2"); } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLSocketFactoryExt.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLSocketFactoryExt.java index 001600bd004..7c1e8c87724 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLSocketFactoryExt.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestSSLSocketFactoryExt.java @@ -20,9 +20,9 @@ import javax.net.ssl.SSLSocketFactory; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; public class TestSSLSocketFactoryExt { @@ -51,6 +51,6 @@ public void testCreateSocketException() { } catch (Exception e) { validAssert = false; } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestTrustAllManager.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestTrustAllManager.java index 8690a79abf6..7a5256925c9 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestTrustAllManager.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TestTrustAllManager.java @@ -17,14 +17,14 @@ package org.apache.servicecomb.foundation.ssl; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + import java.net.Socket; import java.security.cert.X509Certificate; import javax.net.ssl.SSLEngine; -import org.junit.Assert; -import org.junit.Test; - public class TestTrustAllManager { @Test public void testTrustAllManager() throws Exception { @@ -45,6 +45,6 @@ public void testTrustAllManager() throws Exception { manager.checkServerTrusted((X509Certificate[]) null, (String) null, (SSLEngine) null); - Assert.assertEquals(manager.getAcceptedIssuers() == null, true); + Assertions.assertNull(manager.getAcceptedIssuers()); } } diff --git a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TrustManagerExtTest.java b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TrustManagerExtTest.java index 22f8cb74051..d9f65d56aae 100644 --- a/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TrustManagerExtTest.java +++ b/foundations/foundation-ssl/src/test/java/org/apache/servicecomb/foundation/ssl/TrustManagerExtTest.java @@ -41,7 +41,6 @@ import javax.net.ssl.X509ExtendedTrustManager; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -49,11 +48,12 @@ import mockit.Mock; import mockit.MockUp; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TrustManagerExtTest { final String strFilePath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); - class MyX509ExtendedTrustManager extends X509ExtendedTrustManager { + static class MyX509ExtendedTrustManager extends X509ExtendedTrustManager { public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate, String paramString, Socket paramSocket) throws CertificateException { } @@ -83,7 +83,8 @@ public X509Certificate[] getAcceptedIssuers() { } } - class MyX509Certificate extends X509Certificate { + @SuppressWarnings("deprecation") + static class MyX509Certificate extends X509Certificate { private static final long serialVersionUID = -3585440601605666276L; public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { @@ -260,8 +261,8 @@ public void testConstructor() { TrustManagerExt trustManagerExt = new TrustManagerExt((X509ExtendedTrustManager) trustManager[0], option, custom); - Assert.assertEquals(3, trustManagerExt.getAcceptedIssuers()[0].getVersion()); - Assert.assertNotNull(trustManagerExt); + Assertions.assertEquals(3, trustManagerExt.getAcceptedIssuers()[0].getVersion()); + Assertions.assertNotNull(trustManagerExt); } @Test @@ -269,9 +270,9 @@ public void testConstructorWithParam() { MyX509Certificate myX509Certificate1 = new MyX509Certificate(); MyX509Certificate myX509Certificate2 = new MyX509Certificate(); - MyX509Certificate[] MyX509CertificateArray = new MyX509Certificate[2]; - MyX509CertificateArray[0] = myX509Certificate1; - MyX509CertificateArray[1] = myX509Certificate2; + MyX509Certificate[] myX509CertificateArray = new MyX509Certificate[2]; + myX509CertificateArray[0] = myX509Certificate1; + myX509CertificateArray[1] = myX509Certificate2; new Expectations(CertificateUtil.class) { { @@ -286,16 +287,16 @@ public void testConstructorWithParam() { MyX509ExtendedTrustManager myX509ExtendedTrustManager = new MyX509ExtendedTrustManager(); TrustManagerExt trustManagerExt = new TrustManagerExt(myX509ExtendedTrustManager, option, custom); - Assert.assertNotNull(trustManagerExt); + Assertions.assertNotNull(trustManagerExt); boolean validAssert = true; try { - trustManagerExt.checkClientTrusted(MyX509CertificateArray, "pks"); - trustManagerExt.checkServerTrusted(MyX509CertificateArray, "pks"); + trustManagerExt.checkClientTrusted(myX509CertificateArray, "pks"); + trustManagerExt.checkServerTrusted(myX509CertificateArray, "pks"); trustManagerExt.getAcceptedIssuers(); } catch (Exception e) { validAssert = false; } - Assert.assertTrue(validAssert); + Assertions.assertTrue(validAssert); } @Test @@ -303,9 +304,9 @@ public void testCheckClientTrusted(@Mocked CertificateUtil certificateUtil) { MyX509Certificate myX509Certificate1 = new MyX509Certificate(); MyX509Certificate myX509Certificate2 = new MyX509Certificate(); - MyX509Certificate[] MyX509CertificateArray = new MyX509Certificate[2]; - MyX509CertificateArray[0] = myX509Certificate1; - MyX509CertificateArray[1] = myX509Certificate2; + MyX509Certificate[] myX509CertificateArray = new MyX509Certificate[2]; + myX509CertificateArray[0] = myX509Certificate1; + myX509CertificateArray[1] = myX509Certificate2; new Expectations() { { @@ -324,14 +325,14 @@ public void testCheckClientTrusted(@Mocked CertificateUtil certificateUtil) { SSLEngine sslengine = null; boolean validAssert = true; try { - trustManagerExt.checkClientTrusted(MyX509CertificateArray, "pks", socket); - trustManagerExt.checkClientTrusted(MyX509CertificateArray, "pks", sslengine); - trustManagerExt.checkServerTrusted(MyX509CertificateArray, "pks", socket); - trustManagerExt.checkServerTrusted(MyX509CertificateArray, "pks", sslengine); + trustManagerExt.checkClientTrusted(myX509CertificateArray, "pks", socket); + trustManagerExt.checkClientTrusted(myX509CertificateArray, "pks", sslengine); + trustManagerExt.checkServerTrusted(myX509CertificateArray, "pks", socket); + trustManagerExt.checkServerTrusted(myX509CertificateArray, "pks", sslengine); } catch (Exception e) { validAssert = false; } - Assert.assertTrue(validAssert); + Assertions.assertTrue(validAssert); } @Test @@ -339,9 +340,9 @@ public void testCatchException(@Mocked CertificateUtil certificateUtil) { MyX509Certificate myX509Certificate1 = new MyX509Certificate(); MyX509Certificate myX509Certificate2 = new MyX509Certificate(); - MyX509Certificate[] MyX509CertificateArray = new MyX509Certificate[2]; - MyX509CertificateArray[0] = myX509Certificate1; - MyX509CertificateArray[1] = myX509Certificate2; + MyX509Certificate[] myX509CertificateArray = new MyX509Certificate[2]; + myX509CertificateArray[0] = myX509Certificate1; + myX509CertificateArray[1] = myX509Certificate2; new Expectations() { { @@ -357,22 +358,22 @@ public void testCatchException(@Mocked CertificateUtil certificateUtil) { TrustManagerExt trustManagerExt = new TrustManagerExt(myX509ExtendedTrustManager, option, custom); boolean validAssert = true; try { - trustManagerExt.checkClientTrusted(MyX509CertificateArray, "pks"); + trustManagerExt.checkClientTrusted(myX509CertificateArray, "pks"); } catch (CertificateException e) { - Assert.assertEquals("CN does not match IP: e=[10.67.147.114],t=null", e.getMessage()); + Assertions.assertEquals("CN does not match IP: e=[10.67.147.114],t=null", e.getMessage()); validAssert = false; } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } @Test - public void testCheckClientTrustedExecption(@Mocked CertificateUtil certificateUtil) { + public void testCheckClientTrustedException(@Mocked CertificateUtil certificateUtil) { MyX509Certificate myX509Certificate1 = new MyX509Certificate(); MyX509Certificate myX509Certificate2 = new MyX509Certificate(); - MyX509Certificate[] MyX509CertificateArray = new MyX509Certificate[2]; - MyX509CertificateArray[0] = myX509Certificate1; - MyX509CertificateArray[1] = myX509Certificate2; + MyX509Certificate[] myX509CertificateArray = new MyX509Certificate[2]; + myX509CertificateArray[0] = myX509Certificate1; + myX509CertificateArray[1] = myX509Certificate2; new Expectations() { { @@ -392,20 +393,20 @@ public void testCheckClientTrustedExecption(@Mocked CertificateUtil certificateU new MockUp() { @Mock - public int read(char cbuf[]) throws IOException { + public int read(char[] cbuf) throws IOException { throw new IOException(); } }; boolean validAssert = true; try { - trustManagerExt.checkClientTrusted(MyX509CertificateArray, "pks", socket); - trustManagerExt.checkClientTrusted(MyX509CertificateArray, "pks", sslengine); - trustManagerExt.checkServerTrusted(MyX509CertificateArray, "pks", socket); - trustManagerExt.checkServerTrusted(MyX509CertificateArray, "pks", sslengine); + trustManagerExt.checkClientTrusted(myX509CertificateArray, "pks", socket); + trustManagerExt.checkClientTrusted(myX509CertificateArray, "pks", sslengine); + trustManagerExt.checkServerTrusted(myX509CertificateArray, "pks", socket); + trustManagerExt.checkServerTrusted(myX509CertificateArray, "pks", sslengine); } catch (Exception e) { - Assert.assertEquals("java.security.cert.CertificateException", e.getClass().getName()); + Assertions.assertEquals("java.security.cert.CertificateException", e.getClass().getName()); validAssert = false; } - Assert.assertFalse(validAssert); + Assertions.assertFalse(validAssert); } } diff --git a/foundations/foundation-ssl/src/test/resources/client.ssl.properties b/foundations/foundation-ssl/src/test/resources/client.ssl.properties index 82209e75c81..87808468196 100644 --- a/foundations/foundation-ssl/src/test/resources/client.ssl.properties +++ b/foundations/foundation-ssl/src/test/resources/client.ssl.properties @@ -16,13 +16,14 @@ # #########SSL options -ssl.protocols=TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello -ssl.ciphers=TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA +ssl.protocols=TLSv1.3,TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello +## test with extra blank +ssl.ciphers=TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA ssl.authPeer=true ssl.checkCN.host=false ssl.checkCN.white=true ssl.checkCN.white.file=white.list -ssl.allowRenegociate=false +ssl.allowRenegotiate=false #########certificates config ssl.storePath=internal diff --git a/foundations/foundation-ssl/src/test/resources/log4j.properties b/foundations/foundation-ssl/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/foundations/foundation-ssl/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/foundations/foundation-ssl/src/test/resources/microservice.yaml b/foundations/foundation-ssl/src/test/resources/microservice.yaml index 41ca3326e51..482c8e48ea7 100644 --- a/foundations/foundation-ssl/src/test/resources/microservice.yaml +++ b/foundations/foundation-ssl/src/test/resources/microservice.yaml @@ -23,7 +23,7 @@ ssl: checkCN.host: true checkCN.white: true checkCN.white.file: white.list - allowRenegociate: false + allowRenegotiate: false storePath: internal trustStore: trust.jks trustStoreType: JKS diff --git a/foundations/foundation-ssl/src/test/resources/server.ssl.properties b/foundations/foundation-ssl/src/test/resources/server.ssl.properties index 7adfb36bd4f..d2a8180ab51 100644 --- a/foundations/foundation-ssl/src/test/resources/server.ssl.properties +++ b/foundations/foundation-ssl/src/test/resources/server.ssl.properties @@ -16,13 +16,13 @@ # #########SSL options -ssl.protocols=TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello -ssl.ciphers=TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA +ssl.protocols=TLSv1.3,TLSv1.2,TLSv1.1,TLSv1,SSLv2Hello +ssl.ciphers=TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA ssl.authPeer=true ssl.checkCN.host=true ssl.checkCN.white=true ssl.checkCN.white.file=white.list -ssl.allowRenegociate=false +ssl.allowRenegotiate=false #########certificates config ssl.storePath=internal diff --git a/foundations/foundation-ssl/src/test/resources/server.ssl.resource.properties b/foundations/foundation-ssl/src/test/resources/server.ssl.resource.properties index f1327eeca56..01f7380ba71 100644 --- a/foundations/foundation-ssl/src/test/resources/server.ssl.resource.properties +++ b/foundations/foundation-ssl/src/test/resources/server.ssl.resource.properties @@ -22,7 +22,7 @@ ssl.authPeer=true ssl.checkCN.host=true ssl.checkCN.white=true ssl.checkCN.white.file=white.list -ssl.allowRenegociate=false +ssl.allowRenegotiate=false #########certificates config ssl.storePath=internal diff --git a/foundations/foundation-ssl/src/test/resources/ssl/server.cer b/foundations/foundation-ssl/src/test/resources/ssl/server.cer index 79a62b21dea..fa0810bf80f 100644 --- a/foundations/foundation-ssl/src/test/resources/ssl/server.cer +++ b/foundations/foundation-ssl/src/test/resources/ssl/server.cer @@ -50,18 +50,18 @@ Certificate: 53:08:33 Exponent: 65537 (0x10001) X509v3 extensions: - X509v3 Basic Constraints: + X509v3 Basic Constraints: CA:FALSE X509v3 Key Usage: critical Digital Signature, Non Repudiation, Key Encipherment - X509v3 Subject Key Identifier: + X509v3 Subject Key Identifier: 27:15:69:5B:D5:13:60:C4:5C:62:54:75:55:A1:1D:4D:57:27:03:1F - X509v3 Authority Key Identifier: + X509v3 Authority Key Identifier: keyid:D5:4E:82:08:70:16:63:3D:DF:87:25:0B:7D:2E:EB:83:21:6A:BA:5B DirName:/C=CN/ST=GuangDong/L=ShenZhen/O=Huawei Technologies Co., Ltd/OU=OSS & Service Tools Dept/CN=OSS3.0 CA serial:7D:FD:C5:D8:70:DA:6E:0F:00:00:00:00:00:00:00:00 - X509v3 Subject Alternative Name: + X509v3 Subject Alternative Name: DNS:10.57.65.225, IP Address:10.57.65.225 Signature Algorithm: sha256WithRSAEncryption 38:1b:40:c9:3c:7f:63:a0:2d:64:59:2b:d9:4a:4b:db:c4:70: diff --git a/foundations/foundation-ssl/src/test/resources/ssl/trust.cer b/foundations/foundation-ssl/src/test/resources/ssl/trust.cer index a41bd779130..f010f4bf058 100644 --- a/foundations/foundation-ssl/src/test/resources/ssl/trust.cer +++ b/foundations/foundation-ssl/src/test/resources/ssl/trust.cer @@ -50,18 +50,18 @@ Certificate: 05:60:4b Exponent: 65537 (0x10001) X509v3 extensions: - X509v3 Basic Constraints: + X509v3 Basic Constraints: CA:TRUE X509v3 Key Usage: critical Certificate Sign, CRL Sign - X509v3 Subject Key Identifier: + X509v3 Subject Key Identifier: D5:4E:82:08:70:16:63:3D:DF:87:25:0B:7D:2E:EB:83:21:6A:BA:5B - X509v3 Authority Key Identifier: + X509v3 Authority Key Identifier: keyid:D5:4E:82:08:70:16:63:3D:DF:87:25:0B:7D:2E:EB:83:21:6A:BA:5B DirName:/C=CN/ST=GuangDong/L=ShenZhen/O=Huawei Technologies Co., Ltd/OU=OSS & Service Tools Dept/CN=OSS3.0 CA serial:7D:FD:C5:D8:70:DA:6E:0F:00:00:00:00:00:00:00:00 - X509v3 Subject Alternative Name: + X509v3 Subject Alternative Name: email:oss3ca@huawei.com Signature Algorithm: sha256WithRSAEncryption 8a:52:5f:99:d0:7b:a0:8c:2d:e8:6c:ff:7a:bc:89:64:03:d4: diff --git a/foundations/foundation-ssl/src/test/resources/ssl/white.list b/foundations/foundation-ssl/src/test/resources/ssl/white.list index fe1d44d8e85..5719754cff9 100644 --- a/foundations/foundation-ssl/src/test/resources/ssl/white.list +++ b/foundations/foundation-ssl/src/test/resources/ssl/white.list @@ -1,4 +1,4 @@ 127.0.0.1 10.67.190.60 10.67.147.115 -10.57.65.225 \ No newline at end of file +10.57.65.225 diff --git a/foundations/foundation-test-scaffolding/pom.xml b/foundations/foundation-test-scaffolding/pom.xml index a757c0ad0dd..f3feba62148 100644 --- a/foundations/foundation-test-scaffolding/pom.xml +++ b/foundations/foundation-test-scaffolding/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb foundations - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT foundation-test-scaffolding Java Chassis::Foundations::Test Scaffolding @@ -31,15 +31,6 @@ org.springframework spring-context - - com.netflix.archaius - archaius-core - - - commons-configuration - commons-configuration - compile - io.vertx vertx-web @@ -50,12 +41,18 @@ provided - com.netflix.spectator - spectator-reg-servo + com.google.guava + guava + + + org.apache.logging.log4j + log4j-core + provided + true - log4j - log4j + org.apache.logging.log4j + log4j-api provided true @@ -71,6 +68,11 @@ org.springframework spring-aspects + + io.swagger.core.v3 + swagger-core-jakarta + provided + org.assertj assertj-core diff --git a/foundations/foundation-test-scaffolding/src/main/java/io/vertx/core/impl/SyncContext.java b/foundations/foundation-test-scaffolding/src/main/java/io/vertx/core/impl/SyncContext.java deleted file mode 100644 index ec2536bd961..00000000000 --- a/foundations/foundation-test-scaffolding/src/main/java/io/vertx/core/impl/SyncContext.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 io.vertx.core.impl; - -import io.vertx.core.AsyncResult; -import io.vertx.core.Future; -import io.vertx.core.Handler; -import io.vertx.core.Promise; - -public class SyncContext extends EventLoopContext { - protected VertxInternal owner; - - public SyncContext() { - this(null); - } - - public SyncContext(VertxInternal vertx) { - super(vertx, null, null, null, null, null, null); - } - - public VertxInternal owner() { - return owner; - } - - public void setOwner(VertxInternal owner) { - this.owner = owner; - } - - @Override - public void runOnContext(AbstractContext ctx, Handler action) { - action.handle(null); - } - - public static void syncExecuteBlocking(Handler> blockingCodeHandler, - Handler> asyncResultHandler) { - Promise res = Promise.promise(); - - try { - blockingCodeHandler.handle(res); - } catch (Throwable e) { - res.fail(e); - return; - } - - res.future().onComplete(asyncResultHandler); - } - - private static Future syncExecuteBlocking(Handler> blockingCodeHandler) { - Promise res = Promise.promise(); - - try { - blockingCodeHandler.handle(res); - } catch (Throwable e) { - res.fail(e); - return res.future(); - } - - res.complete(); - return res.future(); - } - - @Override - public Future executeBlockingInternal(Handler> action) { - return syncExecuteBlocking(action); - } - - @Override - public void executeBlocking(Handler> blockingCodeHandler, boolean ordered, - Handler> asyncResultHandler) { - syncExecuteBlocking(blockingCodeHandler, asyncResultHandler); - } -} diff --git a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/AssertUtils.java b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/AssertUtils.java index 84560543d7b..ef310a9da51 100644 --- a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/AssertUtils.java +++ b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/AssertUtils.java @@ -30,4 +30,4 @@ static AbstractStringAssert assertPrettyJson(Object value) { .replace(LineSeparator.WINDOWS.value(), LineSeparator.UNIX.value()); return assertThat(json); } -} \ No newline at end of file +} diff --git a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java deleted file mode 100644 index be347046daf..00000000000 --- a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/config/ArchaiusUtils.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.foundation.test.scaffolding.config; - -import java.lang.reflect.Field; -import java.util.concurrent.ConcurrentHashMap; - -import org.springframework.util.ReflectionUtils; - -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.ConfigurationManager; -import com.netflix.config.DynamicProperty; -import com.netflix.config.DynamicPropertyFactory; - -public final class ArchaiusUtils { - private static final Field FIELD_INSTANCE = ReflectionUtils.findField(ConfigurationManager.class, "instance"); - - private static final Field FIELD_CUSTOM_CONFIGURATION_INSTALLED = - ReflectionUtils.findField(ConfigurationManager.class, "customConfigurationInstalled"); - - private static final Field FIELD_CONFIG = ReflectionUtils.findField(DynamicPropertyFactory.class, "config"); - - private static final Field FIELD_INITIALIZED_WITH_DEFAULT_CONFIG = - ReflectionUtils.findField(DynamicPropertyFactory.class, "initializedWithDefaultConfig"); - - private static final Field FIELD_DYNAMIC_PROPERTY_SUPPORTIMPL = - ReflectionUtils.findField(DynamicProperty.class, "dynamicPropertySupportImpl"); - - private static final Field FIELD_DYNAMIC_PROPERTY_ALL_PROPS = ReflectionUtils - .findField(DynamicProperty.class, "ALL_PROPS"); - - static { - FIELD_INSTANCE.setAccessible(true); - FIELD_CUSTOM_CONFIGURATION_INSTALLED.setAccessible(true); - FIELD_CONFIG.setAccessible(true); - FIELD_INITIALIZED_WITH_DEFAULT_CONFIG.setAccessible(true); - FIELD_DYNAMIC_PROPERTY_SUPPORTIMPL.setAccessible(true); - FIELD_DYNAMIC_PROPERTY_ALL_PROPS.setAccessible(true); - } - - private ArchaiusUtils() { - } - - @SuppressWarnings("unchecked") - public static void resetConfig() { - ReflectionUtils.setField(FIELD_INSTANCE, null, null); - ReflectionUtils.setField(FIELD_CUSTOM_CONFIGURATION_INSTALLED, null, false); - ReflectionUtils.setField(FIELD_CONFIG, null, null); - ReflectionUtils.setField(FIELD_INITIALIZED_WITH_DEFAULT_CONFIG, null, false); - ReflectionUtils.setField(FIELD_DYNAMIC_PROPERTY_SUPPORTIMPL, null, null); - ((ConcurrentHashMap) ReflectionUtils.getField(FIELD_DYNAMIC_PROPERTY_ALL_PROPS, null)) - .clear(); - } - - public static void setProperty(String key, Object value) { - // ensure have instance - DynamicPropertyFactory.getInstance(); - - ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory - .getBackingConfigurationSource(); - if (value != null) { - config.getConfiguration(0).setProperty(key, value); - return; - } - - config.getConfiguration(0).clearProperty(key); - } -} diff --git a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java index cb60423e94e..5b435b89829 100644 --- a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java +++ b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java @@ -19,67 +19,82 @@ import java.io.Closeable; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; -import org.apache.log4j.Appender; -import org.apache.log4j.AppenderSkeleton; -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -import org.apache.log4j.spi.LoggingEvent; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Appender; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.appender.AbstractAppender; +import org.apache.logging.log4j.core.config.Configuration; +import org.apache.logging.log4j.core.config.Property; +import org.apache.logging.log4j.core.layout.PatternLayout; public class LogCollector implements Closeable { - List events = new ArrayList<>(); + List events = new ArrayList<>(); - Appender appender = new AppenderSkeleton() { - @Override - public void append(LoggingEvent event) { - events.add(event); - } + Appender appender; - @Override - public void close() { - - } - - @Override - public boolean requiresLayout() { - return false; - } - }; + String appenderName; public LogCollector() { - Logger.getRootLogger().addAppender(appender); + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + appenderName = "LogCollector" + System.nanoTime(); + appender = new AbstractAppender(appenderName, null, PatternLayout.createDefaultLayout(), + true, + Property.EMPTY_ARRAY) { + @Override + public void append(LogEvent event) { + events.add(event); + } + }; + appender.start(); + config.getRootLogger().addAppender(appender, Level.ALL, null); + ctx.updateLoggers(config); } public LogCollector setLogLevel(String logName, Level level) { - Logger.getLogger(logName).setLevel(level); + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + config.getLoggerConfig(logName).setLevel(level); return this; } - public List getEvents() { + public List getEvents() { return events; } - public LoggingEvent getLastEvents() { + public LogEvent getEvent(int index) { + return events.get(index); + } + + public LogEvent getLastEvents() { return events.get(events.size() - 1); } public List getThrowables() { return events.stream() - .filter(e -> e.getThrowableInformation() != null) - .map(e -> e.getThrowableInformation().getThrowable()) + .map(LogEvent::getThrown) + .filter(Objects::nonNull) .collect(Collectors.toList()); } public List getThrowableMessages() { return events.stream() - .filter(e -> e.getThrowableInformation() != null) - .map(e -> e.getThrowableInformation().getThrowable().getMessage()) + .filter(e -> e.getThrown() != null) + .map(e -> e.getThrown().getMessage()) .collect(Collectors.toList()); } - public void teardown() { - Logger.getRootLogger().removeAppender(appender); + public void tearDown() { + LoggerContext ctx = (LoggerContext) LogManager.getContext(false); + Configuration config = ctx.getConfiguration(); + appender.stop(); + config.getRootLogger().removeAppender(appenderName); + ctx.updateLoggers(config); } public void clear() { @@ -88,6 +103,6 @@ public void clear() { @Override public void close() { - teardown(); + tearDown(); } } diff --git a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/User.java b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/User.java index 0508a67864a..630d48b0ca1 100644 --- a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/User.java +++ b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/model/User.java @@ -19,8 +19,14 @@ import java.util.List; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Schema; + public class User { public String name; + // An issue not fixed by open api + // see: https://github.com/swagger-api/swagger-core/issues/3484 + @ArraySchema(schema = @Schema(implementation = User.class)) public List friends; } diff --git a/foundations/foundation-test-scaffolding/src/main/resources/config/log4j.properties b/foundations/foundation-test-scaffolding/src/main/resources/config/log4j.properties deleted file mode 100644 index a6911b4f6b3..00000000000 --- a/foundations/foundation-test-scaffolding/src/main/resources/config/log4j.properties +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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. -# -paas.logs.dir=target/ \ No newline at end of file diff --git a/foundations/foundation-vertx/pom.xml b/foundations/foundation-vertx/pom.xml index 2670b120112..24556f590f7 100644 --- a/foundations/foundation-vertx/pom.xml +++ b/foundations/foundation-vertx/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb foundations - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT foundation-vertx Java Chassis::Foundations::Vertx @@ -49,10 +49,20 @@ vertx-codegen provided - + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core + test + - org.slf4j - slf4j-log4j12 + org.jmockit + jmockit test diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/AddressResolverConfig.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/AddressResolverConfig.java index 2f0f14a231a..2d4ee389642 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/AddressResolverConfig.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/AddressResolverConfig.java @@ -20,12 +20,10 @@ import java.util.Arrays; import java.util.List; -import org.apache.commons.configuration.Configuration; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.config.DynamicPropertyFactory; - import io.vertx.core.dns.AddressResolverOptions; public class AddressResolverConfig { @@ -37,84 +35,69 @@ public class AddressResolverConfig { * @param tag config tag, such as sc.consumer or cc.consumer * @return AddressResolverOptions */ - public static AddressResolverOptions getAddressResover(String tag) { - return getAddressResover(tag, null); - } - - /** - * get the target endpoints with custom address resolve config - * @param tag config tag, such as sc.consumer or cc.consumer - * @param configSource get config from special config source - * @return AddressResolverOptions - */ - public static AddressResolverOptions getAddressResover(String tag, Configuration configSource) { + public static AddressResolverOptions getAddressResolverOptions(String tag) { AddressResolverOptions addressResolverOptions = new AddressResolverOptions(); addressResolverOptions - .setServers(getStringListProperty(configSource, + .setServers(getStringListProperty( AddressResolverOptions.DEFAULT_SERVERS, "addressResolver." + tag + ".servers", "addressResolver.servers")); addressResolverOptions - .setOptResourceEnabled(getBooleanProperty(configSource, + .setOptResourceEnabled(getBooleanProperty( AddressResolverOptions.DEFAULT_OPT_RESOURCE_ENABLED, "addressResolver." + tag + ".optResourceEnabled", "addressResolver.optResourceEnabled")); addressResolverOptions - .setCacheMinTimeToLive(getPositiveIntProperty(configSource, + .setCacheMinTimeToLive(getPositiveIntProperty( AddressResolverOptions.DEFAULT_CACHE_MIN_TIME_TO_LIVE, "addressResolver." + tag + ".cacheMinTimeToLive", "addressResolver.cacheMinTimeToLive")); addressResolverOptions - .setCacheMaxTimeToLive(getPositiveIntProperty(configSource, + .setCacheMaxTimeToLive(getPositiveIntProperty( AddressResolverOptions.DEFAULT_CACHE_MAX_TIME_TO_LIVE, "addressResolver." + tag + ".cacheMaxTimeToLive", "addressResolver.cacheMaxTimeToLive")); addressResolverOptions - .setCacheNegativeTimeToLive(getPositiveIntProperty(configSource, + .setCacheNegativeTimeToLive(getPositiveIntProperty( AddressResolverOptions.DEFAULT_CACHE_NEGATIVE_TIME_TO_LIVE, "addressResolver." + tag + ".cacheNegativeTimeToLive", "addressResolver.cacheNegativeTimeToLive")); addressResolverOptions - .setQueryTimeout(getPositiveIntProperty(configSource, + .setQueryTimeout(getPositiveIntProperty( AddressResolverOptions.DEFAULT_QUERY_TIMEOUT, "addressResolver." + tag + ".queryTimeout", "addressResolver.queryTimeout")); addressResolverOptions - .setMaxQueries(getPositiveIntProperty(configSource, + .setMaxQueries(getPositiveIntProperty( AddressResolverOptions.DEFAULT_MAX_QUERIES, "addressResolver." + tag + ".maxQueries", "addressResolver.maxQueries")); addressResolverOptions - .setRdFlag(getBooleanProperty(configSource, + .setRdFlag(getBooleanProperty( AddressResolverOptions.DEFAULT_RD_FLAG, "addressResolver." + tag + ".rdFlag", "addressResolver.rdFlag")); addressResolverOptions - .setSearchDomains(getStringListProperty(configSource, - AddressResolverOptions.DEFAULT_SEACH_DOMAINS, + .setSearchDomains(getStringListProperty( + AddressResolverOptions.DEFAULT_SEARCH_DOMAINS, "addressResolver." + tag + ".searchDomains", "addressResolver.searchDomains")); addressResolverOptions - .setNdots(getPositiveIntProperty(configSource, + .setNdots(getPositiveIntProperty( AddressResolverOptions.DEFAULT_NDOTS, "addressResolver." + tag + ".ndots", "addressResolver.ndots")); addressResolverOptions - .setRotateServers(getBooleanProperty(configSource, + .setRotateServers(getBooleanProperty( AddressResolverOptions.DEFAULT_ROTATE_SERVERS, "addressResolver." + tag + ".rotateServers", "addressResolver.rotateServers")); return addressResolverOptions; } - private static List getStringListProperty(Configuration configSource, - List defaultValue, String... keys) { - configSource = guardConfigSource(configSource); - if (configSource == null) { - return defaultValue; - } + private static List getStringListProperty(List defaultValue, String... keys) { for (String key : keys) { - String[] vals = configSource.getStringArray(key); + String[] vals = LegacyPropertyFactory.getProperty(key, String[].class); if (vals != null && vals.length > 0) { return Arrays.asList(vals); } @@ -122,15 +105,11 @@ private static List getStringListProperty(Configuration configSource, return defaultValue; } - private static int getPositiveIntProperty(Configuration configSource, int defaultValue, String... keys) { - configSource = guardConfigSource(configSource); - if (configSource == null) { - return defaultValue; - } + private static int getPositiveIntProperty(int defaultValue, String... keys) { for (String key : keys) { - Integer val = configSource.getInteger(key, null); + Integer val = LegacyPropertyFactory.getProperty(key, Integer.class); if (val != null && val <= 0) { - LOGGER.warn("Address resover key:{}'s value:{} is not positive, please check!", key, val); + LOGGER.warn("Address resolver key:{}'s value:{} is not positive, please check!", key, val); continue; } if (val != null) { @@ -140,25 +119,14 @@ private static int getPositiveIntProperty(Configuration configSource, int defaul return defaultValue; } - private static boolean getBooleanProperty(Configuration configSource, boolean defaultValue, + private static boolean getBooleanProperty(boolean defaultValue, String... keys) { - configSource = guardConfigSource(configSource); - if (configSource == null) { - return defaultValue; - } for (String key : keys) { - Boolean val = configSource.getBoolean(key, null); + Boolean val = LegacyPropertyFactory.getProperty(key, Boolean.class); if (val != null) { return val; } } return defaultValue; } - - private static Configuration guardConfigSource(Configuration configSource) { - if (configSource == null && DynamicPropertyFactory.getBackingConfigurationSource() != null) { - configSource = (Configuration) DynamicPropertyFactory.getBackingConfigurationSource(); - } - return configSource; - } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SharedVertxFactory.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SharedVertxFactory.java index 5e35641a241..9f2d3af797b 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SharedVertxFactory.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SharedVertxFactory.java @@ -18,8 +18,7 @@ import org.apache.servicecomb.foundation.vertx.metrics.DefaultVertxMetricsFactory; import org.apache.servicecomb.foundation.vertx.metrics.MetricsOptionsEx; - -import com.netflix.config.DynamicPropertyFactory; +import org.springframework.core.env.Environment; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; @@ -33,13 +32,13 @@ static class SharedVertxInfo implements Shareable { public MetricsOptionsEx metricsOptionsEx = (MetricsOptionsEx) metricsFactory.newOptions(); - public SharedVertxInfo() { + public SharedVertxInfo(Environment environment) { vertxOptions.setMetricsOptions(metricsOptionsEx); - vertxOptions.setEventLoopPoolSize(readEventLoopPoolSize("servicecomb.transport.eventloop.size")); + vertxOptions.setEventLoopPoolSize(readEventLoopPoolSize(environment, "servicecomb.transport.eventloop.size")); } - private static int readEventLoopPoolSize(String key) { - int count = DynamicPropertyFactory.getInstance().getIntProperty(key, -1).get(); + private static int readEventLoopPoolSize(Environment environment, String key) { + int count = environment.getProperty(key, int.class, -1); if (count > 0) { return count; } @@ -51,20 +50,21 @@ private static int readEventLoopPoolSize(String key) { private static final String INFO = "transport-vertx-info"; - public static DefaultVertxMetricsFactory getMetricsFactory() { - SharedVertxInfo info = (SharedVertxInfo) getSharedVertx().sharedData().getLocalMap(LOCAL_MAP_NAME) + public static DefaultVertxMetricsFactory getMetricsFactory(Environment environment) { + SharedVertxInfo info = (SharedVertxInfo) getSharedVertx(environment).sharedData().getLocalMap(LOCAL_MAP_NAME) .get(INFO); return info.metricsFactory; } - public static Vertx getSharedVertx() { - return VertxUtils.getVertxMap().computeIfAbsent("transport", SharedVertxFactory::createSharedVertx); + public static Vertx getSharedVertx(Environment environment) { + return VertxUtils.getVertxMap().computeIfAbsent("transport", + key -> createSharedVertx(environment, key)); } - private static Vertx createSharedVertx(String name) { - SharedVertxInfo info = new SharedVertxInfo(); + private static Vertx createSharedVertx(Environment environment, String name) { + SharedVertxInfo info = new SharedVertxInfo(environment); - Vertx vertx = VertxUtils.init(name, info.vertxOptions); + Vertx vertx = VertxUtils.init(name, info.vertxOptions, info.metricsFactory); info.metricsFactory.setVertx(vertx, info.vertxOptions); vertx.sharedData().getLocalMap(LOCAL_MAP_NAME).put(INFO, info); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SimpleBodyHandler.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SimpleBodyHandler.java index afced60db00..7f089ead415 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SimpleBodyHandler.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/SimpleBodyHandler.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.foundation.vertx; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.apache.http.HttpHeaders; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxTLSBuilder.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxTLSBuilder.java index 309057259d2..ba2203338e6 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxTLSBuilder.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxTLSBuilder.java @@ -23,6 +23,7 @@ import java.util.HashSet; import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.ssl.SSLCustom; import org.apache.servicecomb.foundation.ssl.SSLManager; import org.apache.servicecomb.foundation.ssl.SSLOption; @@ -32,6 +33,7 @@ import io.vertx.core.http.ClientAuth; import io.vertx.core.http.HttpClientOptions; +import io.vertx.core.http.WebSocketClientOptions; import io.vertx.core.net.ClientOptionsBase; import io.vertx.core.net.JksOptions; import io.vertx.core.net.NetServerOptions; @@ -75,10 +77,10 @@ private static void setClientAuth(SSLOption sslOption, NetServerOptions netServe } public static void buildHttpClientOptions(String sslKey, HttpClientOptions httpClientOptions) { - SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory(sslKey, null); + SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory(sslKey, LegacyPropertyFactory.getEnvironment()); SSLOption sslOption; if (factory == null) { - sslOption = SSLOption.buildFromYaml(sslKey); + sslOption = SSLOption.build(sslKey, LegacyPropertyFactory.getEnvironment()); } else { sslOption = factory.createSSLOption(); } @@ -86,6 +88,18 @@ public static void buildHttpClientOptions(String sslKey, HttpClientOptions httpC buildHttpClientOptions(sslOption, sslCustom, httpClientOptions); } + public static void buildWebSocketClientOptions(String sslKey, WebSocketClientOptions webSocketClientOptions) { + SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory(sslKey, LegacyPropertyFactory.getEnvironment()); + SSLOption sslOption; + if (factory == null) { + sslOption = SSLOption.build(sslKey, LegacyPropertyFactory.getEnvironment()); + } else { + sslOption = factory.createSSLOption(); + } + SSLCustom sslCustom = SSLCustom.createSSLCustom(sslOption.getSslCustomClass()); + buildWebSocketClientOptions(sslOption, sslCustom, webSocketClientOptions); + } + public static HttpClientOptions buildHttpClientOptions(SSLOption sslOption, SSLCustom sslCustom, HttpClientOptions httpClientOptions) { buildClientOptionsBase(sslOption, sslCustom, httpClientOptions); @@ -93,6 +107,13 @@ public static HttpClientOptions buildHttpClientOptions(SSLOption sslOption, SSLC return httpClientOptions; } + public static WebSocketClientOptions buildWebSocketClientOptions(SSLOption sslOption, SSLCustom sslCustom, + WebSocketClientOptions webSocketClientOptions) { + buildClientOptionsBase(sslOption, sslCustom, webSocketClientOptions); + webSocketClientOptions.setVerifyHost(sslOption.isCheckCNHost()); + return webSocketClientOptions; + } + public static ClientOptionsBase buildClientOptionsBase(SSLOption sslOption, SSLCustom sslCustom, ClientOptionsBase clientOptionsBase) { buildTCPSSLOptions(sslOption, sslCustom, clientOptionsBase); @@ -110,9 +131,7 @@ private static TCPSSLOptions buildTCPSSLOptions(SSLOption sslOption, SSLCustom s tcpClientOptions.setSsl(true); if (sslOption.getEngine().equalsIgnoreCase("openssl")) { - OpenSSLEngineOptions options = new OpenSSLEngineOptions(); - options.setSessionCacheEnabled(true); - tcpClientOptions.setOpenSslEngineOptions(new OpenSSLEngineOptions()); + tcpClientOptions.setSslEngineOptions(new OpenSSLEngineOptions()); } String fullKeyStore = sslCustom.getFullPath(sslOption.getKeyStore()); if (isFileExists(fullKeyStore)) { @@ -120,12 +139,12 @@ private static TCPSSLOptions buildTCPSSLOptions(SSLOption sslOption, SSLCustom s PfxOptions keyPfxOptions = new PfxOptions(); keyPfxOptions.setPath(fullKeyStore); keyPfxOptions.setPassword(new String(sslCustom.decode(sslOption.getKeyStoreValue().toCharArray()))); - tcpClientOptions.setPfxKeyCertOptions(keyPfxOptions); + tcpClientOptions.setKeyCertOptions(keyPfxOptions); } else if (STORE_JKS.equalsIgnoreCase(sslOption.getKeyStoreType())) { JksOptions keyJksOptions = new JksOptions(); keyJksOptions.setPath(fullKeyStore); keyJksOptions.setPassword(new String(sslCustom.decode(sslOption.getKeyStoreValue().toCharArray()))); - tcpClientOptions.setKeyStoreOptions(keyJksOptions); + tcpClientOptions.setKeyCertOptions(keyJksOptions); } else { throw new IllegalArgumentException("invalid key store type."); } @@ -139,13 +158,13 @@ private static TCPSSLOptions buildTCPSSLOptions(SSLOption sslOption, SSLCustom s trustPfxOptions.setPath(fullTrustStore); trustPfxOptions .setPassword(new String(sslCustom.decode(sslOption.getTrustStoreValue().toCharArray()))); - tcpClientOptions.setPfxTrustOptions(trustPfxOptions); + tcpClientOptions.setTrustOptions(trustPfxOptions); } else if (STORE_JKS.equalsIgnoreCase(sslOption.getTrustStoreType())) { JksOptions trustJksOptions = new JksOptions(); trustJksOptions.setPath(fullTrustStore); trustJksOptions .setPassword(new String(sslCustom.decode(sslOption.getTrustStoreValue().toCharArray()))); - tcpClientOptions.setTrustStoreOptions(trustJksOptions); + tcpClientOptions.setTrustOptions(trustJksOptions); } else { throw new IllegalArgumentException("invalid trust store type."); } @@ -154,9 +173,9 @@ private static TCPSSLOptions buildTCPSSLOptions(SSLOption sslOption, SSLCustom s } tcpClientOptions - .setEnabledSecureTransportProtocols(new HashSet(Arrays.asList(sslOption.getProtocols().split(",")))); + .setEnabledSecureTransportProtocols(new HashSet<>(Arrays.asList(sslOption.getProtocols().split(",")))); - for (String cipher : SSLManager.getEnabledCiphers(sslOption.getCiphers())) { + for (String cipher : SSLManager.getEnabledCiphers(sslOption)) { tcpClientOptions.addEnabledCipherSuite(cipher); } @@ -175,10 +194,14 @@ private static boolean isFileExists(String name) { return true; } - ClassLoader classLoader = - Thread.currentThread().getContextClassLoader() == null ? VertxTLSBuilder.class.getClassLoader() - : Thread.currentThread().getContextClassLoader(); - URL resource = classLoader.getResource(name); - return resource != null; + try { + ClassLoader classLoader = + Thread.currentThread().getContextClassLoader() == null ? VertxTLSBuilder.class.getClassLoader() + : Thread.currentThread().getContextClassLoader(); + URL resource = classLoader.getResource(name); + return resource != null; + } catch (Exception e) { + return false; + } } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java index 953f989145e..5eceac0b24d 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/VertxUtils.java @@ -20,13 +20,14 @@ import java.io.IOException; import java.io.InputStream; import java.lang.management.ManagementFactory; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.apache.commons.io.IOUtils; -import org.apache.servicecomb.foundation.common.Holder; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager; import org.apache.servicecomb.foundation.vertx.client.ClientVerticle; @@ -34,19 +35,20 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.config.DynamicPropertyFactory; - import io.netty.buffer.ByteBuf; import io.vertx.core.AbstractVerticle; import io.vertx.core.DeploymentOptions; +import io.vertx.core.Future; import io.vertx.core.Verticle; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.buffer.Buffer; -import io.vertx.core.file.impl.FileResolver; -import io.vertx.core.impl.VertxBuilder; +import io.vertx.core.impl.SysProps; import io.vertx.core.impl.VertxThread; +import io.vertx.core.internal.VertxBootstrap; +import io.vertx.core.spi.VertxMetricsFactory; import io.vertx.core.spi.VertxThreadFactory; +import io.vertx.core.transport.Transport; /** * VertxUtils @@ -59,7 +61,7 @@ public final class VertxUtils { private static final long BLOCKED_THREAD_CHECK_INTERVAL = Long.MAX_VALUE / 2; // key为vertx实例名称,以支撑vertx功能分组 - private static Map vertxMap = new ConcurrentHashMapEx<>(); + private static final Map vertxMap = new ConcurrentHashMapEx<>(); private VertxUtils() { } @@ -85,17 +87,19 @@ public static DeploymentOptions createClientDeployOptions( } // deploy Verticle and wait for its success. do not call this method in event-loop thread - public static boolean blockDeploy(Vertx vertx, + public static Map blockDeploy(Vertx vertx, Class cls, DeploymentOptions options) throws InterruptedException { - Holder result = new Holder<>(); + Map result = new HashMap<>(); CountDownLatch latch = new CountDownLatch(1); - vertx.deployVerticle(cls.getName(), options, ar -> { - result.value = ar.succeeded(); + Future future = vertx.deployVerticle(cls.getName(), options); + future.onComplete((success, failure) -> { + result.put("code", failure == null); - if (ar.failed()) { - LOGGER.error("deploy vertx failed, cause ", ar.cause()); + if (failure != null) { + result.put("message", failure.getMessage()); + LOGGER.error("deploy vertx failed, cause ", failure); } latch.countDown(); @@ -103,14 +107,15 @@ public static boolean blockDeploy(Vertx vertx, latch.await(); - return result.value; + return result; } - public static Vertx getOrCreateVertxByName(String name, VertxOptions vertxOptions) { - return vertxMap.computeIfAbsent(name, vertxName -> init(vertxName, vertxOptions)); + public static Vertx getOrCreateVertxByName(String name, VertxOptions vertxOptions, + VertxMetricsFactory metricsFactory) { + return vertxMap.computeIfAbsent(name, vertxName -> init(name, vertxOptions, metricsFactory)); } - public static Vertx init(String name, VertxOptions vertxOptions) { + public static Vertx init(String name, VertxOptions vertxOptions, VertxMetricsFactory metricsFactory) { if (vertxOptions == null) { vertxOptions = new VertxOptions(); } @@ -123,29 +128,46 @@ public static Vertx init(String name, VertxOptions vertxOptions) { configureVertxFileCaching(vertxOptions); - return new VertxBuilder(vertxOptions).threadFactory(new VertxThreadFactory() { - @Override - public VertxThread newVertxThread(Runnable target, String threadName, boolean worker, long maxExecTime, - TimeUnit maxExecTimeUnit) { - return VertxThreadFactory.super - .newVertxThread(target, name + "-" + threadName, worker, maxExecTime, maxExecTimeUnit); - } - }).init().vertx(); + VertxBootstrap bootstrap = bootstrap(vertxOptions, metricsFactory) + .threadFactory(new VertxThreadFactory() { + @Override + public VertxThread newVertxThread(Runnable target, String threadName, boolean worker, long maxExecTime, + TimeUnit maxExecTimeUnit) { + return VertxThreadFactory.super + .newVertxThread(target, name + "-" + threadName, worker, maxExecTime, maxExecTimeUnit); + } + }); + + return bootstrap.init().vertx(); + } + + private static VertxBootstrap bootstrap(VertxOptions options, VertxMetricsFactory metricsFactory) { + VertxBootstrap bootstrap = VertxBootstrap.create(); + bootstrap.options(options); + bootstrap.metricsFactory(metricsFactory); + Transport tr; + if (options.getPreferNativeTransport()) { + tr = Transport.nativeTransport(); + } else { + tr = Transport.NIO; + } + bootstrap.transport(tr.implementation()); + return bootstrap; } /** * 配置vertx的文件缓存功能,默认关闭 */ - protected static void configureVertxFileCaching(VertxOptions vertxOptions) { - boolean disableFileCPResolving = DynamicPropertyFactory.getInstance() - .getBooleanProperty(FileResolver.DISABLE_CP_RESOLVING_PROP_NAME, true).get(); + private static void configureVertxFileCaching(VertxOptions vertxOptions) { + boolean disableFileCPResolving = LegacyPropertyFactory + .getBooleanProperty(SysProps.DISABLE_FILE_CP_RESOLVING.name, true); vertxOptions.getFileSystemOptions().setClassPathResolvingEnabled(!disableFileCPResolving); } // try to reference byte[] // otherwise copy byte[] public static byte[] getBytesFast(InputStream inputStream) throws IOException { - if (BufferInputStream.class.isInstance(inputStream)) { + if (inputStream instanceof BufferInputStream) { return getBytesFast(((BufferInputStream) inputStream).getByteBuf()); } @@ -153,8 +175,9 @@ public static byte[] getBytesFast(InputStream inputStream) throws IOException { } public static byte[] getBytesFast(Buffer buffer) { - ByteBuf byteBuf = buffer.getByteBuf(); - return getBytesFast(byteBuf); + byte[] arr = new byte[buffer.length()]; + buffer.getBytes(arr, 0); + return arr; } public static byte[] getBytesFast(ByteBuf byteBuf) { @@ -177,22 +200,24 @@ public static CompletableFuture closeVertxByName(String name) { return future; } - vertx.close(ar -> { - if (ar.succeeded()) { + Future closeFuture = vertx.close(); + closeFuture.onComplete((succ, fail) -> { + if (fail == null) { LOGGER.info("Success to close vertx {}.", name); future.complete(null); return; } - future.completeExceptionally(ar.cause()); + future.completeExceptionally(fail); }); + return future; } public static void blockCloseVertxByName(String name) { CompletableFuture future = closeVertxByName(name); try { - future.get(); + future.get(30, TimeUnit.SECONDS); } catch (Throwable e) { LOGGER.error("Failed to wait close vertx {}.", name, e); } @@ -200,8 +225,9 @@ public static void blockCloseVertxByName(String name) { public static void blockCloseVertx(Vertx vertx) { CountDownLatch latch = new CountDownLatch(1); - vertx.close(ar -> { - if (ar.succeeded()) { + Future closeFuture = vertx.close(); + closeFuture.onComplete((succ, fail) -> { + if (fail == null) { LOGGER.info("Success to close vertx {}.", vertx); } else { LOGGER.info("Failed to close vertx {}.", vertx); @@ -211,8 +237,8 @@ public static void blockCloseVertx(Vertx vertx) { }); try { - latch.await(); - } catch (InterruptedException e) { + latch.await(30, TimeUnit.SECONDS); + } catch (Throwable e) { LOGGER.info("Failed to wait close vertx {}.", vertx); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java index e86673226d4..900f994c161 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/ClientPoolManager.java @@ -39,17 +39,17 @@ * sync/async is not about net operation, just about consumer invoke mode. */ public class ClientPoolManager { - private Vertx vertx; + private final Vertx vertx; - private String id = UUID.randomUUID().toString(); + private final String id = UUID.randomUUID().toString(); - private ClientPoolFactory factory; + private final ClientPoolFactory factory; - private List pools = new CopyOnWriteArrayList<>(); + private final List pools = new CopyOnWriteArrayList<>(); // reactive mode, when call from other thread, must select a context for it // if we use threadId to hash a context, will always select the same context from one thread - private AtomicInteger reactiveNextIndex = new AtomicInteger(); + private final AtomicInteger reactiveNextIndex = new AtomicInteger(); public ClientPoolManager(Vertx vertx, ClientPoolFactory factory) { this.vertx = vertx; @@ -95,9 +95,9 @@ protected CLIENT_POOL findByContext(Context targetContext) { return clientPool; } - // this will make "client.thread-count" bigger than which in microservice.yaml - // maybe it's better to remove "client.thread-count", just use "rest/highway.thread-count" - return createClientPool(currentContext); + // Maybe executed in a call back of a reactive call. + // The Context is created in a non-event thread and passed to the event loop + // thread by vert.x. } // not in correct context: @@ -120,7 +120,7 @@ public CLIENT_POOL findThreadBindClientPool() { } private void assertPoolsInitialized() { - if (pools.size() == 0) { + if (pools.isEmpty()) { throw new IllegalStateException("client pool not initialized successfully when making calls." + "Please check if system boot up is ready or some errors happened when startup."); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientOptionsSPI.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientOptionsSPI.java index 164e4f4dc4c..83bf28db9ca 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientOptionsSPI.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientOptionsSPI.java @@ -20,10 +20,10 @@ import org.apache.servicecomb.foundation.common.encrypt.Encryptions; import org.apache.servicecomb.foundation.vertx.VertxTLSBuilder; -import com.netflix.config.ConcurrentCompositeConfiguration; - import io.vertx.core.http.HttpClientOptions; import io.vertx.core.http.HttpVersion; +import io.vertx.core.http.WebSocketClientOptions; +import io.vertx.core.net.ClientOptionsBase; import io.vertx.core.net.ProxyOptions; /** @@ -40,12 +40,9 @@ public interface HttpClientOptionsSPI { boolean enabled(); /* config tag is used for group configurations, like ssl, address resolver, etc. set config tag to distinguish - * other clients configuration or read the common configuration. */ + * other clients configuration or read the common configuration. */ String getConfigTag(); - /* for config modules, the configuration is not ready, need set up config reader */ - ConcurrentCompositeConfiguration getConfigReader(); - /***************** vert.x common settings ***************************/ int getEventLoopPoolSize(); @@ -79,12 +76,15 @@ public interface HttpClientOptionsSPI { int getKeepAliveTimeout(); + boolean enableLogActivity(); + /***************** http 2 settings ****************************/ int getHttp2MultiplexingLimit(); int getHttp2MaxPoolSize(); boolean isUseAlpn(); + /***************** proxy settings ***************************/ boolean isProxyEnable(); @@ -99,18 +99,10 @@ public interface HttpClientOptionsSPI { /***************** ssl settings ***************************/ boolean isSsl(); - static HttpClientOptions createHttpClientOptions(HttpClientOptionsSPI spi) { - HttpClientOptions httpClientOptions = new HttpClientOptions(); - - httpClientOptions.setProtocolVersion(spi.getHttpVersion()); + static void buildClientOptionsBase(HttpClientOptionsSPI spi, ClientOptionsBase httpClientOptions) { httpClientOptions.setConnectTimeout(spi.getConnectTimeoutInMillis()); httpClientOptions.setIdleTimeout(spi.getIdleTimeoutInSeconds()); - httpClientOptions.setTryUseCompression(spi.isTryUseCompression()); - httpClientOptions.setMaxWaitQueueSize(spi.getMaxWaitQueueSize()); - httpClientOptions.setMaxPoolSize(spi.getMaxPoolSize()); - httpClientOptions.setKeepAlive(spi.isKeepAlive()); - httpClientOptions.setMaxHeaderSize(spi.getMaxHeaderSize()); - httpClientOptions.setKeepAliveTimeout(spi.getKeepAliveTimeout()); + httpClientOptions.setLogActivity(spi.enableLogActivity()); if (spi.isProxyEnable()) { ProxyOptions proxy = new ProxyOptions(); @@ -123,10 +115,25 @@ static HttpClientOptions createHttpClientOptions(HttpClientOptionsSPI spi) { } if (spi.getHttpVersion() == HttpVersion.HTTP_2) { - httpClientOptions.setHttp2ClearTextUpgrade(false); httpClientOptions.setUseAlpn(spi.isUseAlpn()); + } + } + + static HttpClientOptions createHttpClientOptions(HttpClientOptionsSPI spi) { + HttpClientOptions httpClientOptions = new HttpClientOptions(); + buildClientOptionsBase(spi, httpClientOptions); + + httpClientOptions.setProtocolVersion(spi.getHttpVersion()); + httpClientOptions.setDecompressionSupported(spi.isTryUseCompression()); + httpClientOptions.setKeepAlive(spi.isKeepAlive()); + httpClientOptions.setMaxHeaderSize(spi.getMaxHeaderSize()); + + if (spi.getHttpVersion() == HttpVersion.HTTP_2) { + httpClientOptions.setHttp2ClearTextUpgrade(false); httpClientOptions.setHttp2MultiplexingLimit(spi.getHttp2MultiplexingLimit()); - httpClientOptions.setHttp2MaxPoolSize(spi.getHttp2MaxPoolSize()); + httpClientOptions.setHttp2KeepAliveTimeout(spi.getKeepAliveTimeout()); + } else { + httpClientOptions.setKeepAliveTimeout(spi.getKeepAliveTimeout()); } if (spi.isSsl()) { @@ -135,4 +142,15 @@ static HttpClientOptions createHttpClientOptions(HttpClientOptionsSPI spi) { return httpClientOptions; } + + static WebSocketClientOptions createWebSocketClientOptions(HttpClientOptionsSPI spi, boolean sslEnabled) { + WebSocketClientOptions webSocketClientOptions = new WebSocketClientOptions(); + buildClientOptionsBase(spi, webSocketClientOptions); + + if (sslEnabled) { + VertxTLSBuilder.buildWebSocketClientOptions(spi.getConfigTag(), webSocketClientOptions); + } + + return webSocketClientOptions; + } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientPoolFactory.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientPoolFactory.java index 685ddf8a7aa..69f15e6e397 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientPoolFactory.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientPoolFactory.java @@ -5,9 +5,7 @@ * 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. @@ -24,32 +22,38 @@ import io.vertx.core.Context; import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientOptions; +import io.vertx.core.http.PoolOptions; // execute in vertx context public class HttpClientPoolFactory implements ClientPoolFactory { private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientPoolFactory.class); - private HttpClientOptions httpClientOptions; + private final HttpClientOptions httpClientOptions; - public HttpClientPoolFactory(HttpClientOptions httpClientOptions) { + private final PoolOptions poolOptions; + + public HttpClientPoolFactory(HttpClientOptions httpClientOptions, PoolOptions poolOptions) { this.httpClientOptions = httpClientOptions; + this.poolOptions = poolOptions; } @Override public HttpClientWithContext createClientPool(Context context) { - HttpClient httpClient = context.owner().createHttpClient(httpClientOptions); - httpClient.connectionHandler(connection -> { - LOGGER.debug("http connection connected, local:{}, remote:{}.", - connection.localAddress(), connection.remoteAddress()); - connection.closeHandler(v -> - LOGGER.debug("http connection closed, local:{}, remote:{}.", - connection.localAddress(), connection.remoteAddress()) - ); - connection.exceptionHandler(e -> - LOGGER.info("http connection exception, local:{}, remote:{}.", - connection.localAddress(), connection.remoteAddress(), e) - ); - }); + HttpClient httpClient = context.owner().httpClientBuilder() + .with(httpClientOptions) + .with(poolOptions) + .withConnectHandler(connection -> { + LOGGER.debug("http connection connected, local:{}, remote:{}.", + connection.localAddress(), connection.remoteAddress()); + connection.closeHandler(v -> + LOGGER.debug("http connection closed, local:{}, remote:{}.", + connection.localAddress(), connection.remoteAddress()) + ); + connection.exceptionHandler(e -> + LOGGER.error("http connection exception, local:{}, remote:{}.", + connection.localAddress(), connection.remoteAddress(), e) + ); + }).build(); return new HttpClientWithContext(httpClient, context); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientWithContext.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientWithContext.java index 9b85ac3ad6a..f9dab51e83a 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientWithContext.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClientWithContext.java @@ -25,9 +25,9 @@ public interface RunHandler { void run(HttpClient httpClient); } - private HttpClient httpClient; + private final HttpClient httpClient; - private Context context; + private final Context context; public HttpClientWithContext(HttpClient httpClient, Context context) { this.httpClient = httpClient; @@ -39,9 +39,7 @@ public HttpClient getHttpClient() { } public void runOnContext(RunHandler handler) { - context.runOnContext((v) -> { - handler.run(httpClient); - }); + context.runOnContext((v) -> handler.run(httpClient)); } public Context context() { diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClients.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClients.java index 1f62e4a1be6..b1ef46436ec 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClients.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/http/HttpClients.java @@ -21,6 +21,7 @@ import java.util.List; import java.util.Map; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.AddressResolverConfig; import org.apache.servicecomb.foundation.vertx.SharedVertxFactory; @@ -30,13 +31,14 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.annotations.VisibleForTesting; - import io.vertx.core.Context; import io.vertx.core.DeploymentOptions; +import io.vertx.core.ThreadingModel; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.dns.AddressResolverOptions; +import io.vertx.core.http.PoolOptions; +import io.vertx.core.http.WebSocketClient; /** * load and manages a set of HttpClient at boot up. @@ -60,34 +62,25 @@ public static void load() { }); } - @VisibleForTesting - public static void mockClientPoolManager(String name, ClientPoolManager clientPool) { - httpClients.put(name, clientPool); - } - - /* used for configurations module: these module must be boot before other HttpClients is initialized. so can - * not load by SPI, must add manually */ - public static void addNewClientPoolManager(HttpClientOptionsSPI option) { - httpClients.put(option.clientName(), createClientPoolManager(option)); - } - /* destroy at shutdown. */ public static void destroy() { httpClients.clear(); List clientOptionsList = SPIServiceUtils.getOrLoadSortedService(HttpClientOptionsSPI.class); - clientOptionsList.forEach(option -> { - VertxUtils.blockCloseVertxByName(option.clientName()); - }); + clientOptionsList.forEach(option -> VertxUtils.blockCloseVertxByName(option.clientName())); } private static ClientPoolManager createClientPoolManager(HttpClientOptionsSPI option) { Vertx vertx = getOrCreateVertx(option); + PoolOptions poolOptions = new PoolOptions(); + poolOptions.setMaxWaitQueueSize(option.getMaxWaitQueueSize()); + poolOptions.setHttp1MaxSize(option.getMaxPoolSize()); + poolOptions.setHttp2MaxSize(option.getHttp2MaxPoolSize()); ClientPoolManager clientPoolManager = new ClientPoolManager<>(vertx, - new HttpClientPoolFactory(HttpClientOptionsSPI.createHttpClientOptions(option))); + new HttpClientPoolFactory(HttpClientOptionsSPI.createHttpClientOptions(option), poolOptions)); DeploymentOptions deployOptions = VertxUtils.createClientDeployOptions(clientPoolManager, - option.getInstanceCount()) - .setWorker(option.isWorker()) + option.getInstanceCount()) + .setThreadingModel(option.isWorker() ? ThreadingModel.WORKER : ThreadingModel.EVENT_LOOP) .setWorkerPoolName(option.getWorkerPoolName()) .setWorkerPoolSize(option.getWorkerPoolSize()); try { @@ -98,19 +91,24 @@ private static ClientPoolManager createClientPoolManager( } } + public static WebSocketClient createWebSocketClient(HttpClientOptionsSPI option, boolean sslEnabled) { + Vertx vertx = getOrCreateVertx(option); + return vertx.createWebSocketClient(HttpClientOptionsSPI.createWebSocketClientOptions(option, sslEnabled)); + } + private static Vertx getOrCreateVertx(HttpClientOptionsSPI option) { if (option.useSharedVertx()) { - return SharedVertxFactory.getSharedVertx(); + return SharedVertxFactory.getSharedVertx(LegacyPropertyFactory.getEnvironment()); } AddressResolverOptions resolverOptions = AddressResolverConfig - .getAddressResover(option.getConfigTag(), option.getConfigReader()); + .getAddressResolverOptions(option.getConfigTag()); VertxOptions vertxOptions = new VertxOptions() .setAddressResolverOptions(resolverOptions) .setEventLoopPoolSize(option.getEventLoopPoolSize()); // Maybe we can deploy only one vert.x for the application. However this has did it like this. - return VertxUtils.getOrCreateVertxByName(option.clientName(), vertxOptions); + return VertxUtils.getOrCreateVertxByName(option.clientName(), vertxOptions, null); } /** @@ -119,12 +117,7 @@ private static Vertx getOrCreateVertx(HttpClientOptionsSPI option) { * @return the deployed instance name */ public static HttpClientWithContext getClient(String clientName) { - ClientPoolManager poolManager = httpClients.get(clientName); - if (poolManager == null) { - LOGGER.error("client name [{}] not exists, should only happen in tests.", clientName); - return null; - } - return poolManager.findThreadBindClientPool(); + return getClient(clientName, true); } /** @@ -134,12 +127,7 @@ public static HttpClientWithContext getClient(String clientName) { * @return the deployed instance name */ public static HttpClientWithContext getClient(String clientName, boolean sync) { - ClientPoolManager poolManager = httpClients.get(clientName); - if (poolManager == null) { - LOGGER.error("client name [{}] not exists, should only happen in tests.", clientName); - return null; - } - return poolManager.findClientPool(sync); + return getClient(clientName, sync, null); } /** diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/AbstractTcpClientPackage.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/AbstractTcpClientPackage.java index 823e3dde37b..ef6717f8968 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/AbstractTcpClientPackage.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/AbstractTcpClientPackage.java @@ -21,15 +21,15 @@ import org.apache.servicecomb.foundation.vertx.tcp.TcpOutputStream; public abstract class AbstractTcpClientPackage { - private static AtomicLong reqId = new AtomicLong(); + private static final AtomicLong reqId = new AtomicLong(); public static long getAndIncRequestId() { return reqId.getAndIncrement(); } - private long msRequestTimeout; + private volatile long msRequestTimeout; - private long finishWriteToBuffer; + private volatile long finishWriteToBuffer; protected long msgId = getAndIncRequestId(); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/NetClientWrapper.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/NetClientWrapper.java index b0c2542286d..ce47126ee47 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/NetClientWrapper.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/NetClientWrapper.java @@ -16,8 +16,7 @@ */ package org.apache.servicecomb.foundation.vertx.client.tcp; -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; +import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.net.NetClient; import io.vertx.core.net.NetSocket; @@ -26,13 +25,13 @@ // can not support normal and ssl by the same instance // so we do this wrap public class NetClientWrapper { - private TcpClientConfig normalClientConfig; + private final TcpClientConfig normalClientConfig; - private NetClient normalNetClient; + private final NetClient normalNetClient; - private TcpClientConfig sslClientConfig; + private final TcpClientConfig sslClientConfig; - private NetClient sslNetClient; + private final NetClient sslNetClient; public NetClientWrapper(Vertx vertx, TcpClientConfig normalClientConfig, TcpClientConfig sslClientConfig) { this.normalClientConfig = normalClientConfig; @@ -50,12 +49,11 @@ public TcpClientConfig getClientConfig(boolean ssl) { return normalClientConfig; } - public void connect(boolean ssl, int port, String host, Handler> connectHandler) { + public Future connect(boolean ssl, int port, String host) { if (ssl) { - sslNetClient.connect(port, host, connectHandler); - return; + return sslNetClient.connect(port, host); } - normalNetClient.connect(port, host, connectHandler); + return normalNetClient.connect(port, host); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientConnection.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientConnection.java index 080cc1e9d85..db071e3c34f 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientConnection.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientConnection.java @@ -39,6 +39,7 @@ import io.vertx.core.AsyncResult; import io.vertx.core.Context; +import io.vertx.core.Future; import io.vertx.core.buffer.Buffer; import io.vertx.core.net.NetSocket; import io.vertx.core.net.impl.NetSocketImpl; @@ -53,24 +54,24 @@ enum Status { WORKING } - private NetClientWrapper netClientWrapper; + private final NetClientWrapper netClientWrapper; - private TcpClientConfig clientConfig; + private final TcpClientConfig clientConfig; - private URIEndpointObject endpoint; + private final URIEndpointObject endpoint; - private InetSocketAddress socketAddress; + private final InetSocketAddress socketAddress; - private boolean localSupportLogin = false; + private volatile boolean localSupportLogin = false; - private boolean remoteSupportLogin; + private final boolean remoteSupportLogin; private volatile Status status = Status.DISCONNECTED; // save msg before login success. // before login, we can not know parameters, like: zip/codec compatible, and so on // so can only save package, can not save byteBuf - private Queue packageQueue = new ConcurrentLinkedQueue<>(); + private final Queue packageQueue = new ConcurrentLinkedQueue<>(); private volatile Map requestMap = new ConcurrentHashMap<>(); @@ -144,7 +145,7 @@ private boolean writeToBufferQueue(AbstractTcpClientPackage tcpClientPackage) { if (Status.WORKING.equals(status)) { // encode in sender thread try (TcpOutputStream os = tcpClientPackage.createStream()) { - write(os.getByteBuf()); + write(os.getBuffer()); tcpClientPackage.finishWriteToBuffer(); } return true; @@ -180,17 +181,17 @@ protected void connect() { this.status = Status.CONNECTING; LOGGER.info("connecting to address {}", socketAddress.toString()); - netClientWrapper.connect(endpoint.isSslEnabled(), + Future result = netClientWrapper.connect(endpoint.isSslEnabled(), socketAddress.getPort(), - socketAddress.getHostString(), - ar -> { - if (ar.succeeded()) { - onConnectSuccess(ar.result()); - return; - } - - onConnectFailed(ar.cause()); - }); + socketAddress.getHostString()); + result.onComplete((socket, fail) -> { + if (fail == null) { + onConnectSuccess(socket); + return; + } + + onConnectFailed(fail); + }); } private void onConnectSuccess(NetSocket socket) { @@ -208,7 +209,8 @@ private void onConnectSuccess(NetSocket socket) { tryLogin(); } - private void onClosed(Void v) { + @VisibleForTesting + void onClosed(Void v) { onDisconnected(new IOException("socket closed")); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientPackage.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientPackage.java index f63173cd405..ceee9357f9e 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientPackage.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpClientPackage.java @@ -19,7 +19,7 @@ import org.apache.servicecomb.foundation.vertx.tcp.TcpOutputStream; public class TcpClientPackage extends AbstractTcpClientPackage { - private TcpOutputStream os; + private final TcpOutputStream os; public TcpClientPackage(TcpOutputStream os) { this.os = os; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpRequest.java index d1a44e0da90..6ca90adbcf1 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpRequest.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/client/tcp/TcpRequest.java @@ -24,15 +24,15 @@ import io.vertx.core.buffer.Buffer; public class TcpRequest { - private long begin; + private final long begin; - private long msTimeout; + private final long msTimeout; - private Context callContext; + private final Context callContext; - private long threadId; + private final long threadId; - private TcpResponseCallback responseCallback; + private final TcpResponseCallback responseCallback; public TcpRequest(long msTimeout, TcpResponseCallback responseCallback) { callContext = Vertx.currentContext(); @@ -50,9 +50,7 @@ public void onReply(Buffer headerBuffer, Buffer bodyBuffer) { return; } - callContext.runOnContext(Void -> { - responseCallback.success(tcpData); - }); + callContext.runOnContext(Void -> responseCallback.success(tcpData)); } public void onSendError(Throwable e) { diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxContextExecutor.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxContextExecutor.java index 1d85fb36d03..49febb1b3d4 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxContextExecutor.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxContextExecutor.java @@ -31,7 +31,7 @@ public static VertxContextExecutor create(Context context) { return new VertxContextExecutor(context); } - private Context context; + private final Context context; private VertxContextExecutor(Context context) { this.context = context; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxWorkerExecutor.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxWorkerExecutor.java index 6fcbe683d19..e3334a79f1b 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxWorkerExecutor.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/executor/VertxWorkerExecutor.java @@ -25,10 +25,9 @@ public class VertxWorkerExecutor implements Executor { @Override public void execute(Runnable command) { - Vertx.currentContext().owner().executeBlocking(future -> { - command.run(); - }, - false, - null); + Vertx.currentContext().owner().executeBlocking(() -> { + command.run(); + return null; + }, false); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletRequest.java index b4bea0e9dac..058a9390464 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletRequest.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletRequest.java @@ -28,22 +28,23 @@ import java.util.Locale; import java.util.Map; -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletConnection; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpUpgradeHandler; +import jakarta.servlet.http.Part; public abstract class AbstractHttpServletRequest extends BodyBufferSupportImpl implements HttpServletRequestEx { - private Map attributeMap = new HashMap<>(); + private final Map attributeMap = new HashMap<>(); @Override public Object getAttribute(String name) { @@ -65,6 +66,21 @@ public void setCharacterEncoding(String env) throws UnsupportedEncodingException throw new Error("not supported method"); } + @Override + public String getRequestId() { + throw new Error("not supported method"); + } + + @Override + public String getProtocolRequestId() { + throw new Error("not supported method"); + } + + @Override + public ServletConnection getServletConnection() { + throw new Error("not supported method"); + } + @Override public int getContentLength() { throw new Error("not supported method"); @@ -170,12 +186,6 @@ public RequestDispatcher getRequestDispatcher(String path) { throw new Error("not supported method"); } - @Override - @Deprecated - public String getRealPath(String path) { - throw new Error("not supported method"); - } - @Override public int getRemotePort() { throw new Error("not supported method"); @@ -357,12 +367,6 @@ public boolean isRequestedSessionIdFromURL() { throw new Error("not supported method"); } - @Override - @Deprecated - public boolean isRequestedSessionIdFromUrl() { - throw new Error("not supported method"); - } - @Override public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { throw new Error("not supported method"); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletResponse.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletResponse.java index 8b1a9a6a421..bd7899b471c 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletResponse.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/AbstractHttpServletResponse.java @@ -25,13 +25,14 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.Part; -import javax.ws.rs.core.Response.StatusType; +import io.vertx.core.buffer.Buffer; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.Response.StatusType; public abstract class AbstractHttpServletResponse extends BodyBufferSupportImpl implements HttpServletResponseEx { - private Map attributes = new HashMap<>(); + private final Map attributes = new HashMap<>(); @Override public String getCharacterEncoding() { @@ -85,6 +86,11 @@ public int getBufferSize() { @Override public void flushBuffer() throws IOException { + // for vert.x do noting + } + + @Override + public void endResponse() throws IOException { throw new Error("not supported method"); } @@ -133,18 +139,6 @@ public String encodeRedirectURL(String url) { throw new Error("not supported method"); } - @Override - @Deprecated - public String encodeUrl(String url) { - throw new Error("not supported method"); - } - - @Override - @Deprecated - public String encodeRedirectUrl(String url) { - throw new Error("not supported method"); - } - @Override public void sendError(int sc, String msg) throws IOException { throw new Error("not supported method"); @@ -195,12 +189,6 @@ public void setStatus(int sc) { throw new Error("not supported method"); } - @Override - @Deprecated - public void setStatus(int sc, String sm) { - throw new Error("not supported method"); - } - @Override public int getStatus() { throw new Error("not supported method"); @@ -240,4 +228,9 @@ public Object getAttribute(String key) { public CompletableFuture sendPart(Part body) { throw new Error("not supported method"); } + + @Override + public CompletableFuture sendBuffer(Buffer buffer) { + throw new Error("not supported method"); + } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/BodyBufferSupportImpl.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/BodyBufferSupportImpl.java index 2bab47b3606..eceedf64cc9 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/BodyBufferSupportImpl.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/BodyBufferSupportImpl.java @@ -17,6 +17,7 @@ package org.apache.servicecomb.foundation.vertx.http; +import com.google.common.annotations.VisibleForTesting; import org.apache.servicecomb.foundation.vertx.VertxUtils; import io.vertx.core.buffer.Buffer; @@ -48,12 +49,22 @@ public Buffer getBodyBuffer() { return bodyBuffer; } + @VisibleForTesting + void setBodyBytes(byte[] bodyBytes) { + this.bodyBytes = bodyBytes; + } + @Override public byte[] getBodyBytes() { prepare(); return bodyBytes; } + @VisibleForTesting + void setBodyLength(int bodyLength) { + this.bodyLength = bodyLength; + } + @Override public int getBodyBytesLength() { prepare(); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/DownloadUtils.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/DownloadUtils.java index f37712e34e1..7c9c0fffbfc 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/DownloadUtils.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/DownloadUtils.java @@ -18,7 +18,7 @@ import java.io.IOException; -import javax.servlet.http.Part; +import jakarta.servlet.http.Part; import org.apache.servicecomb.foundation.common.http.HttpUtils; import org.apache.servicecomb.foundation.common.part.FilePartForSend; @@ -44,14 +44,18 @@ public static void prepareDownloadHeader(HttpServletResponseEx responseEx, Part return; } if (responseEx.getHeader(HttpHeaders.CONTENT_TYPE.toString()) == null) { - responseEx.setHeader(HttpHeaders.CONTENT_TYPE.toString(), part.getContentType()); + if (responseEx.getContentType() != null) { + responseEx.setHeader(HttpHeaders.CONTENT_TYPE.toString(), responseEx.getContentType()); + } else { + responseEx.setHeader(HttpHeaders.CONTENT_TYPE.toString(), part.getContentType()); + } } - if (responseEx.getHeader(javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION) == null) { + if (responseEx.getHeader(jakarta.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION) == null) { // to support chinese and space filename in firefox // must use "filename*", (https://tools.ietf.org/html/rtf6266) String encodedFileName = HttpUtils.uriEncodePath(part.getSubmittedFileName()); - responseEx.setHeader(javax.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION, + responseEx.setHeader(jakarta.ws.rs.core.HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + encodedFileName + ";filename*=utf-8''" + encodedFileName); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/EmptyAsyncContext.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/EmptyAsyncContext.java index dd9f6acf0f2..142435ead3e 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/EmptyAsyncContext.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/EmptyAsyncContext.java @@ -17,12 +17,12 @@ package org.apache.servicecomb.foundation.vertx.http; -import javax.servlet.AsyncContext; -import javax.servlet.AsyncListener; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.AsyncListener; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; public class EmptyAsyncContext implements AsyncContext { @Override diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/FileUploadPart.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/FileUploadPart.java index b80ac450d02..9e72d64d289 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/FileUploadPart.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/FileUploadPart.java @@ -18,9 +18,9 @@ package org.apache.servicecomb.foundation.vertx.http; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Files; import org.apache.commons.io.FileUtils; import org.apache.servicecomb.foundation.common.part.AbstractPart; @@ -28,7 +28,7 @@ import io.vertx.ext.web.FileUpload; public class FileUploadPart extends AbstractPart { - private FileUpload fileUpload; + private final FileUpload fileUpload; public FileUploadPart(FileUpload fileUpload) { this.fileUpload = fileUpload; @@ -36,7 +36,7 @@ public FileUploadPart(FileUpload fileUpload) { @Override public InputStream getInputStream() throws IOException { - return new FileInputStream(fileUpload.uploadedFileName()); + return Files.newInputStream(new File(fileUpload.uploadedFileName()).toPath()); } @Override diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletRequestEx.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletRequestEx.java index d2f62f2b0fe..701b117ab6c 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletRequestEx.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletRequestEx.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.foundation.vertx.http; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; public interface HttpServletRequestEx extends HttpServletRequest, BodyBufferSupport { default void setHeader(String name, String value) { diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletResponseEx.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletResponseEx.java index e1c2158d743..a565ed7791e 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletResponseEx.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/HttpServletResponseEx.java @@ -17,13 +17,16 @@ package org.apache.servicecomb.foundation.vertx.http; +import java.io.IOException; +import java.io.PrintWriter; import java.util.concurrent.CompletableFuture; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.Part; -import javax.ws.rs.core.Response.StatusType; - +import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpHeaders; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.Response.StatusType; public interface HttpServletResponseEx extends HttpServletResponse, BodyBufferSupport { StatusType getStatusType(); @@ -34,7 +37,21 @@ public interface HttpServletResponseEx extends HttpServletResponse, BodyBufferSu CompletableFuture sendPart(Part body); + CompletableFuture sendBuffer(Buffer buffer); + default void setChunked(boolean chunked) { setHeader(HttpHeaders.TRANSFER_ENCODING.toString(), HttpHeaders.CHUNKED.toString()); } + + void endResponse() throws IOException; + + @Override + default ServletOutputStream getOutputStream() throws IOException { + throw new IOException("Not allowed"); + } + + @Override + default PrintWriter getWriter() throws IOException { + throw new IOException("Not allowed"); + } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/ReadStreamPart.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/ReadStreamPart.java index 3d1dcd630be..acd2fc1978a 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/ReadStreamPart.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/ReadStreamPart.java @@ -20,18 +20,15 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Function; -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; - -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.foundation.common.http.HttpUtils; import org.apache.servicecomb.foundation.common.part.AbstractPart; import org.apache.servicecomb.foundation.vertx.stream.PumpCommon; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.vertx.core.AsyncResult; import io.vertx.core.Context; +import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; import io.vertx.core.file.AsyncFile; @@ -39,21 +36,23 @@ import io.vertx.core.http.HttpClientResponse; import io.vertx.core.streams.ReadStream; import io.vertx.core.streams.WriteStream; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.HttpHeaders; /** * this is not a really part type, all method extend from AbstractPart is undefined except:
* 1.getContentType
* 2.getSubmittedFileName
* extend from AbstractPart just because want to make it be Part type, - * so that can be sent by + * so that can be sent by * {@link org.apache.servicecomb.foundation.vertx.http.VertxServerResponseToHttpServletResponse#sendPart(Part) VertxServerResponseToHttpServletResponse.sendPart} */ public class ReadStreamPart extends AbstractPart { private static final Logger LOGGER = LoggerFactory.getLogger(ReadStreamPart.class); - private Context context; + private final Context context; - private ReadStream readStream; + private final ReadStream readStream; public ReadStreamPart(Context context, HttpClientResponse httpClientResponse) { this(context, (ReadStream) httpClientResponse); @@ -83,23 +82,21 @@ public ReadStream getReadStream() { } /** - * - * @param writeStream * @return future of save action
* * important: WriteStream did not provide endHandler, so we can not know when will really finished write. * so the return future only means finished read from readStream. */ public CompletableFuture saveToWriteStream(WriteStream writeStream) { - return new PumpCommon().pump(context, readStream, writeStream, null); + return new PumpCommon().pump(readStream, writeStream, null); } public CompletableFuture saveAsBytes() { - return saveAs(buf -> buf.getBytes()); + return saveAs(Buffer::getBytes); } public CompletableFuture saveAsString() { - return saveAs(buf -> buf.toString()); + return saveAs(Buffer::toString); } public CompletableFuture saveAs(Function converter) { @@ -121,8 +118,6 @@ public CompletableFuture saveAs(Function converter) { } /** - * - * @param fileName * @return future of save to file, future complete means write to file finished */ public CompletableFuture saveToFile(String fileName) { @@ -133,9 +128,6 @@ public CompletableFuture saveToFile(String fileName) { } /** - * - * @param file - * @param openOptions * @return future of save to file, future complete means write to file finished */ public CompletableFuture saveToFile(File file, OpenOptions openOptions) { @@ -143,25 +135,24 @@ public CompletableFuture saveToFile(File file, OpenOptions openOptions) { context.runOnContext((v) -> { Vertx vertx = context.owner(); - vertx.fileSystem().open(file.getAbsolutePath(), openOptions, ar -> { - onFileOpened(file, ar, future); - }); + Future openFuture = vertx.fileSystem().open(file.getAbsolutePath(), openOptions); + openFuture.onComplete((s, f) -> onFileOpened(file, s, f, future)); }); return future; } - protected void onFileOpened(File file, AsyncResult ar, CompletableFuture future) { - if (ar.failed()) { - future.completeExceptionally(ar.cause()); + protected void onFileOpened(File file, AsyncFile asyncFile, Throwable failure, CompletableFuture future) { + if (failure != null) { + future.completeExceptionally(failure); return; } - AsyncFile asyncFile = ar.result(); CompletableFuture saveFuture = saveToWriteStream(asyncFile); saveFuture.whenComplete((v, saveException) -> { - asyncFile.close(closeAr -> { - if (closeAr.failed()) { + Future result = asyncFile.close(); + result.onComplete((s, f) -> { + if (f != null) { LOGGER.error("Failed to close file {}.", file); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java index b68a3ca1f61..82b46b47597 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletRequestEx.java @@ -30,24 +30,23 @@ import java.util.Map; import java.util.Map.Entry; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MediaType; - import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; +import com.google.common.annotations.VisibleForTesting; + import io.vertx.core.buffer.Buffer; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import jakarta.ws.rs.HttpMethod; +import jakarta.ws.rs.core.MediaType; public class StandardHttpServletRequestEx extends HttpServletRequestWrapper implements HttpServletRequestEx { - private BodyBufferSupport bodyBuffer = new BodyBufferSupportImpl(); + private final BodyBufferSupport bodyBuffer = new BodyBufferSupportImpl(); private boolean cacheRequest; @@ -66,14 +65,19 @@ public void setCacheRequest(boolean cacheRequest) { this.cacheRequest = cacheRequest; } + @VisibleForTesting + public boolean isCacheRequest() { + return cacheRequest; + } + @Override public ServletInputStream getInputStream() throws IOException { if (this.inputStream == null) { if (cacheRequest) { - byte inputBytes[] = IOUtils.toByteArray(getRequest().getInputStream()); - ByteBuf byteBuf = Unpooled.wrappedBuffer(inputBytes); + byte[] inputBytes = IOUtils.toByteArray(getRequest().getInputStream()); + Buffer byteBuf = Buffer.buffer(inputBytes); this.inputStream = new BufferInputStream(byteBuf); - setBodyBuffer(Buffer.buffer(Unpooled.wrappedBuffer(byteBuf))); + setBodyBuffer(byteBuf); } else { this.inputStream = getRequest().getInputStream(); } @@ -117,7 +121,7 @@ private Map parseParameterMap() { private Map convertListMapToArrayMap(Map> listMap) { Map arrayMap = new HashMap<>(); for (Entry> entry : listMap.entrySet()) { - arrayMap.put(entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()])); + arrayMap.put(entry.getKey(), entry.getValue().toArray(new String[0])); } return arrayMap; } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletResponseEx.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletResponseEx.java index ba1ee636e15..38db248efdb 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletResponseEx.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/StandardHttpServletResponseEx.java @@ -23,23 +23,21 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import javax.servlet.http.Part; -import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.Response.StatusType; - -import org.apache.servicecomb.foundation.common.http.HttpStatus; import org.apache.servicecomb.foundation.vertx.stream.PumpFromPart; import io.vertx.core.Context; import io.vertx.core.Vertx; import io.vertx.core.buffer.Buffer; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.StatusType; public class StandardHttpServletResponseEx extends HttpServletResponseWrapper implements HttpServletResponseEx { - private BodyBufferSupport bodyBuffer = new BodyBufferSupportImpl(); + private final BodyBufferSupport bodyBuffer = new BodyBufferSupportImpl(); - private Map attributes = new HashMap<>(); + private final Map attributes = new HashMap<>(); private StatusType statusType; @@ -67,13 +65,6 @@ public int getBodyBytesLength() { return bodyBuffer.getBodyBytesLength(); } - @SuppressWarnings("deprecation") - @Override - public void setStatus(int sc, String sm) { - super.setStatus(sc, sm); - statusType = new HttpStatus(sc, sm); - } - @Override public void setStatus(int sc) { super.setStatus(sc); @@ -91,11 +82,7 @@ public StatusType getStatusType() { } @Override - public void flushBuffer() throws IOException { - byte[] bytes = getBodyBytes(); - if (bytes != null) { - getOutputStream().write(bytes, 0, getBodyBytesLength()); - } + public void endResponse() throws IOException { super.flushBuffer(); } @@ -130,4 +117,16 @@ public CompletableFuture sendPart(Part part) { Context context = Vertx.currentContext(); return new PumpFromPart(context, part).toOutputStream(outputStream, false); } + + @Override + public CompletableFuture sendBuffer(Buffer buffer) { + CompletableFuture future = new CompletableFuture<>(); + try { + getOutputStream().write(buffer.getBytes(), 0, buffer.length()); + future.complete(null); + } catch (IOException e) { + future.completeExceptionally(e); + } + return future; + } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java index fcb54525ef5..8a54b8d835f 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientRequestToHttpServletRequest.java @@ -20,15 +20,14 @@ import java.util.Collections; import java.util.Enumeration; -import javax.ws.rs.core.HttpHeaders; - import org.apache.servicecomb.foundation.common.http.HttpUtils; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpClientRequest; +import jakarta.ws.rs.core.HttpHeaders; public class VertxClientRequestToHttpServletRequest extends AbstractHttpServletRequest { - private HttpClientRequest clientRequest; + private final HttpClientRequest clientRequest; private String characterEncoding; @@ -42,6 +41,11 @@ public String getRequestURI() { return clientRequest.path(); } + @Override + public StringBuffer getRequestURL() { + return new StringBuffer(clientRequest.path()); + } + @Override public String getQueryString() { return clientRequest.query(); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientResponseToHttpServletResponse.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientResponseToHttpServletResponse.java index 82b84c045e3..da7e532174b 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientResponseToHttpServletResponse.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxClientResponseToHttpServletResponse.java @@ -19,8 +19,8 @@ import java.util.Collection; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response.StatusType; import org.apache.servicecomb.foundation.common.http.HttpStatus; @@ -28,7 +28,7 @@ import io.vertx.core.http.HttpClientResponse; public class VertxClientResponseToHttpServletResponse extends AbstractHttpServletResponse { - private HttpClientResponse clientResponse; + private final HttpClientResponse clientResponse; private StatusType statusType; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java index 392f0a8649e..da55f5ff613 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerRequestToHttpServletRequest.java @@ -27,12 +27,6 @@ import java.util.Set; import java.util.stream.Collectors; -import javax.servlet.AsyncContext; -import javax.servlet.ServletInputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; - import org.apache.servicecomb.foundation.common.http.HttpUtils; import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; import org.slf4j.Logger; @@ -44,6 +38,12 @@ import io.vertx.core.net.SocketAddress; import io.vertx.ext.web.FileUpload; import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.impl.RoutingContextInternal; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.HttpHeaders; // wrap vertx http request to Servlet http request public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletRequest { @@ -51,9 +51,9 @@ public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletR private static final EmptyAsyncContext EMPTY_ASYNC_CONTEXT = new EmptyAsyncContext(); - private RoutingContext context; + private final RoutingContext context; - private HttpServerRequest vertxRequest; + private final HttpServerRequest vertxRequest; private Cookie[] cookies; @@ -61,7 +61,7 @@ public class VertxServerRequestToHttpServletRequest extends AbstractHttpServletR private String path; - private SocketAddress socketAddress; + private final SocketAddress socketAddress; // cache from convert vertx parameters to servlet parameters private Map parameterMap; @@ -77,13 +77,16 @@ public VertxServerRequestToHttpServletRequest(RoutingContext context) { this.context = context; this.vertxRequest = context.request(); this.socketAddress = this.vertxRequest.remoteAddress(); - super.setBodyBuffer(context.getBody()); + super.setBodyBuffer(context.body().buffer()); } @Override public void setBodyBuffer(Buffer bodyBuffer) { super.setBodyBuffer(bodyBuffer); - context.setBody(bodyBuffer); + if (context instanceof RoutingContextInternal) { + RoutingContextInternal contextInternal = (RoutingContextInternal) context; + contextInternal.setBody(bodyBuffer); + } this.inputStream = null; } @@ -95,11 +98,11 @@ public String getContentType() { @Override public Cookie[] getCookies() { if (cookies == null) { - Map vertxCookies = context.cookieMap(); - Cookie tmpCookies[] = new Cookie[vertxCookies.size()]; + Set cookieSet = context.request().cookies(); + Cookie[] tmpCookies = new Cookie[cookieSet.size()]; int idx = 0; - for (io.vertx.core.http.Cookie oneVertxCookie : vertxCookies.values()) { - Cookie cookie = new Cookie(oneVertxCookie.getName(), oneVertxCookie.getValue()); + for (io.vertx.core.http.Cookie vertxCookie : cookieSet) { + Cookie cookie = new Cookie(vertxCookie.getName(), vertxCookie.getValue()); tmpCookies[idx] = cookie; idx++; } @@ -134,7 +137,7 @@ public String[] getParameterValues(String name) { } List paramList = this.vertxRequest.params().getAll(name); - return paramList.toArray(new String[paramList.size()]); + return paramList.toArray(new String[0]); } @Override @@ -143,8 +146,7 @@ public Map getParameterMap() { Map paramMap = new HashMap<>(); MultiMap map = this.vertxRequest.params(); for (String name : map.names()) { - List valueList = map.getAll(name); - paramMap.put(name, map.getAll(name).toArray(new String[valueList.size()])); + paramMap.put(name, map.getAll(name).toArray(new String[0])); } parameterMap = paramMap; } @@ -240,6 +242,14 @@ public String getRequestURI() { return this.path; } + @Override + public StringBuffer getRequestURL() { + if (this.path == null) { + this.path = vertxRequest.path(); + } + return new StringBuffer(this.path); + } + @Override public String getServletPath() { return this.getPathInfo(); @@ -255,10 +265,10 @@ public ServletInputStream getInputStream() { if (inputStream != null) { return inputStream; } - if (context.getBody() == null) { + if (context.body().buffer() == null) { return null; } - inputStream = new BufferInputStream(context.getBody().getByteBuf()); + inputStream = new BufferInputStream(context.body().buffer()); return inputStream; } @@ -284,8 +294,7 @@ public Part getPart(String name) { @Override public Collection getParts() { - Set fileUploads = context.fileUploads(); - return fileUploads.stream().map(FileUploadPart::new).collect(Collectors.toList()); + return context.fileUploads().stream().map(FileUploadPart::new).collect(Collectors.toList()); } public RoutingContext getContext() { diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java index 23e8bb75b15..81785e9698c 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/http/VertxServerResponseToHttpServletResponse.java @@ -17,25 +17,26 @@ package org.apache.servicecomb.foundation.vertx.http; +import java.io.IOException; import java.util.Collection; import java.util.Objects; import java.util.concurrent.CompletableFuture; -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.StatusType; - import org.apache.servicecomb.foundation.common.http.HttpStatus; import org.apache.servicecomb.foundation.vertx.stream.PumpFromPart; import io.vertx.core.Context; import io.vertx.core.Vertx; +import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpServerResponse; +import jakarta.servlet.http.Part; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response.StatusType; public class VertxServerResponseToHttpServletResponse extends AbstractHttpServletResponse { - private Context context; + private final Context context; - private HttpServerResponse serverResponse; + private final HttpServerResponse serverResponse; private StatusType statusType; @@ -52,17 +53,16 @@ public void setContentType(String type) { } @Override - @Deprecated - public void setStatus(int sc, String sm) { - serverResponse.setStatusCode(sc); - serverResponse.setStatusMessage(sm); + public void setContentLength(int len) { + serverResponse.headers().set(HttpHeaders.CONTENT_LENGTH, String.valueOf(len)); } + @Override public void setStatus(int sc) { serverResponse.setStatusCode(sc); } - + @Override public StatusType getStatusType() { if (statusType == null) { @@ -107,7 +107,7 @@ public Collection getHeaderNames() { } @Override - public void flushBuffer() { + public void endResponse() { if (context == Vertx.currentContext()) { internalFlushBuffer(); return; @@ -117,12 +117,10 @@ public void flushBuffer() { } public void internalFlushBuffer() { - if (bodyBuffer == null) { - serverResponse.end(); + if (serverResponse.closed()) { return; } - - serverResponse.end(bodyBuffer); + serverResponse.end(); } @Override @@ -134,6 +132,23 @@ public CompletableFuture sendPart(Part part) { return new PumpFromPart(context, part).toWriteStream(serverResponse, null); } + @Override + public CompletableFuture sendBuffer(Buffer buffer) { + if (serverResponse.closed()) { + return CompletableFuture.failedFuture(new IOException("Response is closed before sending any data. " + + "Maybe client is timeout or check idle connection timeout for provider is properly configured.")); + } + CompletableFuture future = new CompletableFuture<>(); + serverResponse.write(buffer).onComplete(result -> { + if (result.failed()) { + future.completeExceptionally(result.cause()); + } else { + future.complete(null); + } + }); + return future; + } + @Override public void setChunked(boolean chunked) { serverResponse.setChunked(chunked); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultClientMetrics.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultClientMetrics.java index c3893a2e60d..2bc9288857b 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultClientMetrics.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultClientMetrics.java @@ -17,16 +17,14 @@ package org.apache.servicecomb.foundation.vertx.metrics; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetric; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientTaskMetric; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultRequestMetric; - import io.vertx.core.spi.metrics.ClientMetrics; import io.vertx.core.spi.observability.HttpRequest; import io.vertx.core.spi.observability.HttpResponse; +import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetric; +import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultRequestMetric; public class DefaultClientMetrics implements - ClientMetrics { + ClientMetrics { private final DefaultClientEndpointMetric clientEndpointMetric; public DefaultClientMetrics(DefaultClientEndpointMetric clientEndpointMetric) { @@ -37,18 +35,6 @@ public DefaultClientEndpointMetric getClientEndpointMetric() { return this.clientEndpointMetric; } - @Override - public DefaultClientTaskMetric enqueueRequest() { - DefaultClientTaskMetric taskMetric = new DefaultClientTaskMetric(clientEndpointMetric); - taskMetric.enqueueRequest(); - return taskMetric; - } - - @Override - public void dequeueRequest(DefaultClientTaskMetric endpointMetric) { - endpointMetric.dequeueRequest(); - } - @Override public DefaultRequestMetric requestBegin(String uri, HttpRequest request) { DefaultRequestMetric requestMetric = new DefaultRequestMetric(this.clientEndpointMetric); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpClientMetrics.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpClientMetrics.java index 59649948348..1279a4f8566 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpClientMetrics.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultHttpClientMetrics.java @@ -18,7 +18,6 @@ import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetricManager; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientTaskMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultRequestMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultTcpSocketMetric; @@ -26,7 +25,7 @@ import io.vertx.core.spi.metrics.HttpClientMetrics; public class DefaultHttpClientMetrics implements - HttpClientMetrics { + HttpClientMetrics { private static final String PROTOCOL = "http://"; private final DefaultClientEndpointMetricManager clientEndpointMetricManager; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetrics.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetrics.java index ee345ed4e2b..c0b89a42eea 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetrics.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetrics.java @@ -18,23 +18,22 @@ import java.util.Map; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetricManager; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric; - import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.http.HttpClientOptions; import io.vertx.core.http.HttpServerOptions; -import io.vertx.core.metrics.impl.DummyVertxMetrics; import io.vertx.core.net.NetClientOptions; import io.vertx.core.net.NetServerOptions; import io.vertx.core.net.SocketAddress; import io.vertx.core.spi.metrics.HttpClientMetrics; import io.vertx.core.spi.metrics.HttpServerMetrics; import io.vertx.core.spi.metrics.TCPMetrics; +import io.vertx.core.spi.metrics.VertxMetrics; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetricManager; +import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric; -public class DefaultVertxMetrics extends DummyVertxMetrics { +public class DefaultVertxMetrics implements VertxMetrics { // to support listen multiple addresses, must use a map to manage the metric private final Map serverEndpointMetricMap = new ConcurrentHashMapEx<>(); @@ -61,7 +60,7 @@ public Map getServerEndpointMetricMap() { } @Override - public HttpClientMetrics createHttpClientMetrics(HttpClientOptions options) { + public HttpClientMetrics createHttpClientMetrics(HttpClientOptions options) { return new DefaultHttpClientMetrics(clientEndpointMetricManager); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetricsFactory.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetricsFactory.java index dca7cecca92..540a644b1e1 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetricsFactory.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/DefaultVertxMetricsFactory.java @@ -55,7 +55,6 @@ public synchronized VertxMetrics metrics(VertxOptions options) { @Override public MetricsOptions newOptions() { MetricsOptionsEx metricsOptions = new MetricsOptionsEx(); - metricsOptions.setFactory(this); metricsOptions.setEnabled(true); return metricsOptions; } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetric.java index d8d3789a471..ce618078957 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetric.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetric.java @@ -24,12 +24,12 @@ * for one listen address, include multiple httpClient or httpServer */ public class DefaultClientEndpointMetric extends DefaultEndpointMetric { - private LongAdder queue = new LongAdder(); + private final LongAdder queue = new LongAdder(); // control if the metric instance will be expired // all invoker about incRefCount/isExpired, must lock: DefaultClientEndpointMetricManager // decRefCount no need to lock, because that only cause to be expired later. - private long lastNanoTime = System.nanoTime(); + private volatile long lastNanoTime = System.nanoTime(); public DefaultClientEndpointMetric(String address) { super(address); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java index 32ee3617f39..17977a468ca 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientEndpointMetricManager.java @@ -32,7 +32,7 @@ public class DefaultClientEndpointMetricManager { // to avoid save too many endpoint that not exist any more // must check expired periodically - private Map clientEndpointMetricMap = new ConcurrentHashMapEx<>(); + private final Map clientEndpointMetricMap = new ConcurrentHashMapEx<>(); // clientEndpointMetricMap is thread safe // but get/isExpired/remove is not safe @@ -50,7 +50,10 @@ public DefaultClientEndpointMetricManager(MetricsOptionsEx metricsOptionsEx) { public DefaultClientEndpointMetric getOrCreateEndpointMetric(String address) { rwlock.readLock().lock(); try { - return clientEndpointMetricMap.computeIfAbsent(address, DefaultClientEndpointMetric::new); + if (clientEndpointMetricMap.get(address) == null) { + clientEndpointMetricMap.put(address, new DefaultClientEndpointMetric(address)); + } + return clientEndpointMetricMap.get(address); } finally { rwlock.readLock().unlock(); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientTaskMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientTaskMetric.java index e4757e71c02..0b032c5e672 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientTaskMetric.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultClientTaskMetric.java @@ -18,7 +18,7 @@ package org.apache.servicecomb.foundation.vertx.metrics.metric; public class DefaultClientTaskMetric { - private DefaultClientEndpointMetric endpointMetric; + private final DefaultClientEndpointMetric endpointMetric; public DefaultClientTaskMetric(DefaultClientEndpointMetric endpointMetric) { this.endpointMetric = endpointMetric; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java index e30ed96d3b9..f26f33b58de 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultEndpointMetric.java @@ -22,23 +22,23 @@ * for one listen address, include multiple httpClient or httpServer */ public class DefaultEndpointMetric { - private String address; + private final String address; // summary of connect times from boot // by this, we can know how many new connections connected recently - private LongAdder connectCount = new LongAdder(); + private final LongAdder connectCount = new LongAdder(); // summary of disconnect times from boot // by this, we can know how many connections disconnected recently - private LongAdder disconnectCount = new LongAdder(); + private final LongAdder disconnectCount = new LongAdder(); - private LongAdder bytesRead = new LongAdder(); + private final LongAdder bytesRead = new LongAdder(); - private LongAdder bytesWritten = new LongAdder(); + private final LongAdder bytesWritten = new LongAdder(); - private LongAdder requests = new LongAdder(); + private final LongAdder requests = new LongAdder(); - private LongAdder latency = new LongAdder(); + private final LongAdder latency = new LongAdder(); public DefaultEndpointMetric(String address) { this.address = address; diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultServerEndpointMetric.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultServerEndpointMetric.java index 5fe80774f0b..c01af512ee7 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultServerEndpointMetric.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/metrics/metric/DefaultServerEndpointMetric.java @@ -19,7 +19,7 @@ import java.util.concurrent.atomic.LongAdder; public class DefaultServerEndpointMetric extends DefaultEndpointMetric { - private LongAdder rejectByConnectionLimitCount = new LongAdder(); + private final LongAdder rejectByConnectionLimitCount = new LongAdder(); public DefaultServerEndpointMetric(String address) { super(address); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpParser.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpParser.java index 9127300eda9..4e79f69fca3 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpParser.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpParser.java @@ -17,29 +17,19 @@ package org.apache.servicecomb.foundation.vertx.server; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; -import io.netty.buffer.ByteBuf; import io.vertx.core.Handler; import io.vertx.core.buffer.Buffer; import io.vertx.core.parsetools.RecordParser; -/** - * TcpParser - * - * - */ public class TcpParser implements Handler { public static final byte[] TCP_MAGIC; public static final int TCP_HEADER_LENGTH = 23; static { - try { - TCP_MAGIC = "CSE.TCP".getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e); - } + TCP_MAGIC = "CSE.TCP".getBytes(StandardCharsets.UTF_8); } enum ParseStatus { @@ -47,7 +37,7 @@ enum ParseStatus { TCP_PAYLOAD } - private TcpBufferHandler outputHandler; + private final TcpBufferHandler outputHandler; private RecordParser parser; @@ -90,16 +80,17 @@ public boolean firstNEqual(byte[] a, byte[] b, int n) { protected void onParse(Buffer buffer) { switch (status) { case TCP_HEADER: - ByteBuf buf = buffer.getByteBuf(); - if (!firstNEqual(TCP_MAGIC, buf.array(), TCP_MAGIC.length)) { + if (!firstNEqual(TCP_MAGIC, buffer.getBytes(), TCP_MAGIC.length)) { reset(); return; } - buf.skipBytes(TCP_MAGIC.length); - msgId = buf.readLong(); - totalLen = buf.readInt(); - headerLen = buf.readInt(); + int index = TCP_MAGIC.length; + msgId = buffer.getLong(index); + index = index + 8; + totalLen = buffer.getInt(index); + index = index + 4; + headerLen = buffer.getInt(index); if (headerLen > totalLen || headerLen <= 0) { throw new IllegalStateException("possibly attack."); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServer.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServer.java index 58b36c94302..8a960175ad8 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServer.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServer.java @@ -19,8 +19,8 @@ import java.net.InetSocketAddress; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; import org.apache.servicecomb.foundation.ssl.SSLCustom; import org.apache.servicecomb.foundation.ssl.SSLOption; import org.apache.servicecomb.foundation.ssl.SSLOptionFactory; @@ -31,6 +31,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.vertx.core.Future; import io.vertx.core.Vertx; import io.vertx.core.net.NetServer; import io.vertx.core.net.NetServerOptions; @@ -39,7 +40,7 @@ public class TcpServer { private static final Logger LOGGER = LoggerFactory.getLogger(TcpServer.class); - private URIEndpointObject endpointObject; + private final URIEndpointObject endpointObject; public TcpServer(URIEndpointObject endpointObject) { this.endpointObject = endpointObject; @@ -49,10 +50,10 @@ public void init(Vertx vertx, String sslKey, AsyncResultCallback { - LOGGER.error("Unexpected error in server.{}", ExceptionUtils.getExceptionMessageWithoutTrace(e)); - }); + netServer.exceptionHandler( + e -> LOGGER.error("Unexpected error in server.", e)); InetSocketAddress socketAddress = endpointObject.getSocketAddress(); - netServer.listen(socketAddress.getPort(), socketAddress.getHostString(), ar -> { - if (ar.succeeded()) { + Future result = netServer.listen(socketAddress.getPort(), socketAddress.getHostString()); + result.onComplete((s, f) -> { + if (f == null) { callback.success(socketAddress); return; } // 监听失败 - String msg = String.format("listen failed, address=%s", socketAddress.toString()); - callback.fail(new Exception(msg, ar.cause())); + String msg = String.format("listen failed, address=%s", socketAddress); + callback.fail(new Exception(msg, f)); }); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServerConnection.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServerConnection.java index 348a3f8437a..dae3d422161 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServerConnection.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/server/TcpServerConnection.java @@ -36,17 +36,13 @@ public void init(NetSocket netSocket) { LOGGER.info("connect from {}, in thread {}", remoteAddress, Thread.currentThread().getName()); - netSocket.exceptionHandler(e -> { - LOGGER.error("disconected from {}, in thread {}, cause {}", - remoteAddress, - Thread.currentThread().getName(), - e.getMessage()); - }); - netSocket.closeHandler(Void -> { - LOGGER.error("disconected from {}, in thread {}", - remoteAddress, - Thread.currentThread().getName()); - }); + netSocket.exceptionHandler(e -> LOGGER.error("disconnected from {}, in thread {}, cause {}", + remoteAddress, + Thread.currentThread().getName(), + e.getMessage())); + netSocket.closeHandler(Void -> LOGGER.info("disconnected from {}, in thread {}", + remoteAddress, + Thread.currentThread().getName())); netSocket.handler(splitter); } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferInputStream.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferInputStream.java index ee7caa76a17..af0d4acf185 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferInputStream.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferInputStream.java @@ -20,58 +20,69 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; -import javax.servlet.ReadListener; -import javax.servlet.ServletInputStream; - -import io.netty.buffer.ByteBuf; +import io.vertx.core.buffer.Buffer; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletInputStream; public class BufferInputStream extends ServletInputStream { - private ByteBuf byteBuf; + private int readIndex = 0; + + private final Buffer byteBuf; - public BufferInputStream(ByteBuf buffer) { + public BufferInputStream(Buffer buffer) { this.byteBuf = buffer; } @Override public long skip(long len) { int skipLen = Math.min((int) len, available()); - byteBuf.skipBytes(skipLen); + this.readIndex += skipLen; return skipLen; } public byte readByte() { - return byteBuf.readByte(); + int index = readIndex; + readIndex = index + 1; + return byteBuf.getByte(index); } @Override public int read() { - return byteBuf.readUnsignedByte(); + return this.readByte() & 255; } public boolean readBoolean() { - return byteBuf.readBoolean(); + return this.readByte() != 0; } public short readShort() { - return byteBuf.readShort(); + int index = readIndex; + readIndex = index + 2; + return byteBuf.getShort(index); } public int readInt() { - return byteBuf.readInt(); + int index = readIndex; + readIndex = index + 4; + return byteBuf.getInt(index); } public long readLong() { - return byteBuf.readLong(); + int index = readIndex; + readIndex = index + 8; + return byteBuf.getLong(index); } public int getIndex() { - return byteBuf.readerIndex(); + return readIndex; } public String readString() { int length = readInt(); byte[] bytes = new byte[length]; - byteBuf.readBytes(bytes); + int index = readIndex; + readIndex = index + length; + byteBuf.getBytes(index, readIndex, bytes); return new String(bytes, StandardCharsets.UTF_8); } @@ -83,40 +94,47 @@ public int read(byte[] b) { @Override public int read(byte[] b, int off, int len) { int avail = available(); - if (len > avail) { - len = avail; + if (avail <= 0) { + return -1; } if (len == 0) { - return -1; + return 0; } - byteBuf.readBytes(b, off, len); + if (len > avail) { + len = avail; + } + + int index = readIndex; + readIndex = index + len; + + byteBuf.getBytes(index, readIndex, b); return len; } @Override public int available() { - return byteBuf.readableBytes(); + return byteBuf.length() - readIndex; } @Override public void close() { - byteBuf.release(); + // nothing to do } @Override public void reset() throws IOException { - byteBuf.resetReaderIndex(); + readIndex = 0; } - public ByteBuf getByteBuf() { + public Buffer getByteBuf() { return byteBuf; } @Override public boolean isFinished() { - return !byteBuf.isReadable(); + return byteBuf.length() > readIndex; } @Override diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferOutputStream.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferOutputStream.java index 8f00e2cf8aa..42c9b31261d 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferOutputStream.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/BufferOutputStream.java @@ -20,67 +20,46 @@ import java.io.OutputStream; import java.nio.charset.StandardCharsets; -import io.netty.buffer.ByteBuf; import io.vertx.core.buffer.Buffer; /** - * BufferOutputStream - * + * BufferOutputStream. * + * Notice: will not release the underlining ByteBuffer, the user is responsible to release it. */ public class BufferOutputStream extends OutputStream { private static final int DIRECT_BUFFER_SIZE = 1024; - protected ByteBuf byteBuf; - - private boolean needReleaseBuffer; + protected Buffer byteBuf; public BufferOutputStream() { - // TODO:默认大小加配置项 - // TODO:如何与pool配合起来,vertx中默认都是unpool的,我们的阻塞模式下,申请与释放也不在一个线程,估计更用不上? - // 后续通道没问题了,再来验证这个问题 - // this(PooledByteBufAllocator.DEFAULT.directBuffer()); - - // this(PooledByteBufAllocator.DEFAULT.directBuffer(DIRECT_BUFFER_SIZE)); - - // this(UnpooledByteBufAllocator.DEFAULT.directBuffer(DIRECT_BUFFER_SIZE)); - // needReleaseBuffer = false; - - // this(UnpooledByteBufAllocator.DEFAULT.heapBuffer(DIRECT_BUFFER_SIZE)); - - this(Buffer.buffer(DIRECT_BUFFER_SIZE).getByteBuf()); - needReleaseBuffer = false; + this(Buffer.buffer(DIRECT_BUFFER_SIZE)); } - - public BufferOutputStream(ByteBuf buffer) { + public BufferOutputStream(Buffer buffer) { this.byteBuf = buffer; } - public ByteBuf getByteBuf() { - return byteBuf; - } - public Buffer getBuffer() { - return Buffer.buffer(byteBuf); + return byteBuf; } public int length() { - return byteBuf.readableBytes(); + return byteBuf.length(); } public void writeByte(byte value) { - byteBuf.writeByte(value); + byteBuf.appendByte(value); } // 实际是写byte @Override public void write(int byteValue) { - byteBuf.writeByte((byte) byteValue); + byteBuf.appendByte((byte) byteValue); } public void write(boolean value) { - byteBuf.writeBoolean(value); + byteBuf.appendByte(value ? (byte) 1 : (byte) 0); } public void writeInt(int pos, int value) { @@ -88,39 +67,38 @@ public void writeInt(int pos, int value) { } public void writeShort(short value) { - byteBuf.writeShort(value); + byteBuf.appendShort(value); } public void writeInt(int value) { - byteBuf.writeInt(value); + byteBuf.appendInt(value); } public void writeLong(long value) { - byteBuf.writeLong(value); + byteBuf.appendLong(value); } public void writeString(String value) { - byteBuf.writeInt(value.length()); - byteBuf.writeCharSequence(value, StandardCharsets.UTF_8); + writeInt(value.length()); + byteBuf.appendString(value, StandardCharsets.UTF_8.toString()); } + @Override public void write(byte[] b) { write(b, 0, b.length); } @Override public void write(byte[] bytes, int offset, int len) { - byteBuf.writeBytes(bytes, offset, len); + byteBuf.appendBytes(bytes, offset, len); } @Override public void close() { - if (needReleaseBuffer && byteBuf != null) { - byteBuf.release(); - } + // Do no release byteBuf, the target BufferedInputStream will release it. } public int writerIndex() { - return byteBuf.writerIndex(); + return byteBuf.length(); } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/InputStreamToReadStream.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/InputStreamToReadStream.java index 6a0592e680e..580d460e5c0 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/InputStreamToReadStream.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/InputStreamToReadStream.java @@ -19,14 +19,12 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.netty.buffer.Unpooled; -import io.vertx.core.AsyncResult; import io.vertx.core.Context; -import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Promise; import io.vertx.core.buffer.Buffer; @@ -37,11 +35,11 @@ public class InputStreamToReadStream implements ReadStream { public static final int DEFAULT_READ_BUFFER_SIZE = 1024 * 1024; - private Context context; + private final Context context; - private InputStream inputStream; + private final InputStream inputStream; - private boolean closed; + private volatile boolean closed; private boolean paused; @@ -55,7 +53,7 @@ public class InputStreamToReadStream implements ReadStream { private Handler endHandler; - private boolean autoCloseInputStream; + private final boolean autoCloseInputStream; public InputStreamToReadStream(Context context, InputStream inputStream, boolean autoCloseInputStream) { @@ -98,26 +96,29 @@ public synchronized InputStreamToReadStream handler(Handler handler) { } class ReadResult { - int readed; + int read; byte[] bytes = new byte[readBufferSize]; void doRead() throws IOException { - readed = inputStream.read(bytes); + read = inputStream.read(bytes); } Buffer toBuffer() { - return Buffer.buffer(Unpooled.wrappedBuffer(bytes).writerIndex(readed)); + return Buffer.buffer(Arrays.copyOf(bytes, read)); } } private synchronized void doRead() { if (!readInProgress) { readInProgress = true; - - context.executeBlocking(this::readInWorker, - true, - this::afterReadInEventloop); + Promise future = Promise.promise(); + context.executeBlocking(() -> { + readInWorker(future); + return null; + }, + true); + future.future().onComplete(this::afterReadInEventloop); } } @@ -136,15 +137,14 @@ public void handleException(Throwable e) { exceptionHandler.handle(e); } - private synchronized void afterReadInEventloop(AsyncResult ar) { - if (ar.failed()) { - handleException(ar.cause()); + private synchronized void afterReadInEventloop(ReadResult readResult, Throwable failure) { + if (failure != null) { + handleException(failure); return; } readInProgress = false; - ReadResult readResult = ar.result(); - if (readResult.readed < 0) { + if (readResult.read < 0) { handleEnd(); return; } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/OutputStreamToWriteStream.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/OutputStreamToWriteStream.java index 0cbf0ea1252..35681a723a8 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/OutputStreamToWriteStream.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/OutputStreamToWriteStream.java @@ -21,10 +21,10 @@ import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.foundation.common.io.AsyncCloseable; -import io.vertx.core.AsyncResult; import io.vertx.core.Context; import io.vertx.core.Future; import io.vertx.core.Handler; @@ -40,11 +40,11 @@ public class OutputStreamToWriteStream implements WriteStream, AsyncClos private static final int SMALLEST_MAX_BUFFERS = 2; - private OutputStream outputStream; + private final OutputStream outputStream; - private Context context; + private final Context context; - private boolean autoCloseOutputStream; + private final boolean autoCloseOutputStream; private Handler exceptionHandler; @@ -58,9 +58,9 @@ public class OutputStreamToWriteStream implements WriteStream, AsyncClos // buffers.size() need to loop all node, and maybe result is not correct in concurrent condition // we just need to flow control by pump, so use another size - private Queue buffers = new ConcurrentLinkedQueue<>(); + private final Queue buffers = new ConcurrentLinkedQueue<>(); - private int currentBufferCount; + private final AtomicInteger currentBufferCount = new AtomicInteger(); // just indicate if buffers is full, not control add logic // must >= SMALLEST_MAX_BUFFERS @@ -92,22 +92,20 @@ private void handleException(Throwable t) { @Override public synchronized Future write(Buffer data) { Promise result = Promise.promise(); - write(data, ar -> { - if (ar.failed()) { - handleException(ar.cause()); - } - result.complete(); - }); + write(data, result); return result.future(); } - @Override - public void write(Buffer data, Handler> handler) { - currentBufferCount++; + private void write(Buffer data, Promise future) { + currentBufferCount.incrementAndGet(); buffers.add(data); - context.executeBlocking(this::writeInWorker, - true, - handler); + context.executeBlocking( + () -> { + writeInWorker(future); + return null; + }, + true + ); } protected void writeInWorker(Promise future) { @@ -122,12 +120,13 @@ protected void writeInWorker(Promise future) { outputStream.write(buffer.getBytes()); synchronized (OutputStreamToWriteStream.this) { - currentBufferCount--; - Runnable action = (currentBufferCount == 0 && closedDeferred != null) ? closedDeferred : this::checkDrained; + currentBufferCount.decrementAndGet(); + Runnable action = (currentBufferCount.get() == 0 && closedDeferred != null) + ? closedDeferred : this::checkDrained; action.run(); } } catch (IOException e) { - currentBufferCount--; + currentBufferCount.decrementAndGet(); future.fail(e); return; } @@ -135,20 +134,20 @@ protected void writeInWorker(Promise future) { } @Override - public void end(Handler> handler) { - close(); + public Future end() { + return Future.fromCompletionStage(close()); } @Override public WriteStream setWriteQueueMaxSize(int maxSize) { - this.maxBuffers = maxSize < SMALLEST_MAX_BUFFERS ? SMALLEST_MAX_BUFFERS : maxSize; + this.maxBuffers = Math.max(maxSize, SMALLEST_MAX_BUFFERS); this.drainMark = maxBuffers / 2; return this; } @Override public synchronized boolean writeQueueFull() { - return currentBufferCount >= maxBuffers; + return currentBufferCount.get() >= maxBuffers; } @Override @@ -158,7 +157,7 @@ public synchronized WriteStream drainHandler(Handler handler) { } private synchronized void checkDrained() { - if (drainHandler != null && currentBufferCount <= drainMark) { + if (drainHandler != null && currentBufferCount.get() <= drainMark) { Handler handler = drainHandler; drainHandler = null; handler.handle(null); @@ -186,7 +185,7 @@ private synchronized CompletableFuture closeInternal() { closed = true; CompletableFuture future = new CompletableFuture<>(); - if (currentBufferCount == 0) { + if (currentBufferCount.get() == 0) { doClose(future); } else { closedDeferred = () -> doClose(future); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpCommon.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpCommon.java index 5b70f72766e..ae4b5bac727 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpCommon.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpCommon.java @@ -20,27 +20,23 @@ import org.apache.servicecomb.foundation.common.io.AsyncCloseable; -import io.vertx.core.Context; +import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpClientResponse; -import io.vertx.core.streams.Pump; import io.vertx.core.streams.ReadStream; import io.vertx.core.streams.WriteStream; +import io.vertx.core.streams.impl.PipeImpl; public class PumpCommon { /** - * - * @param context - * @param readStream - * @param writeStream * @return future of save action
*

important: *

if writeStream is AsyncCloseable, future means write complete *

if writeStream is not AsyncCloseable, future only means read complete */ @SuppressWarnings("unchecked") - public CompletableFuture pump(Context context, ReadStream readStream, WriteStream writeStream, + public CompletableFuture pump(ReadStream readStream, WriteStream writeStream, Handler throwableHandler) { CompletableFuture readFuture = new CompletableFuture<>(); @@ -62,17 +58,18 @@ public CompletableFuture pump(Context context, ReadStream readStre readFuture.completeExceptionally(e); }); readStream.exceptionHandler(readFuture::completeExceptionally); - // just means read finished, not means write finished - readStream.endHandler(readFuture::complete); - // if readStream(HttpClientResponse) and writeStream(HttpServerResponse) - // belongs to difference eventloop - // maybe will cause deadlock - // if happened, vertx will print deadlock stacks - Pump.pump(readStream, writeStream).start(); - context.runOnContext(v -> readStream.resume()); + Future pipeResult = new PipeImpl<>(readStream).endOnComplete(false).to(writeStream); - if (!AsyncCloseable.class.isInstance(writeStream)) { + pipeResult.onComplete((s) -> readFuture.complete(null), + (f) -> { + if (throwableHandler != null) { + throwableHandler.handle(f); + } + readFuture.completeExceptionally(f); + }); + + if (!(writeStream instanceof AsyncCloseable)) { return readFuture; } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpFromPart.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpFromPart.java index b59d2e089cc..2c5284e12dc 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpFromPart.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/stream/PumpFromPart.java @@ -21,7 +21,7 @@ import java.io.OutputStream; import java.util.concurrent.CompletableFuture; -import javax.servlet.http.Part; +import jakarta.servlet.http.Part; import org.apache.commons.io.IOUtils; import org.apache.servicecomb.foundation.vertx.http.DownloadUtils; @@ -38,9 +38,9 @@ public class PumpFromPart { private static final Logger LOGGER = LoggerFactory.getLogger(PumpFromPart.class); - private Context context; + private final Context context; - private Part part; + private final Part part; public PumpFromPart(Context context, Part part) { this.context = context; @@ -69,7 +69,7 @@ private CompletableFuture> prepareReadStream() { public CompletableFuture toWriteStream(WriteStream writeStream, Handler throwableHandler) { return prepareReadStream() - .thenCompose(readStream -> new PumpCommon().pump(context, readStream, writeStream, throwableHandler)) + .thenCompose(readStream -> new PumpCommon().pump(readStream, writeStream, throwableHandler)) .whenComplete((v, e) -> { if (e != null) { LOGGER.error("to write stream failed.", e); diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpConnection.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpConnection.java index 02d86e220e0..fcc22bfd7c9 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpConnection.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpConnection.java @@ -20,9 +20,6 @@ import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufAllocator; -import io.netty.buffer.CompositeByteBuf; import io.vertx.core.Context; import io.vertx.core.buffer.Buffer; import io.vertx.core.net.NetSocket; @@ -49,9 +46,9 @@ public class TcpConnection { // so this optimization: // 1.avoid vertx's lock // 2.reduce netty's task schedule - private Queue writeQueue = new ConcurrentLinkedQueue<>(); + private final Queue writeQueue = new ConcurrentLinkedQueue<>(); - private AtomicLong writeQueueSize = new AtomicLong(); + private final AtomicLong writeQueueSize = new AtomicLong(); public String getProtocol() { return protocol; @@ -80,10 +77,10 @@ public NetSocket getNetSocket() { public void initNetSocket(NetSocketImpl netSocket) { this.netSocket = netSocket; - this.context = netSocket.getContext(); + this.context = netSocket.context(); } - public void write(ByteBuf buf) { + public void write(Buffer buf) { writeQueue.add(buf); long oldSize = writeQueueSize.getAndIncrement(); if (oldSize == 0) { @@ -93,29 +90,19 @@ public void write(ByteBuf buf) { // notify context thread to write protected void scheduleWrite() { - context.runOnContext(v -> { - writeInContext(); - }); + context.runOnContext(v -> writeInContext()); } protected void writeInContext() { - CompositeByteBuf cbb = ByteBufAllocator.DEFAULT.compositeBuffer(); for (; ; ) { - ByteBuf buf = writeQueue.poll(); + Buffer buf = writeQueue.poll(); if (buf == null) { break; } writeQueueSize.decrementAndGet(); - cbb.addComponent(true, buf); - if (cbb.numComponents() == cbb.maxNumComponents()) { - netSocket.write(Buffer.buffer(cbb)); - cbb = ByteBufAllocator.DEFAULT.compositeBuffer(); - } - } - if (cbb.isReadable()) { - netSocket.write(Buffer.buffer(cbb)); + netSocket.write(buf); } } } diff --git a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpOutputStream.java b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpOutputStream.java index 716d231aad6..8efcef3b6ce 100644 --- a/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpOutputStream.java +++ b/foundations/foundation-vertx/src/main/java/org/apache/servicecomb/foundation/vertx/tcp/TcpOutputStream.java @@ -26,7 +26,7 @@ * */ public class TcpOutputStream extends BufferOutputStream { - private long msgId; + private final long msgId; public TcpOutputStream(long msgId) { super(); diff --git a/foundations/foundation-vertx/src/main/resources/META-INF/spring/cse.bean.xml b/foundations/foundation-vertx/src/main/resources/META-INF/spring/cse.bean.xml deleted file mode 100644 index 908d9ce1944..00000000000 --- a/foundations/foundation-vertx/src/main/resources/META-INF/spring/cse.bean.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - diff --git a/foundations/foundation-vertx/src/test/java/io/vertx/ext/web/impl/TestHttpServerRequestUtils.java b/foundations/foundation-vertx/src/test/java/io/vertx/ext/web/impl/TestHttpServerRequestUtils.java deleted file mode 100644 index f4c91895757..00000000000 --- a/foundations/foundation-vertx/src/test/java/io/vertx/ext/web/impl/TestHttpServerRequestUtils.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 io.vertx.ext.web.impl; - -import org.apache.servicecomb.foundation.vertx.http.VertxServerRequestToHttpServletRequest; -import org.junit.Assert; -import org.junit.Test; - -import io.vertx.core.http.impl.HttpServerRequestInternal; -import io.vertx.ext.web.AllowForwardHeaders; -import io.vertx.ext.web.RoutingContext; -import mockit.Expectations; -import mockit.Mocked; - -// HttpServerRequestWrapper is a package visible class, so put this test in package io.vertx.ext.web.impl -public class TestHttpServerRequestUtils { - @Test - public void testVertxServerRequestToHttpServletRequest(@Mocked RoutingContext context, - @Mocked HttpServerRequestInternal request) { - HttpServerRequestWrapper wrapper = new HttpServerRequestWrapper(request, AllowForwardHeaders.NONE); - new Expectations() { - { - request.scheme(); - result = "http"; - context.request(); - result = wrapper; - } - }; - - VertxServerRequestToHttpServletRequest reqEx = new VertxServerRequestToHttpServletRequest(context, "abc"); - Assert.assertEquals("abc", reqEx.getRequestURI()); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestAddressResolverConfig.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestAddressResolverConfig.java deleted file mode 100644 index 2cf4bb82015..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestAddressResolverConfig.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.foundation.vertx; - -import static org.hamcrest.CoreMatchers.is; - -import java.util.Arrays; -import java.util.Collections; - -import org.apache.commons.configuration.Configuration; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import io.vertx.core.dns.AddressResolverOptions; -import mockit.Expectations; -import mockit.Mocked; - -public class TestAddressResolverConfig { - - @BeforeClass - public static void classSetup() { - ArchaiusUtils.resetConfig(); - } - - @AfterClass - public static void classTeardown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testGetResolverFromResource(@Mocked Configuration finalConfig) { - ArchaiusUtils.resetConfig(); - ArchaiusUtils.setProperty("addressResolver.servers", "8.8.8.8,8.8.4.4"); - new Expectations() { - { - finalConfig.getStringArray("addressResolver.servers"); - result = new String[] {"6.6.6.6", "6.6.4.4"}; - finalConfig.getStringArray("addressResolver.searchDomains"); - result = new String[] {"default.svc.local.cluster"}; - finalConfig.getInteger("addressResolver.queryTimeout", null); - result = 2000; - finalConfig.getInteger("addressResolver.maxQueries", null); - result = -2; - } - }; - AddressResolverOptions resolverOptions = AddressResolverConfig.getAddressResover("test", finalConfig); - Assert.assertThat(resolverOptions.getServers(), is(Arrays.asList("6.6.6.6", "6.6.4.4"))); - Assert.assertThat(resolverOptions.getSearchDomains(), - is(Collections.singletonList("default.svc.local.cluster"))); - Assert.assertEquals(resolverOptions.getQueryTimeout(), - 2000); - Assert.assertNotEquals(resolverOptions.getMaxQueries(), - -2); - } - - @Test - public void testGetResolver() { - ArchaiusUtils.resetConfig(); - ArchaiusUtils.setProperty("addressResolver.servers", "8.8.8.8,8.8.4.4"); - ArchaiusUtils.setProperty("addressResolver.optResourceEnabled", true); - ArchaiusUtils.setProperty("addressResolver.cacheMinTimeToLive", 0); - ArchaiusUtils.setProperty("addressResolver.cacheMaxTimeToLive", 10000); - ArchaiusUtils.setProperty("addressResolver.cacheNegativeTimeToLive", 0); - ArchaiusUtils.setProperty("addressResolver.queryTimeout", 1000); - ArchaiusUtils.setProperty("addressResolver.maxQueries", 3); - ArchaiusUtils.setProperty("addressResolver.test.maxQueries", 3); - ArchaiusUtils.setProperty("addressResolver.rdFlag", true); - ArchaiusUtils.setProperty("addressResolver.searchDomains", - "default.svc.local.cluster,svc.local.cluster,local.cluster"); - ArchaiusUtils.setProperty("addressResolver.test.searchDomains", - "test.svc.local.cluster,svc.local.cluster,local.cluster"); - ArchaiusUtils.setProperty("addressResolver.ndots", 3); - ArchaiusUtils.setProperty("addressResolver.rotateServers", true); - AddressResolverOptions aroc = AddressResolverConfig.getAddressResover("test"); - Assert.assertThat(aroc.getServers(), is(Arrays.asList("8.8.8.8", "8.8.4.4"))); - Assert.assertThat(aroc.getSearchDomains(), - is(Arrays.asList("test.svc.local.cluster", "svc.local.cluster", "local.cluster"))); - AddressResolverOptions aroc1 = AddressResolverConfig.getAddressResover("test1"); - Assert.assertThat(aroc1.getSearchDomains(), - is(Arrays.asList("default.svc.local.cluster", "svc.local.cluster", "local.cluster"))); - Assert.assertTrue(aroc.isOptResourceEnabled()); - } - - @Test - public void testGetResolverDefault() { - ArchaiusUtils.resetConfig(); - ArchaiusUtils.setProperty("addressResolver.servers", "8.8.8.8,8.8.4.4"); - ArchaiusUtils.setProperty("addressResolver.maxQueries", 3); - ArchaiusUtils.setProperty("addressResolver.rdFlag", false); - AddressResolverOptions resolverOptions = AddressResolverConfig.getAddressResover("test"); - Assert.assertThat(resolverOptions.getServers(), is(Arrays.asList("8.8.8.8", "8.8.4.4"))); - Assert.assertEquals(3, resolverOptions.getMaxQueries()); - Assert.assertEquals(Integer.MAX_VALUE, resolverOptions.getCacheMaxTimeToLive()); - Assert.assertFalse(resolverOptions.isOptResourceEnabled()); - Assert.assertNull(resolverOptions.getSearchDomains()); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSharedVertxFactory.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSharedVertxFactory.java index a27c47f150c..8e77a256251 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSharedVertxFactory.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSharedVertxFactory.java @@ -16,15 +16,34 @@ */ package org.apache.servicecomb.foundation.vertx; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +import io.vertx.core.impl.SysProps; public class TestSharedVertxFactory { + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach + public void setUp() { + Mockito.when(environment.getProperty("servicecomb.transport.eventloop.size", int.class, -1)) + .thenReturn(-1); + Mockito.when(environment.getProperty(SysProps.DISABLE_FILE_CP_RESOLVING.name, boolean.class, true)) + .thenReturn(true); + LegacyPropertyFactory.setEnvironment(environment); + } + + @Test public void getTransportVertx() { - Assert.assertNotNull(SharedVertxFactory.getSharedVertx()); - Assert.assertSame(SharedVertxFactory.getSharedVertx(), SharedVertxFactory.getSharedVertx()); + Assertions.assertNotNull(SharedVertxFactory.getSharedVertx(environment)); + Assertions.assertSame(SharedVertxFactory.getSharedVertx(environment), + SharedVertxFactory.getSharedVertx(environment)); - SharedVertxFactory.getSharedVertx().close(); + SharedVertxFactory.getSharedVertx(environment).close(); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleBodyHandler.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleBodyHandler.java index 0012e73cfed..8aec460f9c0 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleBodyHandler.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleBodyHandler.java @@ -17,12 +17,12 @@ package org.apache.servicecomb.foundation.vertx; -import javax.ws.rs.core.Response.Status; +import jakarta.ws.rs.core.Response.Status; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; import io.vertx.core.MultiMap; @@ -63,7 +63,7 @@ protected boolean contentTypeSupported(String contentType) { } }; instance.handle(context); - Assert.assertTrue(instance.checkContentType(context)); + Assertions.assertTrue(instance.checkContentType(context)); } @Test @@ -75,6 +75,6 @@ protected boolean contentTypeSupported(String contentType) { } }; instance.handle(context); - Assert.assertFalse(instance.checkContentType(context)); + Assertions.assertFalse(instance.checkContentType(context)); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleJsonObject.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleJsonObject.java index 8f621f7c40c..d0a51708073 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleJsonObject.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestSimpleJsonObject.java @@ -16,8 +16,8 @@ */ package org.apache.servicecomb.foundation.vertx; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestSimpleJsonObject { @Test @@ -26,12 +26,12 @@ public void testPutObject() { SimpleJsonObject json = new SimpleJsonObject(); json.put("k", value); - Assert.assertSame(value, json.getValue("k")); + Assertions.assertSame(value, json.getValue("k")); } @Test public void testCopy() { SimpleJsonObject json = new SimpleJsonObject(); - Assert.assertSame(json, json.copy()); + Assertions.assertSame(json, json.copy()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestStream.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestStream.java index 9057056149e..af3e2078c90 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestStream.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestStream.java @@ -19,10 +19,9 @@ import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -import io.netty.buffer.ByteBuf; import io.vertx.core.buffer.Buffer; public class TestStream { @@ -31,17 +30,21 @@ public class TestStream { @Test public void testBufferInputStream() { - ByteBuf obuf = Buffer.buffer(DIRECT_BUFFER_SIZE).getByteBuf(); - obuf.writeBytes(("testss").getBytes()); + Buffer obuf = Buffer.buffer(DIRECT_BUFFER_SIZE); + obuf.appendBytes(("tests1").getBytes()); @SuppressWarnings("resource") BufferInputStream oBufferInputStream = new BufferInputStream(obuf); - Assert.assertNotEquals(1234, oBufferInputStream.skip(0)); - Assert.assertNotEquals(obuf.readByte(), oBufferInputStream.readByte()); - Assert.assertEquals(obuf.readByte() + 1, oBufferInputStream.read()); - Assert.assertEquals(obuf.readBoolean(), oBufferInputStream.readBoolean()); - Assert.assertEquals(obuf.readerIndex(), oBufferInputStream.getIndex()); - Assert.assertEquals(obuf.readableBytes(), oBufferInputStream.available()); - Assert.assertNotEquals(null, oBufferInputStream.read(("test").getBytes())); + + byte test = oBufferInputStream.readByte(); + Assertions.assertEquals((byte) 't', test); + Assertions.assertEquals((byte) 'e', oBufferInputStream.read()); + + Assertions.assertEquals(2, oBufferInputStream.skip(2)); + Assertions.assertEquals((byte) 's', oBufferInputStream.read()); + Assertions.assertTrue(oBufferInputStream.readBoolean()); + + Assertions.assertEquals(6, oBufferInputStream.getIndex()); + Assertions.assertEquals(0, oBufferInputStream.available()); } @Test @@ -49,9 +52,14 @@ public void testBufferOutputStream() { @SuppressWarnings({"resource"}) BufferOutputStream oBufferOutputStream = new BufferOutputStream(); oBufferOutputStream.writeString("test"); - Assert.assertNotEquals(null, oBufferOutputStream.writerIndex()); oBufferOutputStream.write(1); oBufferOutputStream.write(true); - Assert.assertEquals(true, (1 < oBufferOutputStream.length())); + Assertions.assertTrue((1 < oBufferOutputStream.length())); + + @SuppressWarnings("resource") + BufferInputStream oBufferInputStream = new BufferInputStream(oBufferOutputStream.getBuffer()); + Assertions.assertEquals("test", oBufferInputStream.readString()); + Assertions.assertEquals(1, oBufferInputStream.readByte()); + Assertions.assertTrue(oBufferInputStream.readBoolean()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxTLSBuilder.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxTLSBuilder.java index 95a2cd167c3..f99abd698df 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxTLSBuilder.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxTLSBuilder.java @@ -17,14 +17,15 @@ package org.apache.servicecomb.foundation.vertx; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.ssl.SSLCustom; import org.apache.servicecomb.foundation.ssl.SSLOption; import org.apache.servicecomb.foundation.ssl.SSLOptionFactory; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; +import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import io.vertx.core.http.ClientAuth; import io.vertx.core.http.HttpClientOptions; @@ -33,31 +34,28 @@ import mockit.MockUp; public class TestVertxTLSBuilder { - @BeforeClass - public static void classSetup() { - ArchaiusUtils.resetConfig(); - } + Environment environment = Mockito.mock(Environment.class); - @AfterClass - public static void classTeardown() { - ArchaiusUtils.resetConfig(); + @Before + public void setUp() { + LegacyPropertyFactory.setEnvironment(environment); } @Test - public void testbuildHttpServerOptions() { - SSLOption option = SSLOption.buildFromYaml("rest.provider"); + public void testBuildHttpServerOptions() { + SSLOption option = SSLOption.build("rest.provider", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpServerOptions serverOptions = new HttpServerOptions(); VertxTLSBuilder.buildNetServerOptions(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.getClientAuth(), ClientAuth.REQUEST); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertEquals(serverOptions.getClientAuth(), ClientAuth.REQUEST); } @Test - public void testbuildHttpClientOptions_sslKey_noFactory() { + public void testBuildHttpClientOptions_sslKey_noFactory() { HttpClientOptions clientOptions = new HttpClientOptions(); VertxTLSBuilder.buildHttpClientOptions("notExist", clientOptions); - Assert.assertTrue(clientOptions.isSsl()); + Assertions.assertTrue(clientOptions.isSsl()); } public static class SSLOptionFactoryForTest implements SSLOptionFactory { @@ -77,50 +75,51 @@ public SSLOption createSSLOption() { } @Test - public void testbuildHttpClientOptions_ssl_withFactory() { - ArchaiusUtils.setProperty("ssl.exist.sslOptionFactory", SSLOptionFactoryForTest.class.getName()); + public void testBuildHttpClientOptions_ssl_withFactory() { + Mockito.when(environment.getProperty("ssl.exist.sslOptionFactory")) + .thenReturn(SSLOptionFactoryForTest.class.getName()); HttpClientOptions clientOptions = new HttpClientOptions(); VertxTLSBuilder.buildHttpClientOptions("exist", clientOptions); - Assert.assertTrue(clientOptions.isSsl()); - Assert.assertTrue(clientOptions.isVerifyHost()); + Assertions.assertTrue(clientOptions.isSsl()); + Assertions.assertTrue(clientOptions.isVerifyHost()); } @Test - public void testbuildHttpClientOptions() { - SSLOption option = SSLOption.buildFromYaml("rest.consumer"); + public void testBuildHttpClientOptions() { + SSLOption option = SSLOption.build("rest.consumer", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpClientOptions serverOptions = new HttpClientOptions(); VertxTLSBuilder.buildHttpClientOptions(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.isTrustAll(), true); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertTrue(serverOptions.isTrustAll()); } @Test - public void testbuildClientOptionsBase() { - SSLOption option = SSLOption.buildFromYaml("rest.consumer"); + public void testBuildClientOptionsBase() { + SSLOption option = SSLOption.build("rest.consumer", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpClientOptions serverOptions = new HttpClientOptions(); VertxTLSBuilder.buildClientOptionsBase(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.isTrustAll(), true); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertTrue(serverOptions.isTrustAll()); } @Test - public void testbuildClientOptionsBaseFileNull() { - SSLOption option = SSLOption.buildFromYaml("rest.consumer"); + public void testBuildClientOptionsBaseFileNull() { + SSLOption option = SSLOption.build("rest.consumer", environment); option.setKeyStore(null); option.setTrustStore(null); option.setCrl(null); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpClientOptions serverOptions = new HttpClientOptions(); VertxTLSBuilder.buildClientOptionsBase(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.isTrustAll(), true); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertTrue(serverOptions.isTrustAll()); } @Test - public void testbuildClientOptionsBaseAuthPeerFalse() { - SSLOption option = SSLOption.buildFromYaml("rest.consumer"); + public void testBuildClientOptionsBaseAuthPeerFalse() { + SSLOption option = SSLOption.build("rest.consumer", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpClientOptions serverOptions = new HttpClientOptions(); new MockUp() { @@ -131,13 +130,13 @@ public boolean isAuthPeer() { } }; VertxTLSBuilder.buildClientOptionsBase(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.isTrustAll(), true); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertTrue(serverOptions.isTrustAll()); } @Test - public void testbuildClientOptionsBaseSTORE_JKS() { - SSLOption option = SSLOption.buildFromYaml("rest.consumer"); + public void testBuildClientOptionsBaseSTORE_JKS() { + SSLOption option = SSLOption.build("rest.consumer", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpClientOptions serverOptions = new HttpClientOptions(); new MockUp() { @@ -148,13 +147,13 @@ public String getKeyStoreType() { } }; VertxTLSBuilder.buildClientOptionsBase(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.isTrustAll(), true); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertTrue(serverOptions.isTrustAll()); } @Test - public void testbuildClientOptionsBaseSTORE_PKCS12() { - SSLOption option = SSLOption.buildFromYaml("rest.consumer"); + public void testBuildClientOptionsBaseSTORE_PKCS12() { + SSLOption option = SSLOption.build("rest.consumer", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpClientOptions serverOptions = new HttpClientOptions(); new MockUp() { @@ -165,13 +164,13 @@ public String getTrustStoreType() { } }; VertxTLSBuilder.buildClientOptionsBase(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.isTrustAll(), true); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertTrue(serverOptions.isTrustAll()); } @Test - public void testbuildHttpServerOptionsRequest() { - SSLOption option = SSLOption.buildFromYaml("rest.provider"); + public void testBuildHttpServerOptionsRequest() { + SSLOption option = SSLOption.build("rest.provider", environment); SSLCustom custom = SSLCustom.createSSLCustom(option.getSslCustomClass()); HttpServerOptions serverOptions = new HttpServerOptions(); @@ -183,7 +182,7 @@ public boolean isAuthPeer() { } }; VertxTLSBuilder.buildNetServerOptions(option, custom, serverOptions); - Assert.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); - Assert.assertEquals(serverOptions.getClientAuth(), ClientAuth.REQUEST); + Assertions.assertEquals(serverOptions.getEnabledSecureTransportProtocols().toArray().length, 1); + Assertions.assertEquals(serverOptions.getClientAuth(), ClientAuth.REQUEST); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxUtils.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxUtils.java index 56106970fee..9f966cbcbde 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxUtils.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/TestVertxUtils.java @@ -25,22 +25,35 @@ import org.apache.commons.io.FileUtils; import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.buffer.Buffer; -import io.vertx.core.file.impl.FileResolver; +import io.vertx.core.impl.SysProps; public class TestVertxUtils { + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach + public void setUp() { + Mockito.when(environment.getProperty(SysProps.DISABLE_FILE_CP_RESOLVING.name, boolean.class, true)) + .thenReturn(true); + + LegacyPropertyFactory.setEnvironment(environment); + } + @Test public void testGetOrCreateVertx() throws InterruptedException { - Vertx vertx = VertxUtils.getOrCreateVertxByName("ut", null); + Vertx vertx = VertxUtils.getOrCreateVertxByName("ut", null, null); Holder name = new Holder<>(); CountDownLatch latch = new CountDownLatch(1); @@ -50,35 +63,32 @@ public void testGetOrCreateVertx() throws InterruptedException { }); latch.await(); - Assert.assertEquals(name.value, "ut-vert.x-eventloop-thread-0"); + Assertions.assertEquals(name.value, "ut-vert.x-eventloop-thread-0"); VertxUtils.blockCloseVertxByName("ut"); } @Test public void testCreateVertxWithFileCPResolving() { - // Prepare - ArchaiusUtils.resetConfig(); - // create .vertx folder - ArchaiusUtils.setProperty(FileResolver.DISABLE_CP_RESOLVING_PROP_NAME, false); + Mockito.when(environment.getProperty(SysProps.DISABLE_FILE_CP_RESOLVING.name, boolean.class, true)) + .thenReturn(false); deleteCacheFile(); - VertxUtils.getOrCreateVertxByName("testCreateVertxWithFileCPResolvingFalse", null); - Assert.assertTrue(isCacheFileExists()); + VertxUtils.getOrCreateVertxByName("testCreateVertxWithFileCPResolvingFalse", null, null); + Assertions.assertTrue(isCacheFileExists()); VertxUtils.blockCloseVertxByName("testCreateVertxWithFileCPResolvingFalse"); // don't create .vertx folder deleteCacheFile(); - Assert.assertFalse(isCacheFileExists()); - ArchaiusUtils.setProperty(FileResolver.DISABLE_CP_RESOLVING_PROP_NAME, true); - VertxUtils.getOrCreateVertxByName("testCreateVertxWithFileCPResolvingTrue", null); - Assert.assertFalse(isCacheFileExists()); + Assertions.assertFalse(isCacheFileExists()); + Mockito.when(environment.getProperty(SysProps.DISABLE_FILE_CP_RESOLVING.name, boolean.class, true)) + .thenReturn(true); + VertxUtils.getOrCreateVertxByName("testCreateVertxWithFileCPResolvingTrue", null, null); + Assertions.assertFalse(isCacheFileExists()); VertxUtils.blockCloseVertxByName("testCreateVertxWithFileCPResolvingTrue"); - - ArchaiusUtils.resetConfig(); } private void deleteCacheFile() { - String cacheDirBase = System.getProperty(FileResolver.CACHE_DIR_BASE_PROP_NAME, + String cacheDirBase = System.getProperty(SysProps.FILE_CACHE_DIR.name, System.getProperty("java.io.tmpdir", ".")); File folder = new File(cacheDirBase); File[] files = folder.listFiles(); @@ -90,7 +100,7 @@ private void deleteCacheFile() { } private boolean isCacheFileExists() { - String cacheDirBase = System.getProperty(FileResolver.CACHE_DIR_BASE_PROP_NAME, + String cacheDirBase = System.getProperty(SysProps.FILE_CACHE_DIR.name, System.getProperty("java.io.tmpdir", ".")); File folder = new File(cacheDirBase); File[] files = folder.listFiles(); @@ -104,8 +114,8 @@ private boolean isCacheFileExists() { @Test public void testVertxUtilsInitNullOptions() { - Vertx vertx = VertxUtils.init(null, null); - Assert.assertNotEquals(null, vertx); + Vertx vertx = VertxUtils.init(null, null, null); + Assertions.assertNotEquals(null, vertx); VertxUtils.blockCloseVertx(vertx); } @@ -113,19 +123,20 @@ public void testVertxUtilsInitNullOptions() { public void testVertxUtilsInitWithOptions() { VertxOptions oOptions = new VertxOptions(); - Vertx vertx = VertxUtils.init(null, oOptions); - Assert.assertNotEquals(null, vertx); + Vertx vertx = VertxUtils.init(null, oOptions, null); + Assertions.assertNotEquals(null, vertx); VertxUtils.blockCloseVertx(vertx); } @Test public void testgetBytesFastBufferInputStream() throws IOException { byte[] bytes = new byte[] {1}; - ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); + Buffer byteBuf = Buffer.buffer(bytes); try (BufferInputStream inputStream = new BufferInputStream(byteBuf)) { byte[] result = VertxUtils.getBytesFast(inputStream); - Assert.assertSame(bytes, result); + Assertions.assertEquals(bytes.length, result.length); + Assertions.assertEquals(bytes[0], result[0]); } } @@ -135,7 +146,7 @@ public void testgetBytesFastNormalInputStream() throws IOException { try (InputStream inputStream = new ByteArrayInputStream(bytes)) { byte[] result = VertxUtils.getBytesFast(inputStream); - Assert.assertEquals(1, result[0]); + Assertions.assertEquals(1, result[0]); } } @@ -145,7 +156,7 @@ public void testgetBytesFastBuffer() { buffer.appendByte((byte) 1); byte[] result = VertxUtils.getBytesFast(buffer); - Assert.assertEquals(1, result[0]); + Assertions.assertEquals(1, result[0]); } @Test @@ -154,17 +165,17 @@ public void testgetBytesFastByteBufHasArray() { ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes); byte[] result = VertxUtils.getBytesFast(byteBuf); - Assert.assertSame(bytes, result); + Assertions.assertSame(bytes, result); } @Test public void testgetBytesFastByteBufCopy() { ByteBuf byteBuf = Unpooled.directBuffer(); byteBuf.writeByte(1); - Assert.assertFalse(byteBuf.hasArray()); + Assertions.assertFalse(byteBuf.hasArray()); byte[] result = VertxUtils.getBytesFast(byteBuf); - Assert.assertEquals(1, result[0]); + Assertions.assertEquals(1, result[0]); byteBuf.release(); } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java index dc86d9bafeb..c42c3f3360e 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientPoolManager.java @@ -22,10 +22,11 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import io.vertx.core.Context; import io.vertx.core.Vertx; @@ -49,7 +50,7 @@ public class TestClientPoolManager { List pools; - Map contextMap = new HashMap<>(); + Map contextMap = new HashMap<>(); @Mocked Context context; @@ -61,13 +62,13 @@ public void setup() { pools = Deencapsulation.getField(poolMgr, "pools"); new MockUp(context) { @Mock - void put(String key, Object value) { + void put(Object key, Object value) { contextMap.put(key, value); } @SuppressWarnings("unchecked") @Mock - T get(String key) { + T get(Object key) { return (T) contextMap.get(key); } @@ -92,9 +93,9 @@ public void createClientPool(@Mocked HttpClientWithContext pool) { } }; - Assert.assertSame(pool, poolMgr.createClientPool(context)); - Assert.assertSame(pool, context.get(id)); - Assert.assertThat(pools, Matchers.contains(pool)); + Assertions.assertSame(pool, poolMgr.createClientPool(context)); + Assertions.assertSame(pool, context.get(id)); + MatcherAssert.assertThat(pools, Matchers.contains(pool)); } @Test @@ -108,8 +109,8 @@ public void findClientPool_sync(@Mocked HttpClientWithContext pool1, @Mocked Htt } }; - Assert.assertSame(pool1, poolMgr.findClientPool(true)); - Assert.assertSame(pool2, poolMgr.findClientPool(false)); + Assertions.assertSame(pool1, poolMgr.findClientPool(true)); + Assertions.assertSame(pool2, poolMgr.findClientPool(false)); } @Test @@ -124,9 +125,9 @@ long getId() { } }; - Assert.assertSame(pool1, poolMgr.findThreadBindClientPool()); + Assertions.assertSame(pool1, poolMgr.findThreadBindClientPool()); // find again, get the same result - Assert.assertSame(pool1, poolMgr.findThreadBindClientPool()); + Assertions.assertSame(pool1, poolMgr.findThreadBindClientPool()); new MockUp() { @Mock @@ -135,29 +136,29 @@ long getId() { } }; - Assert.assertSame(pool2, poolMgr.findThreadBindClientPool()); + Assertions.assertSame(pool2, poolMgr.findThreadBindClientPool()); // find again, get the same result - Assert.assertSame(pool2, poolMgr.findThreadBindClientPool()); + Assertions.assertSame(pool2, poolMgr.findThreadBindClientPool()); } @Test public void findByContext_reactive() { - HttpClientWithContext notMatchPool = new HttpClientWithContext(null, null); - pools.add(notMatchPool); + HttpClientWithContext notMatchPool1 = new HttpClientWithContext(null, null); + HttpClientWithContext notMatchPool2 = new HttpClientWithContext(null, null); + pools.add(notMatchPool1); + pools.add(notMatchPool2); new Expectations() { { - factory.createClientPool(context); - result = new HttpClientWithContext(null, null); Vertx.currentContext(); result = context; } }; + context.put(id, notMatchPool2); - HttpClientWithContext result = poolMgr.findByContext(); - Assert.assertNotSame(notMatchPool, result); + Assertions.assertSame(notMatchPool2, poolMgr.findByContext()); // find again, get the same result - Assert.assertSame(result, poolMgr.findByContext()); + Assertions.assertSame(notMatchPool2, poolMgr.findByContext()); } @Test @@ -177,10 +178,10 @@ public void findByContext_wrongContext_reverse() { AtomicInteger reactiveNextIndex = Deencapsulation.getField(poolMgr, "reactiveNextIndex"); reactiveNextIndex.set(Integer.MAX_VALUE); // each time invoke find, reactiveNextIndex will inc 1 - Assert.assertSame(pool2, poolMgr.findByContext()); - Assert.assertSame(pool1, poolMgr.findByContext()); - Assert.assertSame(pool2, poolMgr.findByContext()); - Assert.assertSame(pool1, poolMgr.findByContext()); + Assertions.assertSame(pool2, poolMgr.findByContext()); + Assertions.assertSame(pool1, poolMgr.findByContext()); + Assertions.assertSame(pool2, poolMgr.findByContext()); + Assertions.assertSame(pool1, poolMgr.findByContext()); } @Test @@ -195,7 +196,7 @@ public void findByContext_normalThread() { } }; - Assert.assertSame(pool, poolMgr.findByContext()); + Assertions.assertSame(pool, poolMgr.findByContext()); } @Test @@ -212,7 +213,7 @@ public void findByContext_otherVertx(@Mocked VertxImpl otherVertx, @Mocked Conte } }; - Assert.assertSame(pool, poolMgr.findByContext()); + Assertions.assertSame(pool, poolMgr.findByContext()); } @Test @@ -231,6 +232,6 @@ public void findByContext_worker(@Mocked Context workerContext) { } }; - Assert.assertSame(pool, poolMgr.findByContext()); + Assertions.assertSame(pool, poolMgr.findByContext()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientVerticle.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientVerticle.java index 6f76372398b..197eb9f1f34 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientVerticle.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/TestClientVerticle.java @@ -20,7 +20,6 @@ import org.apache.servicecomb.foundation.vertx.SimpleJsonObject; import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; -import org.junit.Assert; import org.junit.Test; import io.vertx.core.Context; @@ -29,6 +28,7 @@ import mockit.Mock; import mockit.MockUp; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestClientVerticle { ClientVerticle clientVerticle = new ClientVerticle<>(); @@ -56,6 +56,6 @@ HttpClientWithContext createClientPool(Context context) { clientVerticle.start(); - Assert.assertEquals(1, count.get()); + Assertions.assertEquals(1, count.get()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/http/TestHttpClientPoolFactory.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/http/TestHttpClientPoolFactory.java deleted file mode 100644 index eb63c1db8d7..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/http/TestHttpClientPoolFactory.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.foundation.vertx.client.http; - -import org.junit.Assert; -import org.junit.Test; - -import io.vertx.core.http.HttpClient; -import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.impl.ContextInternal; -import io.vertx.core.impl.VertxImpl; -import io.vertx.core.impl.VertxInternal; -import mockit.Expectations; -import mockit.Mocked; - -public class TestHttpClientPoolFactory { - private HttpClientOptions httpClientOptions = new HttpClientOptions(); - - HttpClientPoolFactory factory = new HttpClientPoolFactory(httpClientOptions); - - @Test - public void createClientPool(@Mocked VertxInternal vertx, @Mocked ContextInternal context, - @Mocked HttpClient httpClient) { - new Expectations(VertxImpl.class) { - { - context.owner(); - result = vertx; - vertx.createHttpClient(httpClientOptions); - result = httpClient; - } - }; - HttpClientWithContext pool = factory.createClientPool(context); - - Assert.assertSame(context, pool.context()); - Assert.assertSame(httpClient, pool.getHttpClient()); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestAbstractTcpClientPoolFactory.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestAbstractTcpClientPoolFactory.java index 9c7dc36f917..dd01fdab11f 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestAbstractTcpClientPoolFactory.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestAbstractTcpClientPoolFactory.java @@ -16,17 +16,17 @@ */ package org.apache.servicecomb.foundation.vertx.client.tcp; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; +import org.junit.jupiter.api.Assertions; import io.vertx.core.Context; import io.vertx.core.Vertx; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestAbstractTcpClientPoolFactory { - private TcpClientConfig normalClientConfig = new TcpClientConfig(); + private final TcpClientConfig normalClientConfig = new TcpClientConfig(); - private TcpClientConfig sslClientConfig = new TcpClientConfig(); + private final TcpClientConfig sslClientConfig = new TcpClientConfig(); TcpClientPoolFactory factory = new TcpClientPoolFactory(normalClientConfig, sslClientConfig); @@ -37,7 +37,7 @@ public void createClientPool() { Mockito.when(context.owner()).thenReturn(vertx); TcpClientConnectionPool pool = factory.createClientPool(context); - Assert.assertSame(normalClientConfig, pool.netClientWrapper.getClientConfig(false)); - Assert.assertSame(sslClientConfig, pool.netClientWrapper.getClientConfig(true)); + Assertions.assertSame(normalClientConfig, pool.netClientWrapper.getClientConfig(false)); + Assertions.assertSame(sslClientConfig, pool.netClientWrapper.getClientConfig(true)); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestNetClientWrapper.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestNetClientWrapper.java deleted file mode 100644 index 312946da19d..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestNetClientWrapper.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.foundation.vertx.client.tcp; - - -import java.util.ArrayList; -import java.util.List; - -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import io.vertx.core.AsyncResult; -import io.vertx.core.Handler; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.core.net.NetClient; -import io.vertx.core.net.NetSocket; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestNetClientWrapper { - @Mocked - Vertx vertx; - - @Mocked - TcpClientConfig normalClientConfig; - - @Mocked - NetClient normalNetClient; - - @Mocked - TcpClientConfig sslClientConfig; - - @Mocked - NetClient sslNetClient; - - NetClientWrapper netClientWrapper; - - @Before - public void setup() { - new Expectations() { - { - vertx.createNetClient(normalClientConfig); - result = normalNetClient; - vertx.createNetClient(sslClientConfig); - result = sslNetClient; - } - }; - netClientWrapper = new NetClientWrapper(vertx, normalClientConfig, sslClientConfig); - } - - @Test - public void getClientConfig() { - Assert.assertSame(normalClientConfig, netClientWrapper.getClientConfig(false)); - Assert.assertSame(sslClientConfig, netClientWrapper.getClientConfig(true)); - } - - @Test - public void connect(@Mocked NetSocket normalSocket, @Mocked NetSocket sslSocket) { - int port = 8000; - String host = "localhost"; - - Promise promiseConnect = Promise.promise(); - new MockUp(normalNetClient) { - @Mock - NetClient connect(int port, String host, Handler> connectHandler) { - promiseConnect.complete(normalSocket); - connectHandler.handle(promiseConnect.future()); - return null; - } - }; - - Promise sslPromiseConnect = Promise.promise(); - new MockUp(sslNetClient) { - @Mock - NetClient connect(int port, String host, Handler> connectHandler) { - sslPromiseConnect.complete(sslSocket); - connectHandler.handle(sslPromiseConnect.future()); - return null; - } - }; - - List socks = new ArrayList<>(); - netClientWrapper.connect(false, port, host, asyncSocket -> { - socks.add(asyncSocket.result()); - }); - netClientWrapper.connect(true, port, host, asyncSocket -> { - socks.add(asyncSocket.result()); - }); - - Assert.assertThat(socks, Matchers.contains(normalSocket, sslSocket)); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConfig.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConfig.java index 558eb513d49..b7a2f50d048 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConfig.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConfig.java @@ -17,16 +17,16 @@ package org.apache.servicecomb.foundation.vertx.client.tcp; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestTcpClientConfig { @Test public void testTcpClientConfig() { TcpClientConfig config = new TcpClientConfig(); - Assert.assertEquals(config.getMsLoginTimeout(), 30000); - Assert.assertEquals(config.isSsl(), false); + Assertions.assertEquals(config.getMsLoginTimeout(), 30000); + Assertions.assertFalse(config.isSsl()); config.setMsLoginTimeout(500); - Assert.assertEquals(config.getMsLoginTimeout(), 500); + Assertions.assertEquals(config.getMsLoginTimeout(), 500); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnection.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnection.java index f6c13ee52f2..f072d962000 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnection.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnection.java @@ -23,16 +23,16 @@ import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; import org.apache.servicecomb.foundation.vertx.client.tcp.TcpClientConnection.Status; import org.apache.servicecomb.foundation.vertx.tcp.TcpOutputStream; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.vertx.core.AsyncResult; import io.vertx.core.Context; +import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Promise; +import io.vertx.core.buffer.Buffer; import io.vertx.core.net.NetSocket; import io.vertx.core.net.impl.NetSocketImpl; import mockit.Deencapsulation; @@ -68,20 +68,20 @@ public void setup() { @Test public void localSupportLogin() { - Assert.assertFalse(tcpClientConnection.isLocalSupportLogin()); + Assertions.assertFalse(tcpClientConnection.isLocalSupportLogin()); tcpClientConnection.setLocalSupportLogin(true); - Assert.assertTrue(tcpClientConnection.isLocalSupportLogin()); + Assertions.assertTrue(tcpClientConnection.isLocalSupportLogin()); } @Test public void createLogin() { - Assert.assertNull(tcpClientConnection.createLogin()); + Assertions.assertNull(tcpClientConnection.createLogin()); } @Test public void onLoginResponse_buffer() { - Assert.assertTrue(tcpClientConnection.onLoginResponse(null)); + Assertions.assertTrue(tcpClientConnection.onLoginResponse(null)); } @Test @@ -90,14 +90,14 @@ public void send_inWorkingStatus(@Mocked AbstractTcpClientPackage tcpClientPacka Deencapsulation.setField(tcpClientConnection, "status", Status.WORKING); long msgId = 1; - ByteBuf byteBuf = Unpooled.buffer(); + Buffer byteBuf = Buffer.buffer(); new Expectations(tcpClientConnection) { { tcpClientPackage.getMsgId(); result = msgId; tcpClientPackage.createStream(); result = tcpOutputStream; - tcpOutputStream.getByteBuf(); + tcpOutputStream.getBuffer(); result = byteBuf; } }; @@ -110,9 +110,9 @@ void runOnContext(Handler action) { tcpClientConnection.send(tcpClientPackage, ar -> { }); - Assert.assertSame(byteBuf, writeQueue.poll()); - Assert.assertNull(writeQueue.poll()); - Assert.assertEquals(Status.WORKING, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertSame(byteBuf, writeQueue.poll()); + Assertions.assertNull(writeQueue.poll()); + Assertions.assertEquals(Status.WORKING, Deencapsulation.getField(tcpClientConnection, "status")); } @Test @@ -134,9 +134,9 @@ void runOnContext(Handler action) { tcpClientConnection.send(tcpClientPackage, ar -> { }); - Assert.assertSame(tcpClientPackage, packageQueue.poll()); - Assert.assertNull(packageQueue.poll()); - Assert.assertEquals(Status.CONNECTING, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertSame(tcpClientPackage, packageQueue.poll()); + Assertions.assertNull(packageQueue.poll()); + Assertions.assertEquals(Status.CONNECTING, Deencapsulation.getField(tcpClientConnection, "status")); } @Test @@ -159,9 +159,9 @@ void runOnContext(Handler action) { tcpClientConnection.send(tcpClientPackage, ar -> { }); - Assert.assertSame(tcpClientPackage, packageQueue.poll()); - Assert.assertNull(packageQueue.poll()); - Assert.assertEquals(Status.TRY_LOGIN, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertSame(tcpClientPackage, packageQueue.poll()); + Assertions.assertNull(packageQueue.poll()); + Assertions.assertEquals(Status.TRY_LOGIN, Deencapsulation.getField(tcpClientConnection, "status")); } @Test @@ -172,7 +172,7 @@ public void send_disconnectedToWorking(@Mocked AbstractTcpClientPackage tcpClien { tcpClientPackage.getMsgId(); result = msgId; - tcpClientConnection.write((ByteBuf) any); + tcpClientConnection.write((Buffer) any); } }; new MockUp(context) { @@ -185,9 +185,9 @@ void runOnContext(Handler action) { tcpClientConnection.send(tcpClientPackage, ar -> { }); - Assert.assertNull(writeQueue.poll()); - Assert.assertNull(packageQueue.poll()); - Assert.assertEquals(Status.WORKING, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertNull(writeQueue.poll()); + Assertions.assertNull(packageQueue.poll()); + Assertions.assertEquals(Status.WORKING, Deencapsulation.getField(tcpClientConnection, "status")); } @Test @@ -195,16 +195,16 @@ public void connect_success(@Mocked NetSocketImpl netSocket) { Promise promise = Promise.promise(); new MockUp(netClientWrapper) { @Mock - void connect(boolean ssl, int port, String host, Handler> connectHandler) { + public Future connect(boolean ssl, int port, String host) { promise.complete(netSocket); - connectHandler.handle(promise.future()); + return promise.future(); } }; tcpClientConnection.connect(); - Assert.assertSame(netSocket, tcpClientConnection.getNetSocket()); - Assert.assertEquals(Status.WORKING, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertSame(netSocket, tcpClientConnection.getNetSocket()); + Assertions.assertEquals(Status.WORKING, Deencapsulation.getField(tcpClientConnection, "status")); } @Test @@ -216,16 +216,16 @@ public void connect_failed() { RuntimeException error = new RuntimeExceptionWithoutStackTrace(); new MockUp(netClientWrapper) { @Mock - void connect(boolean ssl, int port, String host, Handler> connectHandler) { + public Future connect(boolean ssl, int port, String host) { promise.fail(error); - connectHandler.handle(promise.future()); + return promise.future(); } }; tcpClientConnection.connect(); - Assert.assertEquals(Status.DISCONNECTED, Deencapsulation.getField(tcpClientConnection, "status")); - Assert.assertEquals(0, requestMap.size()); + Assertions.assertEquals(Status.DISCONNECTED, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertEquals(0, requestMap.size()); } @Test @@ -234,9 +234,9 @@ public void onClosed(@Mocked NetSocketImpl netSocket) { })); tcpClientConnection.initNetSocket(netSocket); - Deencapsulation.invoke(tcpClientConnection, "onClosed", new Class[] {Void.class}, new Object[] {null}); - Assert.assertEquals(Status.DISCONNECTED, Deencapsulation.getField(tcpClientConnection, "status")); - Assert.assertEquals(0, requestMap.size()); + tcpClientConnection.onClosed(null); + Assertions.assertEquals(Status.DISCONNECTED, Deencapsulation.getField(tcpClientConnection, "status")); + Assertions.assertEquals(0, requestMap.size()); } @Test @@ -249,11 +249,9 @@ public void onReply_notExist() { public void on_exist() { long msgId = 1L; AtomicInteger count = new AtomicInteger(); - requestMap.put(msgId, new TcpRequest(10, ar -> { - count.incrementAndGet(); - })); + requestMap.put(msgId, new TcpRequest(10, ar -> count.incrementAndGet())); tcpClientConnection.onReply(msgId, null, null); - Assert.assertEquals(1, count.get()); + Assertions.assertEquals(1, count.get()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnectionPool.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnectionPool.java deleted file mode 100644 index f13e59ff75f..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/client/tcp/TestTcpClientConnectionPool.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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.foundation.vertx.client.tcp; - -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import io.vertx.core.impl.ContextInternal; -import mockit.Mocked; - -public class TestTcpClientConnectionPool { - @Mocked - ContextInternal context; - - @Mocked - NetClientWrapper netClientWrapper; - - TcpClientConnectionPool pool; - - @Before - public void setup() { - pool = new TcpClientConnectionPool(context, netClientWrapper); - } - - @Test - public void create() { - Assert.assertThat(pool.create("rest://localhost:8765"), Matchers.instanceOf(TcpClientConnection.class)); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletRequest.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletRequest.java index c25b38930a1..de7c8dfa1db 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletRequest.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletRequest.java @@ -17,18 +17,14 @@ package org.apache.servicecomb.foundation.vertx.http; -import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.util.Collections; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; - +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; + +import jakarta.servlet.http.HttpServletRequest; public class TestAbstractHttpServletRequest { HttpServletRequest request = new AbstractHttpServletRequest() { @@ -39,478 +35,395 @@ public void testAttribute() { String key = "a1"; String value = "abc"; request.setAttribute(key, value); - Assert.assertSame(value, request.getAttribute(key)); - Assert.assertThat(Collections.list(request.getAttributeNames()), Matchers.contains(key)); + Assertions.assertSame(value, request.getAttribute(key)); + MatcherAssert.assertThat(Collections.list(request.getAttributeNames()), Matchers.contains(key)); request.setAttribute("a2", "v"); - Assert.assertThat(Collections.list(request.getAttributeNames()), Matchers.contains(key, "a2")); + MatcherAssert.assertThat(Collections.list(request.getAttributeNames()), Matchers.containsInAnyOrder(key, "a2")); request.removeAttribute(key); - Assert.assertNull(request.getAttribute(key)); + Assertions.assertNull(request.getAttribute(key)); } - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - private void setExceptionExpected() { - expectedException.expect(Error.class); - expectedException.expectMessage(Matchers.is("not supported method")); + private void checkError(Error error) { + Assertions.assertEquals("not supported method", error.getMessage()); } @Test public void testGetCharacterEncoding() { - setExceptionExpected(); - - request.getCharacterEncoding(); + Error error = Assertions.assertThrows(Error.class, () -> request.getCharacterEncoding()); + checkError(error); } @Test - public void testSetCharacterEncoding() throws UnsupportedEncodingException { - setExceptionExpected(); - - request.setCharacterEncoding(""); + public void testSetCharacterEncoding() { + Error error = Assertions.assertThrows(Error.class, () -> request.setCharacterEncoding("")); + checkError(error); } @Test public void testGetContentLength() { - setExceptionExpected(); - - request.getContentLength(); + Error error = Assertions.assertThrows(Error.class, () -> request.getContentLength()); + checkError(error); } @Test public void testGetContentLengthLong() { - setExceptionExpected(); - - request.getContentLengthLong(); + Error error = Assertions.assertThrows(Error.class, () -> request.getContentLengthLong()); + checkError(error); } @Test public void testGetContentType() { - setExceptionExpected(); - - request.getContentType(); + Error error = Assertions.assertThrows(Error.class, () -> request.getContentType()); + checkError(error); } @Test - public void testGetInputStream() throws IOException { - setExceptionExpected(); - - request.getInputStream(); + public void testGetInputStream() { + Error error = Assertions.assertThrows(Error.class, () -> request.getInputStream()); + checkError(error); } @Test public void testGetParameter() { - setExceptionExpected(); - - request.getParameter(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getParameter("")); + checkError(error); } @Test public void testGetParameterNames() { - setExceptionExpected(); - - request.getParameterNames(); + Error error = Assertions.assertThrows(Error.class, () -> request.getParameterNames()); + checkError(error); } @Test public void testGetParameterValues() { - setExceptionExpected(); - - request.getParameterValues(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getParameterValues("")); + checkError(error); } @Test public void testGetParameterMap() { - setExceptionExpected(); - - request.getParameterMap(); + Error error = Assertions.assertThrows(Error.class, () -> request.getParameterMap()); + checkError(error); } @Test public void testGetProtocol() { - setExceptionExpected(); - - request.getProtocol(); + Error error = Assertions.assertThrows(Error.class, () -> request.getProtocol()); + checkError(error); } @Test public void testGetScheme() { - setExceptionExpected(); - - request.getScheme(); + Error error = Assertions.assertThrows(Error.class, () -> request.getScheme()); + checkError(error); } @Test public void testGetServerName() { - setExceptionExpected(); - - request.getServerName(); + Error error = Assertions.assertThrows(Error.class, () -> request.getServerName()); + checkError(error); } @Test public void testGetServerPort() { - setExceptionExpected(); - - request.getServerPort(); + Error error = Assertions.assertThrows(Error.class, () -> request.getServerPort()); + checkError(error); } @Test - public void testGetReader() throws IOException { - setExceptionExpected(); - - request.getReader(); + public void testGetReader() { + Error error = Assertions.assertThrows(Error.class, () -> request.getReader()); + checkError(error); } @Test public void testGetRemoteAddr() { - setExceptionExpected(); - - request.getRemoteAddr(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRemoteAddr()); + checkError(error); } @Test public void testGetRemoteHost() { - setExceptionExpected(); - - request.getRemoteHost(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRemoteHost()); + checkError(error); } @Test public void testGetLocale() { - setExceptionExpected(); - - request.getLocale(); + Error error = Assertions.assertThrows(Error.class, () -> request.getLocale()); + checkError(error); } @Test public void testGetLocales() { - setExceptionExpected(); - - request.getLocales(); + Error error = Assertions.assertThrows(Error.class, () -> request.getLocales()); + checkError(error); } @Test public void testIsSecure() { - setExceptionExpected(); - - request.isSecure(); + Error error = Assertions.assertThrows(Error.class, () -> request.isSecure()); + checkError(error); } @Test public void testGetRequestDispatcher() { - setExceptionExpected(); - - request.getRequestDispatcher(""); - } - - @SuppressWarnings("deprecation") - @Test - public void testGetRealPath() { - setExceptionExpected(); - - request.getRealPath(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getRequestDispatcher("")); + checkError(error); } @Test public void testGetRemotePort() { - setExceptionExpected(); - - request.getRemotePort(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRemotePort()); + checkError(error); } @Test public void testGetLocalName() { - setExceptionExpected(); - - request.getLocalName(); + Error error = Assertions.assertThrows(Error.class, () -> request.getLocalName()); + checkError(error); } @Test public void testGetLocalAddr() { - setExceptionExpected(); - - request.getLocalAddr(); + Error error = Assertions.assertThrows(Error.class, () -> request.getLocalAddr()); + checkError(error); } @Test public void testGetLocalPort() { - setExceptionExpected(); - - request.getLocalPort(); + Error error = Assertions.assertThrows(Error.class, () -> request.getLocalPort()); + checkError(error); } @Test public void testGetServletContext() { - setExceptionExpected(); - - request.getServletContext(); + Error error = Assertions.assertThrows(Error.class, () -> request.getServletContext()); + checkError(error); } @Test public void testStartAsync() { - setExceptionExpected(); - - request.startAsync(); + Error error = Assertions.assertThrows(Error.class, () -> request.startAsync()); + checkError(error); } @Test public void testStartAsyncWithParam() { - setExceptionExpected(); - - request.startAsync(null, null); + Error error = Assertions.assertThrows(Error.class, () -> request.startAsync(null, null)); + checkError(error); } @Test public void testIsAsyncStarted() { - setExceptionExpected(); - - request.isAsyncStarted(); + Error error = Assertions.assertThrows(Error.class, () -> request.isAsyncStarted()); + checkError(error); } @Test public void testIsAsyncSupported() { - setExceptionExpected(); - - request.isAsyncSupported(); + Error error = Assertions.assertThrows(Error.class, () -> request.isAsyncSupported()); + checkError(error); } @Test public void testGetAsyncContext() { - setExceptionExpected(); - - request.getAsyncContext(); + Error error = Assertions.assertThrows(Error.class, () -> request.getAsyncContext()); + checkError(error); } @Test public void testGetDispatcherType() { - setExceptionExpected(); - - request.getDispatcherType(); + Error error = Assertions.assertThrows(Error.class, () -> request.getDispatcherType()); + checkError(error); } @Test public void testGetAuthType() { - setExceptionExpected(); - - request.getAuthType(); + Error error = Assertions.assertThrows(Error.class, () -> request.getAuthType()); + checkError(error); } @Test public void testGetCookies() { - setExceptionExpected(); - - request.getCookies(); + Error error = Assertions.assertThrows(Error.class, () -> request.getCookies()); + checkError(error); } @Test public void testGetDateHeader() { - setExceptionExpected(); - - request.getDateHeader(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getDateHeader("")); + checkError(error); } @Test public void testGetHeader() { - setExceptionExpected(); - - request.getHeader(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getHeader("")); + checkError(error); } @Test public void testGetHeaders() { - setExceptionExpected(); - - request.getHeaders(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getHeaders("")); + checkError(error); } @Test public void testGetHeaderNames() { - setExceptionExpected(); - - request.getHeaderNames(); + Error error = Assertions.assertThrows(Error.class, () -> request.getHeaderNames()); + checkError(error); } @Test public void testGetIntHeader() { - setExceptionExpected(); - - request.getIntHeader(""); + Error error = Assertions.assertThrows(Error.class, () -> request.getIntHeader("")); + checkError(error); } @Test public void testGetMethod() { - setExceptionExpected(); - - request.getMethod(); + Error error = Assertions.assertThrows(Error.class, () -> request.getMethod()); + checkError(error); } @Test public void testGetPathInfo() { - setExceptionExpected(); - - request.getPathInfo(); + Error error = Assertions.assertThrows(Error.class, () -> request.getPathInfo()); + checkError(error); } @Test public void testGetPathTranslated() { - setExceptionExpected(); - - request.getPathTranslated(); + Error error = Assertions.assertThrows(Error.class, () -> request.getPathTranslated()); + checkError(error); } @Test public void testGetContextPath() { - setExceptionExpected(); - - request.getContextPath(); + Error error = Assertions.assertThrows(Error.class, () -> request.getContextPath()); + checkError(error); } @Test public void testGetQueryString() { - setExceptionExpected(); - - request.getQueryString(); + Error error = Assertions.assertThrows(Error.class, () -> request.getQueryString()); + checkError(error); } @Test public void testGetRemoteUser() { - setExceptionExpected(); - - request.getRemoteUser(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRemoteUser()); + checkError(error); } @Test public void testIsUserInRole() { - setExceptionExpected(); - - request.isUserInRole(""); + Error error = Assertions.assertThrows(Error.class, () -> request.isUserInRole("")); + checkError(error); } @Test public void testGetUserPrincipal() { - setExceptionExpected(); - - request.getUserPrincipal(); + Error error = Assertions.assertThrows(Error.class, () -> request.getUserPrincipal()); + checkError(error); } @Test public void testGetRequestedSessionId() { - setExceptionExpected(); - - request.getRequestedSessionId(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRequestedSessionId()); + checkError(error); } @Test public void testGetRequestURI() { - setExceptionExpected(); - - request.getRequestURI(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRequestURI()); + checkError(error); } @Test public void testGetRequestURL() { - setExceptionExpected(); - - request.getRequestURL(); + Error error = Assertions.assertThrows(Error.class, () -> request.getRequestURL()); + checkError(error); } @Test public void testGetServletPath() { - setExceptionExpected(); - - request.getServletPath(); + Error error = Assertions.assertThrows(Error.class, () -> request.getServletPath()); + checkError(error); } @Test public void testGetSessionWithParam() { - setExceptionExpected(); - - request.getSession(true); + Error error = Assertions.assertThrows(Error.class, () -> request.getSession(true)); + checkError(error); } @Test public void testGetSession() { - setExceptionExpected(); - - request.getSession(); + Error error = Assertions.assertThrows(Error.class, () -> request.getSession()); + checkError(error); } @Test public void testChangeSessionId() { - setExceptionExpected(); - - request.changeSessionId(); + Error error = Assertions.assertThrows(Error.class, () -> request.changeSessionId()); + checkError(error); } @Test public void testIsRequestedSessionIdValid() { - setExceptionExpected(); - - request.isRequestedSessionIdValid(); + Error error = Assertions.assertThrows(Error.class, () -> request.isRequestedSessionIdValid()); + checkError(error); } @Test public void testIsRequestedSessionIdFromCookie() { - setExceptionExpected(); - - request.isRequestedSessionIdFromCookie(); + Error error = Assertions.assertThrows(Error.class, () -> request.isRequestedSessionIdFromCookie()); + checkError(error); } @Test public void testIsRequestedSessionIdFromURL() { - setExceptionExpected(); - - request.isRequestedSessionIdFromURL(); - } - - @SuppressWarnings("deprecation") - @Test - public void testIsRequestedSessionIdFromUrl() { - setExceptionExpected(); - - request.isRequestedSessionIdFromUrl(); + Error error = Assertions.assertThrows(Error.class, () -> request.isRequestedSessionIdFromURL()); + checkError(error); } @Test - public void testAuthenticate() throws IOException, ServletException { - setExceptionExpected(); - - request.authenticate(null); + public void testAuthenticate() { + Error error = Assertions.assertThrows(Error.class, () -> request.authenticate(null)); + checkError(error); } @Test - public void testLogin() throws ServletException { - setExceptionExpected(); - - request.login(null, null); + public void testLogin() { + Error error = Assertions.assertThrows(Error.class, () -> request.login(null, null)); + checkError(error); } @Test - public void testLogout() throws ServletException { - setExceptionExpected(); - - request.logout(); + public void testLogout() { + Error error = Assertions.assertThrows(Error.class, () -> request.logout()); + checkError(error); } @Test - public void testGetParts() throws IOException, ServletException { - setExceptionExpected(); - - request.getParts(); + public void testGetParts() { + Error error = Assertions.assertThrows(Error.class, () -> request.getParts()); + checkError(error); } @Test - public void testGetPart() throws IOException, ServletException { - setExceptionExpected(); - - request.getPart(""); + public void testGetPart() { + Error error = Assertions.assertThrows(Error.class, () -> request.getPart("")); + checkError(error); } @Test - public void testUpgrade() throws IOException, ServletException { - setExceptionExpected(); - - request.upgrade(null); + public void testUpgrade() { + Error error = Assertions.assertThrows(Error.class, () -> request.upgrade(null)); + checkError(error); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletResponse.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletResponse.java index ec884eeea8c..053cc56e7de 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletResponse.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestAbstractHttpServletResponse.java @@ -17,306 +17,236 @@ package org.apache.servicecomb.foundation.vertx.http; -import java.io.IOException; - -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestAbstractHttpServletResponse { - @Rule - public ExpectedException expectedException = ExpectedException.none(); HttpServletResponseEx response = new AbstractHttpServletResponse() { }; - private void setExceptionExpected() { - expectedException.expect(Error.class); - expectedException.expectMessage(Matchers.is("not supported method")); + private void checkError(Error error) { + Assertions.assertEquals("not supported method", error.getMessage()); } @Test public void testGetCharacterEncoding() { - setExceptionExpected(); - - response.getCharacterEncoding(); + Error error = Assertions.assertThrows(Error.class, () -> response.getCharacterEncoding()); + checkError(error); } @Test public void testGetContentType() { - setExceptionExpected(); - - response.getContentType(); + Error error = Assertions.assertThrows(Error.class, () -> response.getContentType()); + checkError(error); } @Test - public void testGetOutputStream() throws IOException { - setExceptionExpected(); - - response.getOutputStream(); + public void testGetOutputStream() { + Error error = Assertions.assertThrows(Error.class, () -> response.getOutputStream()); + checkError(error); } @Test - public void testGetWriter() throws IOException { - setExceptionExpected(); - - response.getWriter(); + public void testGetWriter() { + Error error = Assertions.assertThrows(Error.class, () -> response.getWriter()); + checkError(error); } @Test public void testSetCharacterEncoding() { - setExceptionExpected(); - - response.setCharacterEncoding(""); + Error error = Assertions.assertThrows(Error.class, () -> response.setCharacterEncoding("")); + checkError(error); } @Test public void testSetContentLength() { - setExceptionExpected(); - - response.setContentLength(0); + Error error = Assertions.assertThrows(Error.class, () -> response.setContentLength(0)); + checkError(error); } @Test public void testSetContentLengthLong() { - setExceptionExpected(); - - response.setContentLengthLong(0); + Error error = Assertions.assertThrows(Error.class, () -> response.setContentLengthLong(0)); + checkError(error); } @Test public void testSetContentType() { - setExceptionExpected(); - - response.setContentType(""); + Error error = Assertions.assertThrows(Error.class, () -> response.setContentType("")); + checkError(error); } @Test public void testSetBufferSize() { - setExceptionExpected(); - - response.setBufferSize(0); + Error error = Assertions.assertThrows(Error.class, () -> response.setBufferSize(0)); + checkError(error); } @Test public void testGetBufferSize() { - setExceptionExpected(); - - response.getBufferSize(); + Error error = Assertions.assertThrows(Error.class, () -> response.getBufferSize()); + checkError(error); } @Test - public void testFlushBuffer() throws IOException { - setExceptionExpected(); - - response.flushBuffer(); + public void testFlushBuffer() { + Assertions.assertDoesNotThrow(() -> response.flushBuffer()); } @Test public void testResetBuffer() { - setExceptionExpected(); - - response.resetBuffer(); + Error error = Assertions.assertThrows(Error.class, () -> response.resetBuffer()); + checkError(error); } @Test public void testIsCommitted() { - setExceptionExpected(); - - response.isCommitted(); + Error error = Assertions.assertThrows(Error.class, () -> response.isCommitted()); + checkError(error); } @Test public void testReset() { - setExceptionExpected(); - - response.reset(); + Error error = Assertions.assertThrows(Error.class, () -> response.reset()); + checkError(error); } @Test public void testSetLocale() { - setExceptionExpected(); - - response.setLocale(null); + Error error = Assertions.assertThrows(Error.class, () -> response.setLocale(null)); + checkError(error); } @Test public void testGetLocale() { - setExceptionExpected(); - - response.getLocale(); + Error error = Assertions.assertThrows(Error.class, () -> response.getLocale()); + checkError(error); } @Test public void testAddCookie() { - setExceptionExpected(); - - response.addCookie(null); + Error error = Assertions.assertThrows(Error.class, () -> response.addCookie(null)); + checkError(error); } @Test public void testContainsHeader() { - setExceptionExpected(); - - response.containsHeader(null); + Error error = Assertions.assertThrows(Error.class, () -> response.containsHeader(null)); + checkError(error); } @Test public void testEncodeURL() { - setExceptionExpected(); - - response.encodeURL(null); + Error error = Assertions.assertThrows(Error.class, () -> response.encodeURL(null)); + checkError(error); } @Test public void testEncodeRedirectURL() { - setExceptionExpected(); - - response.encodeRedirectURL(null); - } - - @SuppressWarnings("deprecation") - @Test - public void testEncodeUrl() { - setExceptionExpected(); - - response.encodeUrl(null); + Error error = Assertions.assertThrows(Error.class, () -> response.encodeRedirectURL(null)); + checkError(error); } - @SuppressWarnings("deprecation") @Test - public void testEncodeRedirectUrl() { - setExceptionExpected(); - - response.encodeRedirectUrl(null); + public void testSendErrorScAndMsg() { + Error error = Assertions.assertThrows(Error.class, () -> response.sendError(0, null)); + checkError(error); } @Test - public void testSendErrorScAndMsg() throws IOException { - setExceptionExpected(); - - response.sendError(0, null); + public void testSendErrorSc() { + Error error = Assertions.assertThrows(Error.class, () -> response.sendError(0)); + checkError(error); } @Test - public void testSendErrorSc() throws IOException { - setExceptionExpected(); - - response.sendError(0); - } - - @Test - public void testSendRedirect() throws IOException { - setExceptionExpected(); - - response.sendRedirect(null); + public void testSendRedirect() { + Error error = Assertions.assertThrows(Error.class, () -> response.sendRedirect(null)); + checkError(error); } @Test public void testSetDateHeader() { - setExceptionExpected(); - - response.setDateHeader(null, 0); + Error error = Assertions.assertThrows(Error.class, () -> response.setDateHeader(null, 0)); + checkError(error); } @Test public void testAddDateHeader() { - setExceptionExpected(); - - response.addDateHeader(null, 0); + Error error = Assertions.assertThrows(Error.class, () -> response.addDateHeader(null, 0)); + checkError(error); } @Test public void testSetHeader() { - setExceptionExpected(); - - response.setHeader(null, null); + Error error = Assertions.assertThrows(Error.class, () -> response.setHeader(null, null)); + checkError(error); } @Test public void testAddHeader() { - setExceptionExpected(); - - response.addHeader(null, null); + Error error = Assertions.assertThrows(Error.class, () -> response.addHeader(null, null)); + checkError(error); } @Test public void testSetIntHeader() { - setExceptionExpected(); - - response.setIntHeader(null, 0); + Error error = Assertions.assertThrows(Error.class, () -> response.setIntHeader(null, 0)); + checkError(error); } @Test public void testAddIntHeader() { - setExceptionExpected(); - - response.addIntHeader(null, 0); + Error error = Assertions.assertThrows(Error.class, () -> response.addIntHeader(null, 0)); + checkError(error); } @Test public void testSetStatusSc() { - setExceptionExpected(); - - response.setStatus(0); - } - - @SuppressWarnings("deprecation") - @Test - public void testSetStatusScAndSm() { - setExceptionExpected(); - - response.setStatus(0, ""); + Error error = Assertions.assertThrows(Error.class, () -> response.setStatus(0)); + checkError(error); } @Test public void testGetStatus() { - setExceptionExpected(); - - response.getStatus(); + Error error = Assertions.assertThrows(Error.class, () -> response.getStatus()); + checkError(error); } @Test public void testGetHeader() { - setExceptionExpected(); - - response.getHeader(""); + Error error = Assertions.assertThrows(Error.class, () -> response.getHeader("")); + checkError(error); } @Test public void testGetHeaders() { - setExceptionExpected(); - - response.getHeaders(""); + Error error = Assertions.assertThrows(Error.class, () -> response.getHeaders("")); + checkError(error); } @Test public void testGetHeaderNames() { - setExceptionExpected(); - - response.getHeaderNames(); + Error error = Assertions.assertThrows(Error.class, () -> response.getHeaderNames()); + checkError(error); } @Test public void testGetStatusType() { - setExceptionExpected(); - - response.getStatusType(); + Error error = Assertions.assertThrows(Error.class, () -> response.getStatusType()); + checkError(error); } @Test public void attribute() { response.setAttribute("k", "v"); - Assert.assertEquals("v", response.getAttribute("k")); + Assertions.assertEquals("v", response.getAttribute("k")); } @Test public void sendPart() { - setExceptionExpected(); - - response.sendPart(null); + Error error = Assertions.assertThrows(Error.class, () -> response.sendPart(null)); + checkError(error); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestBodyBufferSupportImpl.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestBodyBufferSupportImpl.java index 8e777f4e537..f12bec04915 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestBodyBufferSupportImpl.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestBodyBufferSupportImpl.java @@ -17,58 +17,56 @@ package org.apache.servicecomb.foundation.vertx.http; -import org.junit.Assert; -import org.junit.Test; - import io.vertx.core.buffer.Buffer; -import mockit.Deencapsulation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestBodyBufferSupportImpl { BodyBufferSupportImpl impl = new BodyBufferSupportImpl(); @Test public void testSetBodyBuffer() { - Deencapsulation.setField(impl, "bodyBytes", new byte[] {}); - Deencapsulation.setField(impl, "bodyLength", 10); + impl.setBodyBytes(new byte[] {}); + impl.setBodyLength(10); - Assert.assertNotNull(impl.getBodyBytes()); - Assert.assertEquals(10, impl.getBodyBytesLength()); + Assertions.assertNotNull(impl.getBodyBytes()); + Assertions.assertEquals(10, impl.getBodyBytesLength()); impl.setBodyBuffer(null); - Assert.assertNull(impl.getBodyBytes()); - Assert.assertEquals(0, impl.getBodyBytesLength()); + Assertions.assertNull(impl.getBodyBytes()); + Assertions.assertEquals(0, impl.getBodyBytesLength()); } @Test public void testGetBodyBuffer() { - Assert.assertNull(impl.getBodyBuffer()); + Assertions.assertNull(impl.getBodyBuffer()); Buffer bodyBuffer = Buffer.buffer(); impl.setBodyBuffer(bodyBuffer); - Assert.assertSame(bodyBuffer, impl.getBodyBuffer()); + Assertions.assertSame(bodyBuffer, impl.getBodyBuffer()); } @Test public void testGetBodyBytes() { - Assert.assertNull(impl.getBodyBytes()); + Assertions.assertNull(impl.getBodyBytes()); byte[] bytes = new byte[] {1, 2, 3}; Buffer bodyBuffer = Buffer.buffer(bytes); impl.setBodyBuffer(bodyBuffer); - Assert.assertArrayEquals(bytes, impl.getBodyBytes()); + Assertions.assertArrayEquals(bytes, impl.getBodyBytes()); } @Test public void testGetBodyBytesLength() { - Assert.assertEquals(0, impl.getBodyBytesLength()); + Assertions.assertEquals(0, impl.getBodyBytesLength()); byte[] bytes = new byte[] {1, 2, 3}; Buffer bodyBuffer = Buffer.buffer(bytes); impl.setBodyBuffer(bodyBuffer); - Assert.assertEquals(3, impl.getBodyBytesLength()); + Assertions.assertEquals(3, impl.getBodyBytesLength()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestFileUploadPart.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestFileUploadPart.java index 92098621f88..ed2e331da71 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestFileUploadPart.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestFileUploadPart.java @@ -21,21 +21,22 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.UUID; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; import io.vertx.ext.web.FileUpload; -import mockit.Expectations; -import mockit.Mocked; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestFileUploadPart { - @Mocked + FileUpload fileUpload; FileUploadPart part; @@ -44,95 +45,71 @@ public class TestFileUploadPart { static String content = "fileContent"; - @BeforeClass + @BeforeAll public static void classSetup() throws IOException { - file = File.createTempFile("upload", ".txt"); + file = Files.createTempFile("upload", ".txt").toFile(); file.deleteOnExit(); FileUtils.writeStringToFile(file, content, StandardCharsets.UTF_8, false); } - @Before + @BeforeEach public void setup() { + fileUpload = Mockito.mock(FileUpload.class); part = new FileUploadPart(fileUpload); } + @AfterEach + public void after() { + Mockito.reset(fileUpload); + } + @Test public void getInputStream() throws IOException { - new Expectations() { - { - fileUpload.uploadedFileName(); - result = file.getAbsolutePath(); - } - }; + Mockito.when(fileUpload.uploadedFileName()).thenReturn(file.getAbsolutePath()); try (InputStream is = part.getInputStream()) { - Assert.assertEquals(content, IOUtils.toString(is, StandardCharsets.UTF_8)); + Assertions.assertEquals(content, IOUtils.toString(is, StandardCharsets.UTF_8)); } } @Test public void getContentType() { String contentType = "type"; - new Expectations() { - { - fileUpload.contentType(); - result = contentType; - } - }; - - Assert.assertEquals(contentType, part.getContentType()); + Mockito.when(fileUpload.contentType()).thenReturn(contentType); + + Assertions.assertEquals(contentType, part.getContentType()); } @Test public void getName() { String name = "pName"; - new Expectations() { - { - fileUpload.name(); - result = name; - } - }; - - Assert.assertEquals(name, part.getName()); + Mockito.when(fileUpload.name()).thenReturn(name); + + Assertions.assertEquals(name, part.getName()); } @Test public void getSubmittedFileName() { String clientName = "clientName"; - new Expectations() { - { - fileUpload.fileName(); - result = clientName; - } - }; - - Assert.assertEquals(clientName, part.getSubmittedFileName()); + Mockito.when(fileUpload.fileName()).thenReturn(clientName); + + Assertions.assertEquals(clientName, part.getSubmittedFileName()); } @Test public void getSize() { long fileSize = 10; - new Expectations() { - { - fileUpload.size(); - result = fileSize; - } - }; - - Assert.assertEquals(fileSize, part.getSize()); + Mockito.when(fileUpload.size()).thenReturn(fileSize); + + Assertions.assertEquals(fileSize, part.getSize()); } @Test public void write() throws IOException { - new Expectations() { - { - fileUpload.uploadedFileName(); - result = file.getAbsolutePath(); - } - }; + Mockito.when(fileUpload.uploadedFileName()).thenReturn(file.getAbsolutePath()); File targetFile = new File(UUID.randomUUID().toString()); targetFile.deleteOnExit(); part.write(targetFile.getAbsolutePath()); - Assert.assertEquals(content, FileUtils.readFileToString(targetFile, StandardCharsets.UTF_8)); + Assertions.assertEquals(content, FileUtils.readFileToString(targetFile, StandardCharsets.UTF_8)); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestReadStreamPart.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestReadStreamPart.java deleted file mode 100644 index 50c151da26f..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestReadStreamPart.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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.foundation.vertx.http; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import javax.ws.rs.core.HttpHeaders; - -import org.apache.commons.io.FileUtils; -import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; -import org.apache.servicecomb.foundation.vertx.stream.InputStreamToReadStream; -import org.hamcrest.Matchers; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import io.vertx.core.Handler; -import io.vertx.core.Vertx; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.file.FileSystemException; -import io.vertx.core.file.OpenOptions; -import io.vertx.core.http.HttpClientResponse; -import io.vertx.core.impl.SyncContext; -import io.vertx.core.impl.VertxInternal; -import io.vertx.core.streams.WriteStream; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestReadStreamPart { - static Vertx vertx = Vertx.vertx(); - - static SyncContext context = new SyncContext(); - - static String src = "src"; - - static InputStream inputStream = new ByteArrayInputStream(src.getBytes()); - - InputStreamToReadStream readStream = new InputStreamToReadStream(context, inputStream, true); - - ReadStreamPart part = new ReadStreamPart(context, readStream); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setup() throws IOException { - context.setOwner((VertxInternal)vertx); - inputStream.reset(); - } - - @AfterClass - public static void teardown() { - vertx.close(); - } - - @Test - public void constructFromHttpClientResponse_noContentType(@Mocked HttpClientResponse httpClientResponse) { - new Expectations() { - { - httpClientResponse.getHeader(HttpHeaders.CONTENT_DISPOSITION); - result = "xx;filename=name.txt"; - httpClientResponse.getHeader(HttpHeaders.CONTENT_TYPE); - result = null; - } - }; - - part = new ReadStreamPart(context, httpClientResponse); - - Assert.assertEquals("name.txt", part.getSubmittedFileName()); - Assert.assertEquals("text/plain", part.getContentType()); - } - - @Test - public void constructFromHttpClientResponse_hasContentType(@Mocked HttpClientResponse httpClientResponse) { - new Expectations() { - { - httpClientResponse.getHeader(HttpHeaders.CONTENT_DISPOSITION); - result = "xx;filename=name.txt"; - httpClientResponse.getHeader(HttpHeaders.CONTENT_TYPE); - result = "type"; - } - }; - - part = new ReadStreamPart(context, httpClientResponse); - - Assert.assertEquals("name.txt", part.getSubmittedFileName()); - Assert.assertEquals("type", part.getContentType()); - } - - @Test - public void saveToWriteStream() throws InterruptedException, ExecutionException { - Buffer buf = Buffer.buffer(); - WriteStream writeStream = new MockUp>() { - @Mock - WriteStream write(Buffer data) { - buf.appendBuffer(data); - return null; - } - }.getMockInstance(); - - part.saveToWriteStream(writeStream).get(); - - Assert.assertEquals(src, buf.toString()); - } - - @Test - public void saveToWriteStream_writeException() throws InterruptedException, ExecutionException { - RuntimeException error = new RuntimeExceptionWithoutStackTrace(); - WriteStream writeStream = new MockUp>() { - Handler exceptionHandler; - - @Mock - WriteStream exceptionHandler(Handler handler) { - this.exceptionHandler = handler; - return null; - } - - @Mock - WriteStream write(Buffer data) { - exceptionHandler.handle(error); - return null; - } - }.getMockInstance(); - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.sameInstance(error)); - - part.saveToWriteStream(writeStream).get(); - } - - @Test - public void saveToWrite_readException(@Mocked WriteStream writeStream) - throws InterruptedException, ExecutionException { - RuntimeException error = new RuntimeExceptionWithoutStackTrace(); - new MockUp(inputStream) { - @Mock - int read(byte b[]) throws IOException { - throw error; - } - }; - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.sameInstance(error)); - - part.saveToWriteStream(writeStream).get(); - } - - @Test - public void saveAsBytes() throws InterruptedException, ExecutionException { - Assert.assertArrayEquals(src.getBytes(), part.saveAsBytes().get()); - } - - @Test - public void saveAsString() throws InterruptedException, ExecutionException { - Assert.assertEquals(src, part.saveAsString().get()); - } - - @Test - public void saveToFile() throws InterruptedException, ExecutionException, IOException { - File dir = new File("target/notExist-" + UUID.randomUUID().toString()); - File file = new File(dir, "a.txt"); - - Assert.assertFalse(dir.exists()); - - part.saveToFile(file.getAbsolutePath()).get(); - - Assert.assertEquals(src, FileUtils.readFileToString(file, StandardCharsets.UTF_8)); - - FileUtils.forceDelete(dir); - Assert.assertFalse(dir.exists()); - } - - @Test - public void saveToFile_notExist_notCreate() throws InterruptedException, ExecutionException, IOException { - File dir = new File("target/notExist-" + UUID.randomUUID().toString()); - File file = new File(dir, "a.txt"); - - Assert.assertFalse(dir.exists()); - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.instanceOf(FileSystemException.class)); - - OpenOptions openOptions = new OpenOptions().setCreateNew(false); - part.saveToFile(file, openOptions).get(); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java index 3486d3ee481..15e52aa5f71 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletRequestEx.java @@ -25,15 +25,15 @@ import java.util.Locale; import java.util.Map; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.MediaType; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.ws.rs.HttpMethod; +import jakarta.ws.rs.core.MediaType; import org.apache.commons.io.IOUtils; import org.apache.servicecomb.foundation.vertx.stream.BufferInputStream; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -41,6 +41,7 @@ import mockit.Deencapsulation; import mockit.Expectations; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestStandardHttpServletRequestEx { @Mocked @@ -59,15 +60,15 @@ public void setBodyBuffer() { bodyBuffer.appendString("abc"); requestEx.setBodyBuffer(bodyBuffer); - Assert.assertSame(bodyBuffer, requestEx.getBodyBuffer()); - Assert.assertArrayEquals("abc".getBytes(), Arrays.copyOf(requestEx.getBodyBytes(), requestEx.getBodyBytesLength())); + Assertions.assertSame(bodyBuffer, requestEx.getBodyBuffer()); + Assertions.assertArrayEquals("abc".getBytes(), Arrays.copyOf(requestEx.getBodyBytes(), requestEx.getBodyBytesLength())); } @Test public void getInputStreamNotCache() throws IOException { ServletInputStream inputStream = request.getInputStream(); - Assert.assertSame(inputStream, requestEx.getInputStream()); + Assertions.assertSame(inputStream, requestEx.getInputStream()); } @Test @@ -83,10 +84,10 @@ public void getInputStreamCache() throws IOException { }; ServletInputStream cachedInputStream = requestEx.getInputStream(); - Assert.assertEquals("abc", IOUtils.toString(cachedInputStream, StandardCharsets.UTF_8)); - Assert.assertEquals("abc", requestEx.getBodyBuffer().toString()); + Assertions.assertEquals("abc", IOUtils.toString(cachedInputStream, StandardCharsets.UTF_8)); + Assertions.assertEquals("abc", requestEx.getBodyBuffer().toString()); // do not create another one - Assert.assertSame(cachedInputStream, requestEx.getInputStream()); + Assertions.assertSame(cachedInputStream, requestEx.getInputStream()); } @Test @@ -103,10 +104,10 @@ public void parameterMap_inherited() { } }; - Assert.assertSame(inherited, requestEx.getParameterMap()); - Assert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.contains("p1")); - Assert.assertSame(v1, requestEx.getParameterValues("p1")); - Assert.assertEquals("v1-1", requestEx.getParameter("p1")); + Assertions.assertSame(inherited, requestEx.getParameterMap()); + MatcherAssert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.contains("p1")); + Assertions.assertSame(v1, requestEx.getParameterValues("p1")); + Assertions.assertEquals("v1-1", requestEx.getParameter("p1")); } @Test @@ -116,7 +117,7 @@ public void parameterMap_merge() throws IOException { inherited.put("p1", v1); Buffer buffer = Buffer.buffer("p1=v1-3;p2=v2"); - BufferInputStream inputStream = new BufferInputStream(buffer.getByteBuf()); + BufferInputStream inputStream = new BufferInputStream(buffer); new Expectations() { { request.getParameterMap(); @@ -130,9 +131,9 @@ public void parameterMap_merge() throws IOException { } }; - Assert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.contains("p1", "p2")); - Assert.assertThat(requestEx.getParameterValues("p1"), Matchers.arrayContaining("v1-1", "v1-2", "v1-3")); - Assert.assertEquals("v1-1", requestEx.getParameter("p1")); + MatcherAssert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.containsInAnyOrder("p1", "p2")); + MatcherAssert.assertThat(requestEx.getParameterValues("p1"), Matchers.arrayContaining("v1-1", "v1-2", "v1-3")); + Assertions.assertEquals("v1-1", requestEx.getParameter("p1")); } @Test @@ -143,11 +144,11 @@ public void setParameter() { requestEx.setParameter("k1", "v1"); requestEx.setParameter("k2", "v2"); - Assert.assertEquals("v1", requestEx.getParameter("k1")); - Assert.assertEquals("v2", requestEx.getParameter("k2")); + Assertions.assertEquals("v1", requestEx.getParameter("k1")); + Assertions.assertEquals("v2", requestEx.getParameter("k2")); - Assert.assertSame(parameterMap, requestEx.getParameterMap()); + Assertions.assertSame(parameterMap, requestEx.getParameterMap()); - Assert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.contains("k1", "k2")); + MatcherAssert.assertThat(Collections.list(requestEx.getParameterNames()), Matchers.containsInAnyOrder("k1", "k2")); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletResponseEx.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletResponseEx.java index beebcddf3b6..289d5b15226 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletResponseEx.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestStandardHttpServletResponseEx.java @@ -21,49 +21,40 @@ import java.io.IOException; import java.io.InputStream; -import javax.servlet.ServletOutputStream; -import javax.servlet.WriteListener; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.Part; - -import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.servicecomb.foundation.common.part.InputStreamPart; import org.apache.servicecomb.foundation.test.scaffolding.exception.RuntimeExceptionWithoutStackTrace; -import org.hamcrest.Matchers; -import org.junit.Assert; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; import io.vertx.core.buffer.Buffer; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.WriteListener; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.Part; + public class TestStandardHttpServletResponseEx { - @Mocked HttpServletResponse response; StandardHttpServletResponseEx responseEx; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Before public void setup() { + response = Mockito.mock(HttpServletResponse.class); responseEx = new StandardHttpServletResponseEx(response); } @Test public void setBodyBuffer() { - Assert.assertNull(responseEx.getBodyBuffer()); + Assertions.assertNull(responseEx.getBodyBuffer()); Buffer bodyBuffer = Buffer.buffer(); bodyBuffer.appendString("abc"); responseEx.setBodyBuffer(bodyBuffer); - Assert.assertEquals("abc", responseEx.getBodyBuffer().toString()); + Assertions.assertEquals("abc", responseEx.getBodyBuffer().toString()); } @Test @@ -71,7 +62,7 @@ public void getBodyBytes() { Buffer bodyBuffer = Buffer.buffer(); bodyBuffer.appendString("abc"); responseEx.setBodyBuffer(bodyBuffer); - Assert.assertEquals("abc", new String(responseEx.getBodyBytes(), 0, responseEx.getBodyBytesLength())); + Assertions.assertEquals("abc", new String(responseEx.getBodyBytes(), 0, responseEx.getBodyBytesLength())); } @Test @@ -79,15 +70,7 @@ public void getBodyBytesLength() { Buffer bodyBuffer = Buffer.buffer(); bodyBuffer.appendString("abc"); responseEx.setBodyBuffer(bodyBuffer); - Assert.assertEquals(3, responseEx.getBodyBytesLength()); - } - - @Test - public void setStatus() { - responseEx.setStatus(200, "ok"); - Assert.assertEquals(200, responseEx.getStatus()); - Assert.assertEquals(200, responseEx.getStatusType().getStatusCode()); - Assert.assertEquals("ok", responseEx.getStatusType().getReasonPhrase()); + Assertions.assertEquals(3, responseEx.getBodyBytesLength()); } @Test @@ -105,71 +88,66 @@ public void setWriteListener(WriteListener writeListener) { } @Override - public void write(int b) throws IOException { + public void write(int b) { buffer.appendByte((byte) b); } }; - response = new MockUp() { - @Mock - ServletOutputStream getOutputStream() { - return output; - } - }.getMockInstance(); + + Mockito.when(response.getOutputStream()).thenReturn(output); responseEx = new StandardHttpServletResponseEx(response); // no body responseEx.flushBuffer(); - Assert.assertEquals(0, buffer.length()); + Assertions.assertEquals(0, buffer.length()); Buffer body = Buffer.buffer().appendString("body"); responseEx.setBodyBuffer(body); responseEx.flushBuffer(); - Assert.assertEquals("body", buffer.toString()); + Assertions.assertEquals(0, buffer.length()); } @Test public void attribute() { responseEx.setAttribute("k", "v"); - Assert.assertEquals("v", responseEx.getAttribute("k")); + Assertions.assertEquals("v", responseEx.getAttribute("k")); } @Test public void sendPart_succ() throws Throwable { - String src = RandomStringUtils.random(100); + String src = RandomStringUtils.random(100, true, true); InputStream inputStream = new ByteArrayInputStream(src.getBytes()); Part part = new InputStreamPart("name", inputStream); Buffer buffer = Buffer.buffer(); - ServletOutputStream outputStream = new MockUp() { - @Mock - void write(int b) { - buffer.appendByte((byte) b); + + ServletOutputStream outputStream = new ServletOutputStream() { + @Override + public boolean isReady() { + return false; } - }.getMockInstance(); - new Expectations() { - { - response.getOutputStream(); - result = outputStream; + @Override + public void setWriteListener(WriteListener writeListener) { + + } + + @Override + public void write(int b) { + buffer.appendByte((byte) b); } }; + Mockito.when(response.getOutputStream()).thenReturn(outputStream); responseEx.sendPart(part).get(); - Assert.assertEquals(src, buffer.toString()); + Assertions.assertEquals(src, buffer.toString()); } @Test - public void sendPart_failed(@Mocked Part part) throws Throwable { + public void sendPart_failed() throws Throwable { + Part part = Mockito.mock(Part.class); RuntimeException error = new RuntimeExceptionWithoutStackTrace(); - new Expectations() { - { - response.getOutputStream(); - result = error; - } - }; + Mockito.when(response.getOutputStream()).thenThrow(error); - expectedException.expect(Matchers.sameInstance(error)); - - responseEx.sendPart(part).get(); + Assertions.assertThrows(RuntimeException.class, () -> responseEx.sendPart(part).get()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java index 41536970fc3..9cbe78713b3 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientRequestToHttpServletRequest.java @@ -19,160 +19,122 @@ import java.util.Collections; -import javax.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.HttpHeaders; import org.apache.servicecomb.foundation.common.http.HttpUtils; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpMethod; import mockit.Expectations; -import mockit.Mocked; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestVertxClientRequestToHttpServletRequest { - @Mocked HttpClientRequest clientRequest; Buffer bodyBuffer = Buffer.buffer(); VertxClientRequestToHttpServletRequest request; - @Before + @BeforeEach public void setup() { + clientRequest = Mockito.mock(HttpClientRequest.class); request = new VertxClientRequestToHttpServletRequest(clientRequest, bodyBuffer); } + @AfterEach + public void after() { + Mockito.reset(clientRequest); + } + @Test public void testGetRequestURI() { - new Expectations() { - { - clientRequest.path(); - result = "/path"; - } - }; + Mockito.when(clientRequest.path()).thenReturn("/path"); - Assert.assertEquals("/path", request.getRequestURI()); + Assertions.assertEquals("/path", request.getRequestURI()); } @Test public void testGetQueryString() { - new Expectations() { - { - clientRequest.query(); - result = "a=1&b=2"; - } - }; + Mockito.when(clientRequest.query()).thenReturn("a=1&b=2"); - Assert.assertEquals("a=1&b=2", request.getQueryString()); + Assertions.assertEquals("a=1&b=2", request.getQueryString()); } @Test public void testGetHeader() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); headers.add("name", "value"); - new Expectations() { - { - clientRequest.headers(); - result = headers; - } - }; + Mockito.when(clientRequest.headers()).thenReturn(headers); - Assert.assertEquals("value", request.getHeader("name")); + Assertions.assertEquals("value", request.getHeader("name")); } @Test public void testGetHeaders() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); headers.add("name", "value"); - new Expectations() { - { - clientRequest.headers(); - result = headers; - } - }; + Mockito.when(clientRequest.headers()).thenReturn(headers); - Assert.assertThat(Collections.list(request.getHeaders("name")), Matchers.contains("value")); + MatcherAssert.assertThat(Collections.list(request.getHeaders("name")), Matchers.contains("value")); } @Test public void testGetHeaderNames() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); headers.add("name", "value"); - new Expectations() { - { - clientRequest.headers(); - result = headers; - } - }; + Mockito.when(clientRequest.headers()).thenReturn(headers); - Assert.assertThat(Collections.list(request.getHeaderNames()), Matchers.contains("name")); + MatcherAssert.assertThat(Collections.list(request.getHeaderNames()), Matchers.contains("name")); } @Test public void testSetHeader() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - new Expectations() { - { - clientRequest.headers(); - result = headers; - } - }; + Mockito.when(clientRequest.headers()).thenReturn(headers); request.setHeader("name", "v1"); request.setHeader("name", "v2"); - Assert.assertThat(headers.getAll("name"), Matchers.contains("v2")); + MatcherAssert.assertThat(headers.getAll("name"), Matchers.contains("v2")); } @Test public void testAddHeader() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - new Expectations() { - { - clientRequest.headers(); - result = headers; - } - }; + Mockito.when(clientRequest.headers()).thenReturn(headers); request.addHeader("name", "v1"); request.addHeader("name", "v2"); - Assert.assertThat(headers.getAll("name"), Matchers.contains("v1", "v2")); + MatcherAssert.assertThat(headers.getAll("name"), Matchers.contains("v1", "v2")); } @Test public void testGetContextPath() { - Assert.assertEquals("", request.getContextPath()); + Assertions.assertEquals("", request.getContextPath()); } @Test public void getMethod() { - new Expectations() { - { - clientRequest.getMethod(); - result = HttpMethod.GET; - } - }; + Mockito.when(clientRequest.getMethod()).thenReturn(HttpMethod.GET); - Assert.assertEquals("GET", request.getMethod()); + Assertions.assertEquals("GET", request.getMethod()); } @Test public void getContentType() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - new Expectations() { - { - clientRequest.headers(); - result = headers; - } - }; + Mockito.when(clientRequest.headers()).thenReturn(headers); request.addHeader(HttpHeaders.CONTENT_TYPE, "ct"); - Assert.assertEquals("ct", request.getContentType()); + Assertions.assertEquals("ct", request.getContentType()); } @Test @@ -185,13 +147,12 @@ public void getCharacterEncoding() { { HttpUtils.getCharsetFromContentType(contentType); result = characterEncoding; - clientRequest.headers(); - result = headers; } }; + Mockito.when(clientRequest.headers()).thenReturn(headers); request.addHeader(HttpHeaders.CONTENT_TYPE, contentType); - Assert.assertEquals("ce", request.getCharacterEncoding()); + Assertions.assertEquals("ce", request.getCharacterEncoding()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientResponseToHttpServletResponse.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientResponseToHttpServletResponse.java index 5d38fa3cccb..ca204c9b6fc 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientResponseToHttpServletResponse.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxClientResponseToHttpServletResponse.java @@ -17,84 +17,69 @@ package org.apache.servicecomb.foundation.vertx.http; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.HttpHeaders; +import jakarta.ws.rs.core.Response.StatusType; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; import io.vertx.core.MultiMap; import io.vertx.core.buffer.Buffer; import io.vertx.core.http.HttpClientResponse; -import mockit.Expectations; -import mockit.Mocked; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestVertxClientResponseToHttpServletResponse { - @Mocked HttpClientResponse clientResponse; Buffer bodyBuffer = Buffer.buffer(); VertxClientResponseToHttpServletResponse response; - @Before + @BeforeEach public void setup() { + clientResponse = Mockito.mock(HttpClientResponse.class); response = new VertxClientResponseToHttpServletResponse(clientResponse, bodyBuffer); } + @AfterEach + public void after() { + Mockito.reset(clientResponse); + } + @Test public void getStatus() { - new Expectations() { - { - clientResponse.statusCode(); - result = 123; - } - }; - - Assert.assertEquals(123, response.getStatus()); + Mockito.when(clientResponse.statusCode()).thenReturn(123); + + Assertions.assertEquals(123, response.getStatus()); } @Test public void getStatusType() { - new Expectations() { - { - clientResponse.statusCode(); - result = 123; - clientResponse.statusMessage(); - result = "test"; - } - }; + Mockito.when(clientResponse.statusCode()).thenReturn(123); + Mockito.when(clientResponse.statusMessage()).thenReturn("test"); StatusType type = response.getStatusType(); - Assert.assertSame(type, response.getStatusType()); - Assert.assertEquals(123, type.getStatusCode()); - Assert.assertEquals("test", type.getReasonPhrase()); + Assertions.assertSame(type, response.getStatusType()); + Assertions.assertEquals(123, type.getStatusCode()); + Assertions.assertEquals("test", type.getReasonPhrase()); } @Test public void getContentType() { - new Expectations() { - { - clientResponse.getHeader(HttpHeaders.CONTENT_TYPE); - result = "json"; - } - }; - - Assert.assertEquals("json", response.getContentType()); + Mockito.when(clientResponse.getHeader(HttpHeaders.CONTENT_TYPE)).thenReturn("json"); + + Assertions.assertEquals("json", response.getContentType()); } @Test public void getHeader() { - new Expectations() { - { - clientResponse.getHeader("name"); - result = "value"; - } - }; - - Assert.assertEquals("value", response.getHeader("name")); + Mockito.when(clientResponse.getHeader("name")).thenReturn("value"); + + Assertions.assertEquals("value", response.getHeader("name")); } @Test @@ -102,14 +87,9 @@ public void getHeaders() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); headers.add("name", "v1"); headers.add("name", "v2"); - new Expectations() { - { - clientResponse.headers(); - result = headers; - } - }; - - Assert.assertThat(response.getHeaders("name"), Matchers.contains("v1", "v2")); + Mockito.when(clientResponse.headers()).thenReturn(headers); + + MatcherAssert.assertThat(response.getHeaders("name"), Matchers.contains("v1", "v2")); } @Test @@ -117,13 +97,8 @@ public void getHeaderNames() { MultiMap headers = MultiMap.caseInsensitiveMultiMap(); headers.add("n1", "v1"); headers.add("n2", "v2"); - new Expectations() { - { - clientResponse.headers(); - result = headers; - } - }; - - Assert.assertThat(response.getHeaderNames(), Matchers.contains("n1", "n2")); + Mockito.when(clientResponse.headers()).thenReturn(headers); + + MatcherAssert.assertThat(response.getHeaderNames(), Matchers.contains("n1", "n2")); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java index e51c99fee5e..9d53cd649da 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerRequestToHttpServletRequest.java @@ -20,18 +20,22 @@ import java.io.IOException; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; -import javax.servlet.AsyncContext; -import javax.servlet.ServletInputStream; -import javax.servlet.http.Cookie; -import javax.ws.rs.core.HttpHeaders; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.Cookie; +import jakarta.ws.rs.core.HttpHeaders; +import io.vertx.ext.web.RequestBody; +import io.vertx.ext.web.impl.RoutingContextInternal; import org.apache.servicecomb.foundation.common.Holder; import org.apache.servicecomb.foundation.common.http.HttpUtils; +import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; -import org.junit.Assert; +import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -43,9 +47,9 @@ import io.vertx.ext.web.RoutingContext; import mockit.Deencapsulation; import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; public class TestVertxServerRequestToHttpServletRequest { @Mocked @@ -57,6 +61,14 @@ public class TestVertxServerRequestToHttpServletRequest { @Mocked SocketAddress socketAddress; + RequestBody mockRequestBody; + + RoutingContextInternal mockContext; + + HttpServerRequest mockHttpServerRequest; + + SocketAddress mockSocketAddress; + VertxServerRequestToHttpServletRequest request; @Before @@ -70,70 +82,79 @@ public void setup() { } }; + mockRequestBody = Mockito.mock(RequestBody.class); + mockContext = Mockito.mock(RoutingContextInternal.class); + mockHttpServerRequest = Mockito.mock(HttpServerRequest.class); + mockSocketAddress = Mockito.mock(SocketAddress.class); + // init mocks + Mockito.when(mockHttpServerRequest.remoteAddress()).thenReturn(mockSocketAddress); + Mockito.when(mockContext.body()).thenReturn(mockRequestBody); + Mockito.when(mockContext.request()).thenReturn(mockHttpServerRequest); + request = new VertxServerRequestToHttpServletRequest(context); } + @After + public void clean() { + Mockito.reset(mockRequestBody); + Mockito.reset(mockContext); + } + @Test public void constructWithPath() { request = new VertxServerRequestToHttpServletRequest(context, "/path"); - Assert.assertEquals("/path", request.getRequestURI()); + Assertions.assertEquals("/path", request.getRequestURI()); } @Test public void setBodyBuffer() { Holder bodyHolder = new Holder<>(); - context = new MockUp() { - @Mock - HttpServerRequest request() { - return vertxRequest; - } - - @Mock - void setBody(Buffer body) { - bodyHolder.value = body; - } - }.getMockInstance(); - request = new VertxServerRequestToHttpServletRequest(context); + Mockito.doAnswer(invocation -> { + bodyHolder.value = invocation.getArgument(0); + return null; + }).when(mockContext).setBody(Mockito.any()); + request = new VertxServerRequestToHttpServletRequest(mockContext); Buffer bodyBuffer = Buffer.buffer(); request.setBodyBuffer(bodyBuffer); - Assert.assertSame(bodyBuffer, bodyHolder.value); - Assert.assertSame(bodyBuffer, request.getBodyBuffer()); + Assertions.assertSame(bodyBuffer, bodyHolder.value); + Assertions.assertSame(bodyBuffer, request.getBodyBuffer()); } @Test public void testGetContentType() { - new Expectations() { - { - vertxRequest.getHeader(HttpHeaders.CONTENT_TYPE); - result = "json"; - } - }; - - Assert.assertEquals("json", request.getContentType()); + VertxServerRequestToHttpServletRequest request = new VertxServerRequestToHttpServletRequest(mockContext); + Mockito.when(mockHttpServerRequest.getHeader(HttpHeaders.CONTENT_TYPE)).thenReturn("json"); + Assertions.assertEquals("json", request.getContentType()); } @Test public void testGetCookies() { - Map vertxCookies = new LinkedHashMap<>(); - vertxCookies.put("c1", io.vertx.core.http.Cookie.cookie("c1", "c1v")); - vertxCookies.put("c2", io.vertx.core.http.Cookie.cookie("c2", "c2v")); + Set vertxCookies = new HashSet<>(); + vertxCookies.add(io.vertx.core.http.Cookie.cookie("c1", "c1v")); + vertxCookies.add(io.vertx.core.http.Cookie.cookie("c2", "c2v")); new Expectations() { { - context.cookieMap(); + context.request().cookies(); result = vertxCookies; } }; Cookie[] cookies = request.getCookies(); - Assert.assertEquals("c1", cookies[0].getName()); - Assert.assertEquals("c1v", cookies[0].getValue()); - Assert.assertEquals("c2", cookies[1].getName()); - Assert.assertEquals("c2v", cookies[1].getValue()); - - Assert.assertSame(cookies, request.getCookies()); + // we can't ensure the sequence when set to list + if (cookies[0].getName().equals("c1")) { + Assertions.assertEquals("c1", cookies[0].getName()); + Assertions.assertEquals("c1v", cookies[0].getValue()); + Assertions.assertEquals("c2", cookies[1].getName()); + Assertions.assertEquals("c2v", cookies[1].getValue()); + } else { + Assertions.assertEquals("c2", cookies[0].getName()); + Assertions.assertEquals("c2v", cookies[0].getValue()); + Assertions.assertEquals("c1", cookies[1].getName()); + Assertions.assertEquals("c1v", cookies[1].getValue()); + } } @Test @@ -145,12 +166,12 @@ public void testGetParameter() { } }; - Assert.assertEquals("value", request.getParameter("name")); + Assertions.assertEquals("value", request.getParameter("name")); } @Test public void testGetParameterValuesNull() { - Assert.assertEquals(0, request.getParameterValues("name").length); + Assertions.assertEquals(0, request.getParameterValues("name").length); } @Test @@ -165,7 +186,7 @@ public void testGetParameterValuesNormal() { } }; - Assert.assertThat(request.getParameterValues("name"), Matchers.arrayContaining("value")); + MatcherAssert.assertThat(request.getParameterValues("name"), Matchers.arrayContaining("value")); } @Test @@ -181,9 +202,9 @@ public void testGetParameterMap() { }; Map result = request.getParameterMap(); - Assert.assertThat(result.keySet(), Matchers.contains("name")); - Assert.assertThat(result.get("name"), Matchers.arrayContaining("value")); - Assert.assertSame(result, request.getParameterMap()); + MatcherAssert.assertThat(result.keySet(), Matchers.contains("name")); + MatcherAssert.assertThat(result.get("name"), Matchers.arrayContaining("value")); + Assertions.assertSame(result, request.getParameterMap()); } @Test @@ -195,7 +216,7 @@ public void testScheme() { } }; - Assert.assertEquals("abc", request.getScheme()); + Assertions.assertEquals("abc", request.getScheme()); } @Test @@ -207,7 +228,7 @@ public void testGetRemoteAddr() { } }; - Assert.assertEquals("host", request.getRemoteAddr()); + Assertions.assertEquals("host", request.getRemoteAddr()); } @Test @@ -218,7 +239,7 @@ public void testGetRemoteAddrNull() { result = null; } }; - Assert.assertEquals(null, request.getRemoteAddr()); + Assertions.assertNull(request.getRemoteAddr()); } @Test @@ -230,7 +251,7 @@ public void testGetRemoteHost() { } }; - Assert.assertEquals("host", request.getRemoteHost()); + Assertions.assertEquals("host", request.getRemoteHost()); } @Test @@ -242,7 +263,7 @@ public void testGetRemotePort() { } }; - Assert.assertEquals(1234, request.getRemotePort()); + Assertions.assertEquals(1234, request.getRemotePort()); } @Test @@ -256,7 +277,7 @@ public void testGetgetLocalAddr(@Mocked SocketAddress sa) { } }; - Assert.assertEquals("host", request.getLocalAddr()); + Assertions.assertEquals("host", request.getLocalAddr()); } @Test @@ -270,7 +291,7 @@ public void testGetLocalPort(@Mocked SocketAddress sa) { } }; - Assert.assertEquals(1234, request.getLocalPort()); + Assertions.assertEquals(1234, request.getLocalPort()); } @Test @@ -282,7 +303,7 @@ public void testGetHeader() { } }; - Assert.assertEquals("value", request.getHeader("key")); + Assertions.assertEquals("value", request.getHeader("key")); } @Test @@ -296,7 +317,7 @@ public void testGetHeaders() { } }; - Assert.assertThat(Collections.list(request.getHeaders("name")), Matchers.contains("value")); + MatcherAssert.assertThat(Collections.list(request.getHeaders("name")), Matchers.contains("value")); } @Test @@ -310,12 +331,12 @@ public void testGetHeaderNames() { } }; - Assert.assertThat(Collections.list(request.getHeaderNames()), Matchers.contains("name")); + MatcherAssert.assertThat(Collections.list(request.getHeaderNames()), Matchers.contains("name")); } @Test public void testGetIntHeaderNotExist() { - Assert.assertEquals(-1, request.getIntHeader("key")); + Assertions.assertEquals(-1, request.getIntHeader("key")); } @Test @@ -329,9 +350,9 @@ public void testGetIntHeaderNotNumber() { try { request.getIntHeader("key"); - Assert.fail("must throw exception"); + Assertions.fail("must throw exception"); } catch (NumberFormatException e) { - Assert.assertEquals("For input string: \"value\"", e.getMessage()); + Assertions.assertEquals("For input string: \"value\"", e.getMessage()); } } @@ -344,7 +365,7 @@ public void testGetIntHeaderNormal() { } }; - Assert.assertEquals(1, request.getIntHeader("key")); + Assertions.assertEquals(1, request.getIntHeader("key")); } @Test @@ -356,7 +377,7 @@ public void testGetMethod() { } }; - Assert.assertEquals("GET", request.getMethod()); + Assertions.assertEquals("GET", request.getMethod()); } @Test @@ -368,7 +389,7 @@ public void testGetPathInfo() { } }; - Assert.assertEquals("/path", request.getPathInfo()); + Assertions.assertEquals("/path", request.getPathInfo()); } @Test @@ -380,7 +401,7 @@ public void testGetQueryString() { } }; - Assert.assertEquals("k1=v1&k2=v2", request.getQueryString()); + Assertions.assertEquals("k1=v1&k2=v2", request.getQueryString()); } @Test @@ -392,7 +413,7 @@ public void testGetRequestURI() { } }; - Assert.assertEquals("/path", request.getRequestURI()); + Assertions.assertEquals("/path", request.getRequestURI()); } @Test @@ -404,12 +425,12 @@ public void testGetServletPath() { } }; - Assert.assertEquals("/path", request.getServletPath()); + Assertions.assertEquals("/path", request.getServletPath()); } @Test public void testGetContextPath() { - Assert.assertEquals("", request.getContextPath()); + Assertions.assertEquals("", request.getContextPath()); } @Test @@ -417,23 +438,21 @@ public void testGetInputStream() throws IOException { Buffer body = Buffer.buffer(); body.appendByte((byte) 1); - new Expectations() { - { - context.getBody(); - result = body; - } - }; + Mockito.when(mockRequestBody.buffer()).thenReturn(body); + Mockito.when(mockContext.request()).thenReturn(vertxRequest); + Mockito.when(mockContext.body()).thenReturn(mockRequestBody); + VertxServerRequestToHttpServletRequest request = new VertxServerRequestToHttpServletRequest(mockContext); ServletInputStream is1 = request.getInputStream(); - Assert.assertSame(is1, request.getInputStream()); + Assertions.assertSame(is1, request.getInputStream()); int value = is1.read(); is1.close(); - Assert.assertEquals(1, value); - Assert.assertSame(is1, request.getInputStream()); + Assertions.assertEquals(1, value); + Assertions.assertSame(is1, request.getInputStream()); - request.setBodyBuffer(Buffer.buffer().appendByte((byte)2)); + request.setBodyBuffer(Buffer.buffer().appendByte((byte) 2)); ServletInputStream is2 = request.getInputStream(); - Assert.assertNotSame(is1, is2); + Assertions.assertNotSame(is1, is2); } @Test @@ -441,7 +460,7 @@ public void testGetAsyncContext() { AsyncContext asyncContext = Deencapsulation.getField(VertxServerRequestToHttpServletRequest.class, "EMPTY_ASYNC_CONTEXT"); - Assert.assertSame(asyncContext, request.getAsyncContext()); + Assertions.assertSame(asyncContext, request.getAsyncContext()); } @Test @@ -455,7 +474,7 @@ public void getCharacterEncoding() { } }; - Assert.assertEquals("ce", request.getCharacterEncoding()); + Assertions.assertEquals("ce", request.getCharacterEncoding()); } @@ -467,11 +486,11 @@ public void setParameter() { request.setParameter("k1", "v1"); request.setParameter("k2", "v2"); - Assert.assertEquals("v1", request.getParameter("k1")); - Assert.assertEquals("v2", request.getParameter("k2")); + Assertions.assertEquals("v1", request.getParameter("k1")); + Assertions.assertEquals("v2", request.getParameter("k2")); - Assert.assertSame(parameterMap, request.getParameterMap()); + Assertions.assertSame(parameterMap, request.getParameterMap()); - Assert.assertThat(Collections.list(request.getParameterNames()), Matchers.contains("k1", "k2")); + MatcherAssert.assertThat(Collections.list(request.getParameterNames()), Matchers.containsInAnyOrder("k1", "k2")); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java deleted file mode 100644 index da1d9d258b0..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/http/TestVertxServerResponseToHttpServletResponse.java +++ /dev/null @@ -1,429 +0,0 @@ -/* - * 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.foundation.vertx.http; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; -import java.util.UUID; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -import javax.servlet.http.Part; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response.StatusType; - -import org.apache.commons.io.FileUtils; -import org.apache.servicecomb.foundation.common.http.HttpStatus; -import org.apache.servicecomb.foundation.common.part.FilePart; -import org.apache.servicecomb.foundation.vertx.stream.PumpFromPart; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import io.vertx.core.AsyncResult; -import io.vertx.core.Context; -import io.vertx.core.Handler; -import io.vertx.core.MultiMap; -import io.vertx.core.Promise; -import io.vertx.core.Vertx; -import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpServerResponse; -import io.vertx.core.impl.SyncContext; -import io.vertx.core.streams.WriteStream; -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestVertxServerResponseToHttpServletResponse { - MultiMap headers = MultiMap.caseInsensitiveMultiMap(); - - HttpStatus httpStatus = new HttpStatus(123, "default"); - - HttpServerResponse serverResponse; - - VertxServerResponseToHttpServletResponse response; - - boolean flushWithBody; - - boolean runOnContextInvoked; - - @Mocked - Vertx vertx; - - @Mocked - Context context; - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - boolean chunked; - - @Before - public void setup() { - serverResponse = new MockUp() { - @Mock - HttpServerResponse setStatusCode(int statusCode) { - Deencapsulation.setField(httpStatus, "statusCode", statusCode); - return serverResponse; - } - - @Mock - HttpServerResponse setStatusMessage(String statusMessage) { - Deencapsulation.setField(httpStatus, "reason", statusMessage); - return serverResponse; - } - - @Mock - int getStatusCode() { - return httpStatus.getStatusCode(); - } - - @Mock - String getStatusMessage() { - return httpStatus.getReasonPhrase(); - } - - @Mock - MultiMap headers() { - return headers; - } - - @Mock - HttpServerResponse putHeader(String name, String value) { - headers.set(name, value); - return serverResponse; - } - - @Mock - void end() { - flushWithBody = false; - } - - @Mock - void end(Buffer chunk) { - flushWithBody = true; - } - - @Mock - HttpServerResponse setChunked(boolean chunked) { - TestVertxServerResponseToHttpServletResponse.this.chunked = chunked; - return serverResponse; - } - - @Mock - boolean isChunked() { - return chunked; - } - }.getMockInstance(); - - new Expectations() { - { - Vertx.currentContext(); - result = context; - } - }; - - new MockUp(context) { - @Mock - void runOnContext(Handler action) { - runOnContextInvoked = true; - action.handle(null); - } - - @Mock - void executeBlocking(Handler> blockingCodeHandler, boolean ordered, - Handler> resultHandler) { - SyncContext.syncExecuteBlocking(blockingCodeHandler, resultHandler); - } - - @Mock - Vertx owner() { - return vertx; - } - }; - - response = new VertxServerResponseToHttpServletResponse(serverResponse); - } - - @Test - public void construct_invalid() throws IOException { - new Expectations() { - { - Vertx.currentContext(); - result = null; - } - }; - - expectedException.expect(NullPointerException.class); - expectedException.expectMessage(Matchers.is("must run in vertx context.")); - - new VertxServerResponseToHttpServletResponse(serverResponse); - } - - @Test - public void setContentType() { - response.setContentType("json"); - Assert.assertEquals("json", headers.get(HttpHeaders.CONTENT_TYPE)); - } - - @SuppressWarnings("deprecation") - @Test - public void setStatus() { - response.setStatus(222, "test"); - Assert.assertEquals(222, httpStatus.getStatusCode()); - Assert.assertEquals("test", httpStatus.getReasonPhrase()); - } - - @Test - public void getStatusType() { - StatusType status = response.getStatusType(); - - Assert.assertSame(status, response.getStatusType()); - Assert.assertEquals(123, httpStatus.getStatusCode()); - Assert.assertEquals("default", httpStatus.getReasonPhrase()); - } - - @Test - public void addHeader() { - response.addHeader("n1", "v1_1"); - response.addHeader("n1", "v1_2"); - response.addHeader("n2", "v2"); - - Assert.assertEquals(2, headers.size()); - Assert.assertThat(headers.getAll("n1"), Matchers.contains("v1_1", "v1_2")); - Assert.assertThat(headers.getAll("n2"), Matchers.contains("v2")); - } - - @Test - public void setHeader() { - response.setHeader("n1", "v1_1"); - response.setHeader("n1", "v1_2"); - response.setHeader("n2", "v2"); - - Assert.assertEquals(2, headers.size()); - Assert.assertThat(headers.getAll("n1"), Matchers.contains("v1_2")); - Assert.assertThat(headers.getAll("n2"), Matchers.contains("v2")); - } - - @Test - public void getStatus() { - Assert.assertEquals(123, response.getStatus()); - } - - @Test - public void getContentType() { - headers.set(HttpHeaders.CONTENT_TYPE, "json"); - Assert.assertEquals("json", response.getContentType()); - } - - @Test - public void getHeader() { - headers.set(HttpHeaders.CONTENT_TYPE, "json"); - Assert.assertEquals("json", response.getHeader(HttpHeaders.CONTENT_TYPE)); - } - - @Test - public void getHeaders() { - headers.add("h1", "h1_1"); - headers.add("h1", "h1_2"); - - Assert.assertThat(response.getHeaders("h1"), Matchers.contains("h1_1", "h1_2")); - } - - @Test - public void getHeaderNames() { - headers.add("h1", "h1"); - headers.add("h2", "h2"); - - Assert.assertThat(response.getHeaderNames(), Matchers.contains("h1", "h2")); - } - - @Test - public void flushBuffer_sameContext() throws IOException { - response.flushBuffer(); - - Assert.assertFalse(runOnContextInvoked); - } - - @Test - public void flushBuffer_diffContext() throws IOException { - new Expectations() { - { - Vertx.currentContext(); - result = null; - } - }; - response.flushBuffer(); - - Assert.assertTrue(runOnContextInvoked); - } - - @Test - public void internalFlushBufferNoBody() throws IOException { - response.internalFlushBuffer(); - - Assert.assertFalse(flushWithBody); - } - - @Test - public void internalFlushBufferWithBody() throws IOException { - response.setBodyBuffer(Buffer.buffer()); - response.internalFlushBuffer(); - - Assert.assertTrue(flushWithBody); - } - - @Test - public void prepareSendPartHeader_update(@Mocked Part part) { - new Expectations() { - { - part.getContentType(); - result = "type"; - part.getSubmittedFileName(); - result = "测 试"; - } - }; - DownloadUtils.prepareDownloadHeader(response, part); - - Assert.assertTrue(serverResponse.isChunked()); - Assert.assertEquals("type", response.getHeader(HttpHeaders.CONTENT_TYPE)); - Assert.assertEquals( - "attachment;filename=%E6%B5%8B%20%20%20%20%20%E8%AF%95;filename*=utf-8''%E6%B5%8B%20%20%20%20%20%E8%AF%95", - response.getHeader(HttpHeaders.CONTENT_DISPOSITION)); - } - - @Test - public void prepareSendPartHeader_notUpdate(@Mocked Part part) { - headers.add(HttpHeaders.CONTENT_LENGTH, "10"); - headers.add(HttpHeaders.CONTENT_TYPE, "type"); - headers.add(HttpHeaders.CONTENT_DISPOSITION, "disposition"); - - DownloadUtils.prepareDownloadHeader(response, part); - - Assert.assertFalse(serverResponse.isChunked()); - Assert.assertEquals("type", response.getHeader(HttpHeaders.CONTENT_TYPE)); - Assert.assertEquals("disposition", response.getHeader(HttpHeaders.CONTENT_DISPOSITION)); - } - - @Test - public void sendPart_openInputStreamFailed(@Mocked Part part) - throws IOException, InterruptedException, ExecutionException { - IOException ioException = new IOException("forbid open stream"); - new Expectations() { - { - part.getInputStream(); - result = ioException; - } - }; - - CompletableFuture future = response.sendPart(part); - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.sameInstance(ioException)); - - future.get(); - } - - @Test - public void sendPart_testPartIsNull(@Mocked Part part) throws InterruptedException, ExecutionException { - CompletableFuture future1 = response.sendPart(null); - Assert.assertNull(future1.get()); - } - - @Test - public void sendPart_inputStreamBreak(@Mocked Part part, @Mocked InputStream inputStream) - throws IOException, InterruptedException, ExecutionException { - IOException ioException = new IOException("forbid read"); - new Expectations() { - { - part.getInputStream(); - result = inputStream; - inputStream.read((byte[]) any); - result = ioException; - } - }; - - CompletableFuture future = response.sendPart(part); - - expectedException.expect(ExecutionException.class); - expectedException.expectCause(Matchers.sameInstance(ioException)); - - future.get(); - } - - @Test - public void sendPart_ReadStreamPart(@Mocked ReadStreamPart part) { - CompletableFuture future = new CompletableFuture<>(); - new MockUp() { - @Mock - CompletableFuture toWriteStream(WriteStream writeStream, Handler throwableHandler) { - return future; - } - }; - - Assert.assertSame(future, response.sendPart(part)); - } - - @Test - public void sendPart_succ(@Mocked Part part, @Mocked InputStream inputStream) - throws IOException, InterruptedException, ExecutionException { - new Expectations() { - { - part.getInputStream(); - result = inputStream; - inputStream.read((byte[]) any); - result = -1; - } - }; - - CompletableFuture future = response.sendPart(part); - - Assert.assertNull(future.get()); - } - - @Test - public void clearPartResource_deleteFile() throws IOException { - File file = new File("target", UUID.randomUUID().toString() + ".txt"); - FileUtils.write(file, "content", StandardCharsets.UTF_8); - FilePart part = new FilePart(null, file).setDeleteAfterFinished(true); - - Assert.assertTrue(file.exists()); - DownloadUtils.clearPartResource(part); - Assert.assertFalse(file.exists()); - } - - @Test - public void clearPartResource_notDeleteFile() throws IOException { - File file = new File("target", UUID.randomUUID().toString() + ".txt"); - FileUtils.write(file, "content", StandardCharsets.UTF_8); - FilePart part = new FilePart(null, file); - - Assert.assertTrue(file.exists()); - DownloadUtils.clearPartResource(part); - Assert.assertTrue(file.exists()); - - file.delete(); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpClientMetrics.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpClientMetrics.java index df13b60bf80..7049fb9aa78 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpClientMetrics.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpClientMetrics.java @@ -20,7 +20,6 @@ import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultRequestMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultTcpSocketMetric; -import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -35,6 +34,7 @@ import mockit.Mock; import mockit.MockUp; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestDefaultHttpClientMetrics { @Mocked @@ -138,19 +138,19 @@ public void setup() { @Test public void createMetrics() { - Assert.assertNotSame(clientMetrics_a, clientMetrics_b); + Assertions.assertNotSame(clientMetrics_a, clientMetrics_b); } @Test public void createEndpoint() { - Assert.assertSame(endpointMetric_a_1, endpointMetric_b_1); - Assert.assertNotSame(endpointMetric_a_1, endpointMetric_a_2); + Assertions.assertSame(endpointMetric_a_1, endpointMetric_b_1); + Assertions.assertNotSame(endpointMetric_a_1, endpointMetric_a_2); - Assert.assertNotSame(endpointMetric_a_2, endpointMetric_b_1); - Assert.assertSame(endpointMetric_a_2, endpointMetric_b_2); + Assertions.assertNotSame(endpointMetric_a_2, endpointMetric_b_1); + Assertions.assertSame(endpointMetric_a_2, endpointMetric_b_2); - Assert.assertEquals(2, endpointMetric_a_1.getCurrentConnectionCount()); - Assert.assertEquals(2, endpointMetric_a_2.getCurrentConnectionCount()); + Assertions.assertEquals(2, endpointMetric_a_1.getCurrentConnectionCount()); + Assertions.assertEquals(2, endpointMetric_a_2.getCurrentConnectionCount()); } @Test @@ -163,9 +163,9 @@ public void expire() { nanoTime = 13; defaultVertxMetrics.getClientEndpointMetricManager().onCheckClientEndpointMetricExpired(0); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("http://" + address1.toString())); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("http://" + address2.toString())); clientMetrics_b.disconnected(socketMetric_b_1, null); @@ -173,95 +173,95 @@ public void expire() { nanoTime = 23; defaultVertxMetrics.getClientEndpointMetricManager().onCheckClientEndpointMetricExpired(0); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("http://" + address1.toString())); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("http://" + address2.toString())); nanoTime = 24; defaultVertxMetrics.getClientEndpointMetricManager().onCheckClientEndpointMetricExpired(0); - Assert + Assertions .assertNull(defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric(address1.toString())); - Assert + Assertions .assertNull(defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric(address2.toString())); } @Test public void connect() { { - Assert.assertSame(endpointMetric_a_1, socketMetric_a_1.getEndpointMetric()); - Assert.assertTrue(socketMetric_a_1.isConnected()); - Assert.assertEquals(1, socketMetric_a_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(0, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(2, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_a_1, socketMetric_a_1.getEndpointMetric()); + Assertions.assertTrue(socketMetric_a_1.isConnected()); + Assertions.assertEquals(1, socketMetric_a_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(0, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(2, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 2; clientMetrics_a.disconnected(socketMetric_a_1, null); - Assert.assertEquals(2, ((DefaultClientEndpointMetric) endpointMetric_a_1).getLastNanoTime()); - Assert.assertFalse(socketMetric_a_1.isConnected()); - Assert.assertEquals(1, socketMetric_a_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(2, ((DefaultClientEndpointMetric) endpointMetric_a_1).getLastNanoTime()); + Assertions.assertFalse(socketMetric_a_1.isConnected()); + Assertions.assertEquals(1, socketMetric_a_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); } { - Assert.assertSame(endpointMetric_a_2, socketMetric_a_2.getEndpointMetric()); - Assert.assertTrue(socketMetric_a_2.isConnected()); - Assert.assertEquals(1, socketMetric_a_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(0, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(2, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_a_2, socketMetric_a_2.getEndpointMetric()); + Assertions.assertTrue(socketMetric_a_2.isConnected()); + Assertions.assertEquals(1, socketMetric_a_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(0, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(2, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 4; clientMetrics_a.disconnected(socketMetric_a_2, null); - Assert.assertEquals(4, ((DefaultClientEndpointMetric) endpointMetric_a_2).getLastNanoTime()); - Assert.assertFalse(socketMetric_a_2.isConnected()); - Assert.assertEquals(1, socketMetric_a_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(4, ((DefaultClientEndpointMetric) endpointMetric_a_2).getLastNanoTime()); + Assertions.assertFalse(socketMetric_a_2.isConnected()); + Assertions.assertEquals(1, socketMetric_a_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); } { - Assert.assertSame(endpointMetric_b_1, socketMetric_b_1.getEndpointMetric()); - Assert.assertTrue(socketMetric_b_1.isConnected()); - Assert.assertEquals(1, socketMetric_b_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_b_1, socketMetric_b_1.getEndpointMetric()); + Assertions.assertTrue(socketMetric_b_1.isConnected()); + Assertions.assertEquals(1, socketMetric_b_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 6; clientMetrics_b.disconnected(socketMetric_b_1, null); - Assert.assertEquals(6, ((DefaultClientEndpointMetric) endpointMetric_b_1).getLastNanoTime()); - Assert.assertFalse(socketMetric_b_1.isConnected()); - Assert.assertEquals(1, socketMetric_b_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(2, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(0, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(6, ((DefaultClientEndpointMetric) endpointMetric_b_1).getLastNanoTime()); + Assertions.assertFalse(socketMetric_b_1.isConnected()); + Assertions.assertEquals(1, socketMetric_b_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(2, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(0, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); } { - Assert.assertSame(endpointMetric_b_2, socketMetric_b_2.getEndpointMetric()); - Assert.assertTrue(socketMetric_b_2.isConnected()); - Assert.assertEquals(1, socketMetric_b_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_b_2, socketMetric_b_2.getEndpointMetric()); + Assertions.assertTrue(socketMetric_b_2.isConnected()); + Assertions.assertEquals(1, socketMetric_b_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 7; clientMetrics_b.disconnected(socketMetric_b_2, null); - Assert.assertEquals(7, ((DefaultClientEndpointMetric) endpointMetric_b_2).getLastNanoTime()); - Assert.assertFalse(socketMetric_b_2.isConnected()); - Assert.assertEquals(1, socketMetric_b_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(2, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(0, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(7, ((DefaultClientEndpointMetric) endpointMetric_b_2).getLastNanoTime()); + Assertions.assertFalse(socketMetric_b_2.isConnected()); + Assertions.assertEquals(1, socketMetric_b_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(2, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(0, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); } } @@ -287,10 +287,10 @@ public void bytesReadAndWritten() { clientMetrics_b.bytesRead(socketMetric, address2, 1); clientMetrics_b.bytesWritten(socketMetric, address2, 1); - Assert.assertEquals(2, endpointMetric_a_1.getBytesRead()); - Assert.assertEquals(2, endpointMetric_a_2.getBytesRead()); - Assert.assertEquals(2, endpointMetric_a_1.getBytesWritten()); - Assert.assertEquals(2, endpointMetric_a_2.getBytesWritten()); + Assertions.assertEquals(2, endpointMetric_a_1.getBytesRead()); + Assertions.assertEquals(2, endpointMetric_a_2.getBytesRead()); + Assertions.assertEquals(2, endpointMetric_a_1.getBytesWritten()); + Assertions.assertEquals(2, endpointMetric_a_2.getBytesWritten()); } @Test @@ -302,7 +302,7 @@ public void requestBegin(@Mocked HttpRequest request) { nanoTime = 3; clientMetrics_a_1.requestEnd(requestMetric); - Assert.assertEquals(2, requestMetric.getRequestBeginTime()); - Assert.assertEquals(3, requestMetric.getRequestEndTime()); + Assertions.assertEquals(2, requestMetric.getRequestBeginTime()); + Assertions.assertEquals(3, requestMetric.getRequestEndTime()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java index 092c52849cd..d8cbc40c95b 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultHttpServerMetrics.java @@ -21,20 +21,16 @@ import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultTcpSocketMetric; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; -import io.vertx.core.http.HttpServer; import io.vertx.core.http.HttpServerOptions; import io.vertx.core.net.SocketAddress; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestDefaultHttpServerMetrics { - @Mocked - Vertx vertx; VertxOptions vertxOptions = new VertxOptions(); @@ -42,21 +38,9 @@ public class TestDefaultHttpServerMetrics { DefaultVertxMetrics defaultVertxMetrics; - @Mocked - HttpServer listen1_server1; - - @Mocked - HttpServer listen1_server2; - @Mocked SocketAddress listen1_addr; - @Mocked - HttpServer listen2_server1; - - @Mocked - HttpServer listen2_server2; - @Mocked SocketAddress listen2_addr; @@ -121,11 +105,11 @@ public void createMetrics() { instances.put(metrics_listen1_server2, null); instances.put(metrics_listen2_server1, null); instances.put(metrics_listen2_server2, null); - Assert.assertEquals(4, instances.size()); + Assertions.assertEquals(4, instances.size()); - Assert.assertSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen1_server2.getEndpointMetric()); - Assert.assertNotSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen2_server1.getEndpointMetric()); - Assert.assertSame(metrics_listen2_server1.getEndpointMetric(), metrics_listen2_server2.getEndpointMetric()); + Assertions.assertSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen1_server2.getEndpointMetric()); + Assertions.assertNotSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen2_server1.getEndpointMetric()); + Assertions.assertSame(metrics_listen2_server1.getEndpointMetric(), metrics_listen2_server2.getEndpointMetric()); } @Test @@ -136,16 +120,16 @@ public void connectionCount() { instances.put(socketMetric_listen2_1, null); instances.put(socketMetric_listen2_2, null); instances.put(socketMetric_listen2_3, null); - Assert.assertEquals(5, instances.size()); + Assertions.assertEquals(5, instances.size()); - Assert.assertTrue(socketMetric_listen1_1.isConnected()); - Assert.assertTrue(socketMetric_listen1_2.isConnected()); - Assert.assertTrue(socketMetric_listen2_1.isConnected()); - Assert.assertTrue(socketMetric_listen2_2.isConnected()); - Assert.assertTrue(socketMetric_listen2_3.isConnected()); + Assertions.assertTrue(socketMetric_listen1_1.isConnected()); + Assertions.assertTrue(socketMetric_listen1_2.isConnected()); + Assertions.assertTrue(socketMetric_listen2_1.isConnected()); + Assertions.assertTrue(socketMetric_listen2_2.isConnected()); + Assertions.assertTrue(socketMetric_listen2_3.isConnected()); - Assert.assertEquals(2, endpointMetric1.getCurrentConnectionCount()); - Assert.assertEquals(3, endpointMetric2.getCurrentConnectionCount()); + Assertions.assertEquals(2, endpointMetric1.getCurrentConnectionCount()); + Assertions.assertEquals(3, endpointMetric2.getCurrentConnectionCount()); // disconnect metrics_listen1_server1.disconnected(socketMetric_listen1_1, anyRemoteAddr); @@ -154,14 +138,14 @@ public void connectionCount() { metrics_listen2_server2.disconnected(socketMetric_listen2_2, anyRemoteAddr); metrics_listen2_server2.disconnected(socketMetric_listen2_3, anyRemoteAddr); - Assert.assertFalse(socketMetric_listen1_1.isConnected()); - Assert.assertFalse(socketMetric_listen1_2.isConnected()); - Assert.assertFalse(socketMetric_listen2_1.isConnected()); - Assert.assertFalse(socketMetric_listen2_2.isConnected()); - Assert.assertFalse(socketMetric_listen2_3.isConnected()); + Assertions.assertFalse(socketMetric_listen1_1.isConnected()); + Assertions.assertFalse(socketMetric_listen1_2.isConnected()); + Assertions.assertFalse(socketMetric_listen2_1.isConnected()); + Assertions.assertFalse(socketMetric_listen2_2.isConnected()); + Assertions.assertFalse(socketMetric_listen2_3.isConnected()); - Assert.assertEquals(0, endpointMetric1.getCurrentConnectionCount()); - Assert.assertEquals(0, endpointMetric2.getCurrentConnectionCount()); + Assertions.assertEquals(0, endpointMetric1.getCurrentConnectionCount()); + Assertions.assertEquals(0, endpointMetric2.getCurrentConnectionCount()); } @Test @@ -172,8 +156,8 @@ public void bytesRead() { metrics_listen2_server2.bytesRead(socketMetric_listen2_2, anyRemoteAddr, 4); metrics_listen2_server2.bytesRead(socketMetric_listen2_3, anyRemoteAddr, 5); - Assert.assertEquals(3, endpointMetric1.getBytesRead()); - Assert.assertEquals(12, endpointMetric2.getBytesRead()); + Assertions.assertEquals(3, endpointMetric1.getBytesRead()); + Assertions.assertEquals(12, endpointMetric2.getBytesRead()); } @Test @@ -184,7 +168,7 @@ public void bytesWritten() { metrics_listen2_server2.bytesWritten(socketMetric_listen2_2, anyRemoteAddr, 4); metrics_listen2_server2.bytesWritten(socketMetric_listen2_3, anyRemoteAddr, 5); - Assert.assertEquals(3, endpointMetric1.getBytesWritten()); - Assert.assertEquals(12, endpointMetric2.getBytesWritten()); + Assertions.assertEquals(3, endpointMetric1.getBytesWritten()); + Assertions.assertEquals(12, endpointMetric2.getBytesWritten()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpClientMetrics.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpClientMetrics.java index 6ad08cf4e0c..8c893b60ca9 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpClientMetrics.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpClientMetrics.java @@ -19,7 +19,6 @@ import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultClientEndpointMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultTcpSocketMetric; -import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -32,6 +31,7 @@ import mockit.Mock; import mockit.MockUp; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestDefaultTcpClientMetrics { @Mocked @@ -115,19 +115,19 @@ public void setup() { @Test public void createMetrics() { - Assert.assertNotSame(clientMetrics_a, clientMetrics_b); + Assertions.assertNotSame(clientMetrics_a, clientMetrics_b); } @Test public void createEndpoint() { - Assert.assertSame(endpointMetric_a_1, endpointMetric_b_1); - Assert.assertNotSame(endpointMetric_a_1, endpointMetric_a_2); + Assertions.assertSame(endpointMetric_a_1, endpointMetric_b_1); + Assertions.assertNotSame(endpointMetric_a_1, endpointMetric_a_2); - Assert.assertNotSame(endpointMetric_a_2, endpointMetric_b_1); - Assert.assertSame(endpointMetric_a_2, endpointMetric_b_2); + Assertions.assertNotSame(endpointMetric_a_2, endpointMetric_b_1); + Assertions.assertSame(endpointMetric_a_2, endpointMetric_b_2); - Assert.assertEquals(2, endpointMetric_a_1.getCurrentConnectionCount()); - Assert.assertEquals(2, endpointMetric_a_2.getCurrentConnectionCount()); + Assertions.assertEquals(2, endpointMetric_a_1.getCurrentConnectionCount()); + Assertions.assertEquals(2, endpointMetric_a_2.getCurrentConnectionCount()); } @Test @@ -140,9 +140,9 @@ public void expire() { nanoTime = 13; defaultVertxMetrics.getClientEndpointMetricManager().onCheckClientEndpointMetricExpired(0); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("tcp://" + address1.toString())); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("tcp://" + address2.toString())); clientMetrics_b.disconnected(socketMetric_b_1, null); @@ -150,95 +150,95 @@ public void expire() { nanoTime = 23; defaultVertxMetrics.getClientEndpointMetricManager().onCheckClientEndpointMetricExpired(0); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("tcp://" + address1.toString())); - Assert.assertNotNull( + Assertions.assertNotNull( defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric("tcp://" + address2.toString())); nanoTime = 24; defaultVertxMetrics.getClientEndpointMetricManager().onCheckClientEndpointMetricExpired(0); - Assert + Assertions .assertNull(defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric(address1.toString())); - Assert + Assertions .assertNull(defaultVertxMetrics.getClientEndpointMetricManager().getClientEndpointMetric(address2.toString())); } @Test public void connect() { { - Assert.assertSame(endpointMetric_a_1, socketMetric_a_1.getEndpointMetric()); - Assert.assertTrue(socketMetric_a_1.isConnected()); - Assert.assertEquals(1, socketMetric_a_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(0, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(2, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_a_1, socketMetric_a_1.getEndpointMetric()); + Assertions.assertTrue(socketMetric_a_1.isConnected()); + Assertions.assertEquals(1, socketMetric_a_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(0, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(2, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 2; clientMetrics_a.disconnected(socketMetric_a_1, null); - Assert.assertEquals(2, ((DefaultClientEndpointMetric) endpointMetric_a_1).getLastNanoTime()); - Assert.assertFalse(socketMetric_a_1.isConnected()); - Assert.assertEquals(1, socketMetric_a_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(2, ((DefaultClientEndpointMetric) endpointMetric_a_1).getLastNanoTime()); + Assertions.assertFalse(socketMetric_a_1.isConnected()); + Assertions.assertEquals(1, socketMetric_a_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_a_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_a_1.getEndpointMetric().getCurrentConnectionCount()); } { - Assert.assertSame(endpointMetric_a_2, socketMetric_a_2.getEndpointMetric()); - Assert.assertTrue(socketMetric_a_2.isConnected()); - Assert.assertEquals(1, socketMetric_a_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(0, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(2, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_a_2, socketMetric_a_2.getEndpointMetric()); + Assertions.assertTrue(socketMetric_a_2.isConnected()); + Assertions.assertEquals(1, socketMetric_a_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(0, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(2, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 4; clientMetrics_a.disconnected(socketMetric_a_2, null); - Assert.assertEquals(4, ((DefaultClientEndpointMetric) endpointMetric_a_2).getLastNanoTime()); - Assert.assertFalse(socketMetric_a_2.isConnected()); - Assert.assertEquals(1, socketMetric_a_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(4, ((DefaultClientEndpointMetric) endpointMetric_a_2).getLastNanoTime()); + Assertions.assertFalse(socketMetric_a_2.isConnected()); + Assertions.assertEquals(1, socketMetric_a_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_a_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_a_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_a_2.getEndpointMetric().getCurrentConnectionCount()); } { - Assert.assertSame(endpointMetric_b_1, socketMetric_b_1.getEndpointMetric()); - Assert.assertTrue(socketMetric_b_1.isConnected()); - Assert.assertEquals(1, socketMetric_b_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_b_1, socketMetric_b_1.getEndpointMetric()); + Assertions.assertTrue(socketMetric_b_1.isConnected()); + Assertions.assertEquals(1, socketMetric_b_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 6; clientMetrics_b.disconnected(socketMetric_b_1, null); - Assert.assertEquals(6, ((DefaultClientEndpointMetric) endpointMetric_b_1).getLastNanoTime()); - Assert.assertFalse(socketMetric_b_1.isConnected()); - Assert.assertEquals(1, socketMetric_b_1.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); - Assert.assertEquals(2, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(0, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(6, ((DefaultClientEndpointMetric) endpointMetric_b_1).getLastNanoTime()); + Assertions.assertFalse(socketMetric_b_1.isConnected()); + Assertions.assertEquals(1, socketMetric_b_1.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_1.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(2, socketMetric_b_1.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(0, socketMetric_b_1.getEndpointMetric().getCurrentConnectionCount()); } { - Assert.assertSame(endpointMetric_b_2, socketMetric_b_2.getEndpointMetric()); - Assert.assertTrue(socketMetric_b_2.isConnected()); - Assert.assertEquals(1, socketMetric_b_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(1, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(1, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertSame(endpointMetric_b_2, socketMetric_b_2.getEndpointMetric()); + Assertions.assertTrue(socketMetric_b_2.isConnected()); + Assertions.assertEquals(1, socketMetric_b_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(1, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(1, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); nanoTime = 7; clientMetrics_b.disconnected(socketMetric_b_2, null); - Assert.assertEquals(7, ((DefaultClientEndpointMetric) endpointMetric_b_2).getLastNanoTime()); - Assert.assertFalse(socketMetric_b_2.isConnected()); - Assert.assertEquals(1, socketMetric_b_2.getConnectedTime()); - Assert.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); - Assert.assertEquals(2, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); - Assert.assertEquals(0, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); + Assertions.assertEquals(7, ((DefaultClientEndpointMetric) endpointMetric_b_2).getLastNanoTime()); + Assertions.assertFalse(socketMetric_b_2.isConnected()); + Assertions.assertEquals(1, socketMetric_b_2.getConnectedTime()); + Assertions.assertEquals(2, socketMetric_b_2.getEndpointMetric().getConnectCount()); + Assertions.assertEquals(2, socketMetric_b_2.getEndpointMetric().getDisconnectCount()); + Assertions.assertEquals(0, socketMetric_b_2.getEndpointMetric().getCurrentConnectionCount()); } } @@ -256,9 +256,9 @@ public void bytesReadAndWritten() { clientMetrics_b.bytesRead(socketMetric_b_2, address2, 1); clientMetrics_b.bytesWritten(socketMetric_b_2, address2, 1); - Assert.assertEquals(2, endpointMetric_a_1.getBytesRead()); - Assert.assertEquals(2, endpointMetric_a_2.getBytesRead()); - Assert.assertEquals(2, endpointMetric_a_1.getBytesWritten()); - Assert.assertEquals(2, endpointMetric_a_2.getBytesWritten()); + Assertions.assertEquals(2, endpointMetric_a_1.getBytesRead()); + Assertions.assertEquals(2, endpointMetric_a_2.getBytesRead()); + Assertions.assertEquals(2, endpointMetric_a_1.getBytesWritten()); + Assertions.assertEquals(2, endpointMetric_a_2.getBytesWritten()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpServerMetrics.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpServerMetrics.java index 8eda6331774..f9b93f1ce99 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpServerMetrics.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultTcpServerMetrics.java @@ -21,19 +21,16 @@ import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultEndpointMetric; import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultTcpSocketMetric; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.net.NetServerOptions; import io.vertx.core.net.SocketAddress; import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestDefaultTcpServerMetrics { - @Mocked - Vertx vertx; VertxOptions vertxOptions = new VertxOptions(); @@ -108,11 +105,11 @@ public void createMetrics() { instances.put(metrics_listen1_server2, null); instances.put(metrics_listen2_server1, null); instances.put(metrics_listen2_server2, null); - Assert.assertEquals(4, instances.size()); + Assertions.assertEquals(4, instances.size()); - Assert.assertSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen1_server2.getEndpointMetric()); - Assert.assertNotSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen2_server1.getEndpointMetric()); - Assert.assertSame(metrics_listen2_server1.getEndpointMetric(), metrics_listen2_server2.getEndpointMetric()); + Assertions.assertSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen1_server2.getEndpointMetric()); + Assertions.assertNotSame(metrics_listen1_server1.getEndpointMetric(), metrics_listen2_server1.getEndpointMetric()); + Assertions.assertSame(metrics_listen2_server1.getEndpointMetric(), metrics_listen2_server2.getEndpointMetric()); } @Test @@ -123,16 +120,16 @@ public void connectionCount() { instances.put(socketMetric_listen2_1, null); instances.put(socketMetric_listen2_2, null); instances.put(socketMetric_listen2_3, null); - Assert.assertEquals(5, instances.size()); + Assertions.assertEquals(5, instances.size()); - Assert.assertTrue(socketMetric_listen1_1.isConnected()); - Assert.assertTrue(socketMetric_listen1_2.isConnected()); - Assert.assertTrue(socketMetric_listen2_1.isConnected()); - Assert.assertTrue(socketMetric_listen2_2.isConnected()); - Assert.assertTrue(socketMetric_listen2_3.isConnected()); + Assertions.assertTrue(socketMetric_listen1_1.isConnected()); + Assertions.assertTrue(socketMetric_listen1_2.isConnected()); + Assertions.assertTrue(socketMetric_listen2_1.isConnected()); + Assertions.assertTrue(socketMetric_listen2_2.isConnected()); + Assertions.assertTrue(socketMetric_listen2_3.isConnected()); - Assert.assertEquals(2, endpointMetric1.getCurrentConnectionCount()); - Assert.assertEquals(3, endpointMetric2.getCurrentConnectionCount()); + Assertions.assertEquals(2, endpointMetric1.getCurrentConnectionCount()); + Assertions.assertEquals(3, endpointMetric2.getCurrentConnectionCount()); // disconnect metrics_listen1_server1.disconnected(socketMetric_listen1_1, anyRemoteAddr); @@ -141,14 +138,14 @@ public void connectionCount() { metrics_listen2_server2.disconnected(socketMetric_listen2_2, anyRemoteAddr); metrics_listen2_server2.disconnected(socketMetric_listen2_3, anyRemoteAddr); - Assert.assertFalse(socketMetric_listen1_1.isConnected()); - Assert.assertFalse(socketMetric_listen1_2.isConnected()); - Assert.assertFalse(socketMetric_listen2_1.isConnected()); - Assert.assertFalse(socketMetric_listen2_2.isConnected()); - Assert.assertFalse(socketMetric_listen2_3.isConnected()); + Assertions.assertFalse(socketMetric_listen1_1.isConnected()); + Assertions.assertFalse(socketMetric_listen1_2.isConnected()); + Assertions.assertFalse(socketMetric_listen2_1.isConnected()); + Assertions.assertFalse(socketMetric_listen2_2.isConnected()); + Assertions.assertFalse(socketMetric_listen2_3.isConnected()); - Assert.assertEquals(0, endpointMetric1.getCurrentConnectionCount()); - Assert.assertEquals(0, endpointMetric2.getCurrentConnectionCount()); + Assertions.assertEquals(0, endpointMetric1.getCurrentConnectionCount()); + Assertions.assertEquals(0, endpointMetric2.getCurrentConnectionCount()); } @Test @@ -159,8 +156,8 @@ public void bytesRead() { metrics_listen2_server2.bytesRead(socketMetric_listen2_2, anyRemoteAddr, 4); metrics_listen2_server2.bytesRead(socketMetric_listen2_3, anyRemoteAddr, 5); - Assert.assertEquals(3, endpointMetric1.getBytesRead()); - Assert.assertEquals(12, endpointMetric2.getBytesRead()); + Assertions.assertEquals(3, endpointMetric1.getBytesRead()); + Assertions.assertEquals(12, endpointMetric2.getBytesRead()); } @Test @@ -171,7 +168,7 @@ public void bytesWritten() { metrics_listen2_server2.bytesWritten(socketMetric_listen2_2, anyRemoteAddr, 4); metrics_listen2_server2.bytesWritten(socketMetric_listen2_3, anyRemoteAddr, 5); - Assert.assertEquals(3, endpointMetric1.getBytesWritten()); - Assert.assertEquals(12, endpointMetric2.getBytesWritten()); + Assertions.assertEquals(3, endpointMetric1.getBytesWritten()); + Assertions.assertEquals(12, endpointMetric2.getBytesWritten()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultVertxMetricsFactory.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultVertxMetricsFactory.java index a08a645325e..ccc67374c82 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultVertxMetricsFactory.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestDefaultVertxMetricsFactory.java @@ -16,34 +16,28 @@ */ package org.apache.servicecomb.foundation.vertx.metrics; -import org.junit.Assert; import org.junit.Test; -import io.vertx.core.Vertx; import io.vertx.core.VertxOptions; import io.vertx.core.metrics.MetricsOptions; import io.vertx.core.spi.metrics.VertxMetrics; -import mockit.Mocked; +import org.junit.jupiter.api.Assertions; public class TestDefaultVertxMetricsFactory { - @Mocked - Vertx vertx; VertxOptions options = new VertxOptions(); DefaultVertxMetricsFactory factory = new DefaultVertxMetricsFactory(); - @SuppressWarnings("deprecation") @Test public void metrics() { MetricsOptions metricsOptions = factory.newOptions(); options.setMetricsOptions(metricsOptions); VertxMetrics vertxMetrics = factory.metrics(options); - Assert.assertSame(factory, metricsOptions.getFactory()); - Assert.assertTrue(metricsOptions.isEnabled()); + Assertions.assertTrue(metricsOptions.isEnabled()); - Assert.assertSame(factory.getVertxMetrics(), vertxMetrics); - Assert.assertTrue(vertxMetrics.isMetricsEnabled()); + Assertions.assertSame(factory.getVertxMetrics(), vertxMetrics); + Assertions.assertTrue(vertxMetrics.isMetricsEnabled()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestMetricsOptionsEx.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestMetricsOptionsEx.java index 19f3241ac04..ced6ecb2996 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestMetricsOptionsEx.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/metrics/TestMetricsOptionsEx.java @@ -18,30 +18,30 @@ import java.util.concurrent.TimeUnit; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestMetricsOptionsEx { MetricsOptionsEx metricsOptionsEx = new MetricsOptionsEx(); @Test public void interval() { - Assert.assertEquals(TimeUnit.MINUTES.toMillis(1), + Assertions.assertEquals(TimeUnit.MINUTES.toMillis(1), metricsOptionsEx.getCheckClientEndpointMetricIntervalInMilliseconds()); metricsOptionsEx.setCheckClientEndpointMetricIntervalInMinute(2); - Assert.assertEquals(TimeUnit.MINUTES.toMillis(2), + Assertions.assertEquals(TimeUnit.MINUTES.toMillis(2), metricsOptionsEx.getCheckClientEndpointMetricIntervalInMilliseconds()); } @Test public void expired() { - Assert.assertEquals(TimeUnit.MINUTES.toNanos(15), metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano()); + Assertions.assertEquals(TimeUnit.MINUTES.toNanos(15), metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano()); metricsOptionsEx.setCheckClientEndpointMetricExpiredInNano(10); - Assert.assertEquals(10, metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano()); + Assertions.assertEquals(10, metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano()); metricsOptionsEx.setCheckClientEndpointMetricExpiredInMinute(60); - Assert.assertEquals(TimeUnit.MINUTES.toNanos(60), metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano()); + Assertions.assertEquals(TimeUnit.MINUTES.toNanos(60), metricsOptionsEx.getCheckClientEndpointMetricExpiredInNano()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpParser.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpParser.java index 167ff0406cd..5a1f7b4af12 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpParser.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpParser.java @@ -19,10 +19,10 @@ import java.io.UnsupportedEncodingException; import org.apache.servicecomb.foundation.vertx.tcp.TcpOutputStream; -import org.junit.Assert; -import org.junit.Test; import io.vertx.core.buffer.Buffer; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class TestTcpParser { long msgId; @@ -33,13 +33,10 @@ public class TestTcpParser { @Test public void test() throws UnsupportedEncodingException { - TcpBufferHandler output = new TcpBufferHandler() { - @Override - public void handle(long _msgId, Buffer _headerBuffer, Buffer _bodyBuffer) { - msgId = _msgId; - headerBuffer = _headerBuffer; - bodyBuffer = _bodyBuffer; - } + TcpBufferHandler output = (_msgId, _headerBuffer, _bodyBuffer) -> { + msgId = _msgId; + headerBuffer = _headerBuffer; + bodyBuffer = _bodyBuffer; }; byte[] header = new byte[] {1, 2, 3}; @@ -54,8 +51,8 @@ public void handle(long _msgId, Buffer _headerBuffer, Buffer _bodyBuffer) { parser.handle(os.getBuffer()); os.close(); - Assert.assertEquals(1, msgId); - Assert.assertArrayEquals(header, headerBuffer.getBytes()); - Assert.assertArrayEquals(body, bodyBuffer.getBytes()); + Assertions.assertEquals(1, msgId); + Assertions.assertArrayEquals(header, headerBuffer.getBytes()); + Assertions.assertArrayEquals(body, bodyBuffer.getBytes()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServer.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServer.java deleted file mode 100644 index b95bfc30a58..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServer.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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.foundation.vertx.server; - -import java.net.InetSocketAddress; - -import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.apache.servicecomb.foundation.vertx.AsyncResultCallback; -import org.apache.servicecomb.foundation.vertx.metrics.DefaultTcpServerMetrics; -import org.apache.servicecomb.foundation.vertx.metrics.metric.DefaultServerEndpointMetric; -import org.junit.Assert; -import org.junit.Test; - -import io.vertx.core.Handler; -import io.vertx.core.Vertx; -import io.vertx.core.net.NetServer; -import io.vertx.core.net.NetServerOptions; -import io.vertx.core.net.NetSocket; -import io.vertx.core.net.impl.NetSocketImpl; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestTcpServer { - static class TcpServerForTest extends TcpServer { - public TcpServerForTest(URIEndpointObject endpointObject) { - super(endpointObject); - } - - @Override - protected TcpServerConnection createTcpServerConnection() { - return new TcpServerConnection() { - @Override - public void init(NetSocket netSocket) { - super.init(netSocket); - } - }; - } - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Test - public void testTcpServerNonSSL(@Mocked Vertx vertx, @Mocked AsyncResultCallback callback, - @Mocked NetServer netServer) { - new Expectations() { - { - vertx.createNetServer(); - result = netServer; - netServer.connectHandler((Handler) any); - netServer.listen(anyInt, anyString, (Handler) any); - } - }; - URIEndpointObject endpointObject = new URIEndpointObject("highway://127.0.0.1:6663"); - TcpServer server = new TcpServerForTest(endpointObject); - // assert done in Expectations - server.init(vertx, "", callback); - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Test - public void testTcpServerSSL(@Mocked Vertx vertx, @Mocked AsyncResultCallback callback, - @Mocked NetServer netServer) { - new Expectations() { - { - vertx.createNetServer((NetServerOptions) any); - result = netServer; - netServer.connectHandler((Handler) any); - netServer.listen(anyInt, anyString, (Handler) any); - } - }; - URIEndpointObject endpointObject = new URIEndpointObject("highway://127.0.0.1:6663?sslEnabled=true"); - TcpServer server = new TcpServerForTest(endpointObject); - // assert done in Expectations - server.init(vertx, "", callback); - } - - Handler connectHandler; - - boolean netSocketClosed; - - @SuppressWarnings({"rawtypes", "unchecked"}) - @Test - public void testConnectionLimit(@Mocked Vertx vertx, @Mocked AsyncResultCallback callback, - @Mocked NetServer netServer, @Mocked NetSocketImpl netSocket) { - DefaultServerEndpointMetric endpointMetric = new DefaultServerEndpointMetric(null); - DefaultTcpServerMetrics tcpServerMetrics = new DefaultTcpServerMetrics(endpointMetric); - - new MockUp(netServer) { - @Mock - NetServer connectHandler(Handler handler) { - connectHandler = handler; - return netServer; - } - }; - new MockUp(netSocket) { - @Mock - void close() { - netSocketClosed = true; - } - }; - new Expectations() { - { - vertx.createNetServer((NetServerOptions) any); - result = netServer; - netServer.listen(anyInt, anyString, (Handler) any); - netSocket.metrics(); - result = tcpServerMetrics; - } - }; - URIEndpointObject endpointObject = new URIEndpointObject("highway://127.0.0.1:6663?sslEnabled=true"); - TcpServer server = new TcpServerForTest(endpointObject) { - @Override - protected int getConnectionLimit() { - return 2; - } - }; - // assert done in Expectations - server.init(vertx, "", callback); - - // no problem - endpointMetric.onConnect(); - endpointMetric.onConnect(); - connectHandler.handle(netSocket); - - // reject - endpointMetric.onConnect(); - connectHandler.handle(netSocket); - Assert.assertTrue(netSocketClosed); - Assert.assertEquals(1, endpointMetric.getRejectByConnectionLimitCount()); - } -} diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServerConnection.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServerConnection.java index 3047042f2ff..ac15a8e6baf 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServerConnection.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/server/TestTcpServerConnection.java @@ -16,21 +16,24 @@ */ package org.apache.servicecomb.foundation.vertx.server; -import org.junit.Assert; -import org.junit.Test; - +import io.vertx.core.net.SocketAddress; import io.vertx.core.net.impl.NetSocketImpl; -import mockit.Mocked; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestTcpServerConnection { @Test - public void test(@Mocked NetSocketImpl netSocket) { + public void test() { + SocketAddress socketAddress = Mockito.mock(SocketAddress.class); + NetSocketImpl netSocket = Mockito.mock(NetSocketImpl.class); + Mockito.when(netSocket.remoteAddress()).thenReturn(socketAddress); TcpServerConnection connection = new TcpServerConnection(); connection.setProtocol("p"); connection.setZipName("z"); connection.init(netSocket); - Assert.assertEquals(netSocket, connection.getNetSocket()); + Assertions.assertEquals(netSocket, connection.getNetSocket()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestBufferInputStream.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestBufferInputStream.java index e51ed65fbd1..40be5d48642 100644 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestBufferInputStream.java +++ b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestBufferInputStream.java @@ -19,18 +19,17 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; +import io.vertx.core.buffer.Buffer; public class TestBufferInputStream { @@ -38,7 +37,7 @@ public class TestBufferInputStream { @Before public void setUp() throws Exception { - ByteBuf buffer = Mockito.mock(ByteBuf.class); + Buffer buffer = Mockito.mock(Buffer.class); instance = new BufferInputStream(buffer); } @@ -49,7 +48,7 @@ public void tearDown() throws Exception { @Test public void testRead() { - Assert.assertEquals(0, instance.read()); + Assertions.assertEquals(0, instance.read()); } @Test @@ -60,12 +59,12 @@ public void testReadDecorate() throws IOException { gzipOutputStream.write(text.getBytes()); gzipOutputStream.close(); - ByteBuf buffer = Unpooled.buffer(); - buffer.writeBytes(out.toByteArray()); + Buffer buffer = Buffer.buffer(); + buffer.appendBytes(out.toByteArray()); out.close(); BufferInputStream bufferInputStream = new BufferInputStream(buffer); GZIPInputStream gzipInputStream = new GZIPInputStream(bufferInputStream); - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); byte[] bufferByte = new byte[256]; int n; while ((n = gzipInputStream.read(bufferByte)) >= 0) { @@ -73,29 +72,29 @@ public void testReadDecorate() throws IOException { } gzipInputStream.close(); - Assert.assertEquals(text, sb.toString()); + Assertions.assertEquals(text, sb.toString()); } @Test - public void testReadByteArray() throws UnsupportedEncodingException { - byte[] b = "csr".getBytes("UTF-8"); - Assert.assertEquals(-1, instance.read(b)); + public void testReadByteArray() { + byte[] b = "csr".getBytes(StandardCharsets.UTF_8); + Assertions.assertEquals(-1, instance.read(b)); } @Test - public void testReadByteArrayIntInt() throws UnsupportedEncodingException { - byte[] b = "csr".getBytes("UTF-8"); - Assert.assertEquals(-1, instance.read(b, 1, 0)); + public void testReadByteArrayIntInt() { + byte[] b = "csr".getBytes(StandardCharsets.UTF_8); + Assertions.assertEquals(-1, instance.read(b, 1, 0)); } @Test public void testSkip() { - Assert.assertEquals(0, instance.skip(1)); + Assertions.assertEquals(0, instance.skip(1)); } @Test public void testAvailable() { - Assert.assertEquals(0, instance.available()); + Assertions.assertEquals(0, instance.available()); } @Test @@ -103,42 +102,42 @@ public void testClose() { try { instance.close(); } catch (Exception e) { - Assert.assertTrue(false); // This assertion is made to fail the test case in case the close() throws exception + Assertions.fail(); // This assertion is made to fail the test case in case the close() throws exception } } @Test public void testBufferInputStream() { - Assert.assertNotNull(instance); + Assertions.assertNotNull(instance); } @Test public void testReadBoolean() { - Assert.assertEquals(false, instance.readBoolean()); + Assertions.assertFalse(instance.readBoolean()); } @Test public void testReadShort() { - Assert.assertEquals(0, instance.readShort()); + Assertions.assertEquals(0, instance.readShort()); } @Test public void testReadInt() { - Assert.assertEquals(0, instance.readInt()); + Assertions.assertEquals(0, instance.readInt()); } @Test public void testReadLong() { - Assert.assertEquals(0, instance.readLong()); + Assertions.assertEquals(0, instance.readLong()); } @Test public void testGetIndex() { - Assert.assertEquals(0, instance.getIndex()); + Assertions.assertEquals(0, instance.getIndex()); } @Test public void testReadString() { - Assert.assertNotNull(instance.readString()); + Assertions.assertNotNull(instance.readString()); } } diff --git a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestPumpFromPart.java b/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestPumpFromPart.java deleted file mode 100644 index befcc2e711a..00000000000 --- a/foundations/foundation-vertx/src/test/java/org/apache/servicecomb/foundation/vertx/stream/TestPumpFromPart.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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.foundation.vertx.stream; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.concurrent.ExecutionException; - -import javax.servlet.http.Part; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.servicecomb.foundation.common.part.InputStreamPart; -import org.apache.servicecomb.foundation.vertx.stream.InputStreamToReadStream.ReadResult; -import org.hamcrest.Matchers; -import org.junit.Assert; -import org.junit.Test; - -import io.vertx.core.Context; -import io.vertx.core.Promise; -import io.vertx.core.impl.SyncContext; -import mockit.Expectations; -import mockit.Mock; -import mockit.MockUp; - -public class TestPumpFromPart { - String src = RandomStringUtils.random(100); - - boolean inputStreamClosed; - - InputStream inputStream = new ByteArrayInputStream(src.getBytes()) { - @Override - public void close() throws IOException { - super.close(); - inputStreamClosed = true; - } - }; - - Part part; - - boolean outputStreamClosed; - - BufferOutputStream outputStream; - - IOException error = new IOException(); - - Context context = new SyncContext(); - - private void run(Context context, boolean closeOutput) throws Throwable { - inputStream.reset(); - part = new InputStreamPart("name", inputStream); - - outputStream = new BufferOutputStream() { - @Override - public void close() { - super.close(); - outputStreamClosed = true; - } - }; - - new PumpFromPart(context, part).toOutputStream(outputStream, closeOutput).get(); - } - - public void do_pump_succ(Context context) throws Throwable { - run(context, true); - - Assert.assertEquals(src, outputStream.getBuffer().toString()); - Assert.assertTrue(inputStreamClosed); - Assert.assertTrue(outputStreamClosed); - } - - @Test - public void pump_succ() throws Throwable { - do_pump_succ(null); - do_pump_succ(context); - } - - public void do_pump_outputNotClose(Context context) throws Throwable { - run(context, false); - - Assert.assertEquals(src, outputStream.getBuffer().toString()); - Assert.assertFalse(outputStreamClosed); - } - - @Test - public void pump_outputNotClose() throws Throwable { - do_pump_outputNotClose(null); - do_pump_outputNotClose(context); - } - - public void pump_error(Context context) { - try { - run(context, true); - Assert.fail("must throw exception"); - } catch (Throwable e) { - Assert.assertThat(e, Matchers.instanceOf(ExecutionException.class)); - Assert.assertThat(e.getCause(), Matchers.sameInstance(error)); - } - - Assert.assertTrue(inputStreamClosed); - Assert.assertTrue(outputStreamClosed); - } - - @Test - public void pump_read_error() throws IOException { - new MockUp() { - @Mock - void readInWorker(Promise future) { - future.fail(error); - } - }; - new Expectations(IOUtils.class) { - { - IOUtils.copyLarge((InputStream) any, (OutputStream) any); - result = error; - } - }; - - pump_error(null); - Assert.assertTrue(inputStreamClosed); - Assert.assertTrue(outputStreamClosed); - - inputStreamClosed = false; - outputStreamClosed = false; - pump_error(context); - Assert.assertTrue(inputStreamClosed); - Assert.assertTrue(outputStreamClosed); - } - - @Test - public void pump_write_error() throws IOException { - new MockUp() { - @Mock - void write(byte[] b) throws IOException { - throw error; - } - }; - new Expectations(IOUtils.class) { - { - IOUtils.copyLarge((InputStream) any, (OutputStream) any); - result = error; - } - }; - - pump_error(null); - Assert.assertTrue(inputStreamClosed); - Assert.assertTrue(outputStreamClosed); - - inputStreamClosed = false; - outputStreamClosed = false; - pump_error(context); - Assert.assertTrue(inputStreamClosed); - Assert.assertTrue(outputStreamClosed); - } -} diff --git a/foundations/foundation-vertx/src/test/resources/log4j.properties b/foundations/foundation-vertx/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/foundations/foundation-vertx/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/foundations/pom.xml b/foundations/pom.xml index e995a82e375..7b3f55d334a 100644 --- a/foundations/pom.xml +++ b/foundations/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default foundations diff --git a/governance/README.md b/governance/README.md deleted file mode 100644 index bc6f83e287f..00000000000 --- a/governance/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# About Governance Module - -Governance module provides an abstraction on how to describe governance instructions for commonly used -different microservice frameworks, like Java Chassis, Go Chassis, Spring Cloud, Dubbo, etc. - -This abstraction is based on traffic marking, here is a configuration example. - -```yaml -servicecomb: - matchGroup: - matchGroup0: | - matches: - - apiPath: - exact: "/hello" - name: match0 - rateLimiting: - rateLimiting0: | - rules: - match: matchGroup0.match0 - rate: 1 -``` - -First define a traffic marking rule (match group) `servicecomb.matchGroup.matchGroup0` and detailed matches -specification. Then define governance rules for any marking rule. Marking rule id is `matchGroup0.match0`. diff --git a/governance/pom.xml b/governance/pom.xml index 1176091c0f3..3f78c36ade5 100644 --- a/governance/pom.xml +++ b/governance/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default 4.0.0 @@ -30,17 +30,21 @@ Java Chassis::Governance + + org.apache.servicecomb + foundation-common + io.github.resilience4j resilience4j-all - org.aspectj - aspectjweaver + io.github.resilience4j + resilience4j-micrometer - org.aspectj - aspectjrt + io.micrometer + micrometer-core org.apache.commons @@ -78,8 +82,19 @@ test - org.apache.servicecomb - foundation-common + io.micrometer + micrometer-registry-prometheus + test + + + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core + test diff --git a/governance/src/main/java/org/apache/servicecomb/governance/GovernanceCommonConfiguration.java b/governance/src/main/java/org/apache/servicecomb/governance/GovernanceCommonConfiguration.java new file mode 100644 index 00000000000..b5fd042a723 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/GovernanceCommonConfiguration.java @@ -0,0 +1,240 @@ +/* + * 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.governance; + +import java.util.Map; + +import org.apache.servicecomb.governance.handler.BulkheadHandler; +import org.apache.servicecomb.governance.handler.CircuitBreakerHandler; +import org.apache.servicecomb.governance.handler.FaultInjectionHandler; +import org.apache.servicecomb.governance.handler.GovernanceCacheHandler; +import org.apache.servicecomb.governance.handler.IdentifierRateLimitingHandler; +import org.apache.servicecomb.governance.handler.InstanceBulkheadHandler; +import org.apache.servicecomb.governance.handler.InstanceIsolationHandler; +import org.apache.servicecomb.governance.handler.LoadBalanceHandler; +import org.apache.servicecomb.governance.handler.MapperHandler; +import org.apache.servicecomb.governance.handler.RateLimitingHandler; +import org.apache.servicecomb.governance.handler.RetryHandler; +import org.apache.servicecomb.governance.handler.TimeLimiterHandler; +import org.apache.servicecomb.governance.handler.ext.AbstractCircuitBreakerExtension; +import org.apache.servicecomb.governance.handler.ext.AbstractInstanceIsolationExtension; +import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension; +import org.apache.servicecomb.governance.marker.RequestProcessor; +import org.apache.servicecomb.governance.marker.operator.CompareOperator; +import org.apache.servicecomb.governance.marker.operator.ContainsOperator; +import org.apache.servicecomb.governance.marker.operator.ExactOperator; +import org.apache.servicecomb.governance.marker.operator.MatchOperator; +import org.apache.servicecomb.governance.marker.operator.PrefixOperator; +import org.apache.servicecomb.governance.marker.operator.SuffixOperator; +import org.apache.servicecomb.governance.properties.BulkheadProperties; +import org.apache.servicecomb.governance.properties.CircuitBreakerProperties; +import org.apache.servicecomb.governance.properties.FaultInjectionProperties; +import org.apache.servicecomb.governance.properties.GovernanceCacheProperties; +import org.apache.servicecomb.governance.properties.IdentifierRateLimitProperties; +import org.apache.servicecomb.governance.properties.InstanceBulkheadProperties; +import org.apache.servicecomb.governance.properties.InstanceIsolationProperties; +import org.apache.servicecomb.governance.properties.LoadBalanceProperties; +import org.apache.servicecomb.governance.properties.MapperProperties; +import org.apache.servicecomb.governance.properties.MatchProperties; +import org.apache.servicecomb.governance.properties.RateLimitProperties; +import org.apache.servicecomb.governance.properties.RetryProperties; +import org.apache.servicecomb.governance.properties.TimeLimiterProperties; +import org.apache.servicecomb.governance.service.MatchersService; +import org.apache.servicecomb.governance.service.MatchersServiceImpl; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.core.instrument.MeterRegistry; + +@Configuration +public class GovernanceCommonConfiguration { + // properties configuration + @Bean + public BulkheadProperties scbBulkheadProperties() { + return new BulkheadProperties(); + } + + @Bean + public InstanceBulkheadProperties scbInstanceBulkheadProperties() { + return new InstanceBulkheadProperties(); + } + + @Bean + public CircuitBreakerProperties scbCircuitBreakerProperties() { + return new CircuitBreakerProperties(); + } + + @Bean + public InstanceIsolationProperties scbInstanceIsolationProperties() { + return new InstanceIsolationProperties(); + } + + @Bean + public MatchProperties scbMatchProperties() { + return new MatchProperties(); + } + + @Bean + public RateLimitProperties scbRateLimitProperties() { + return new RateLimitProperties(); + } + + @Bean + public IdentifierRateLimitProperties scbIdentifierRateLimitProperties() { + return new IdentifierRateLimitProperties(); + } + + @Bean + public RetryProperties scbRetryProperties() { + return new RetryProperties(); + } + + @Bean + public TimeLimiterProperties scbTimeLimiterProperties() { + return new TimeLimiterProperties(); + } + + @Bean + public GovernanceCacheProperties scbCacheProperties() { + return new GovernanceCacheProperties(); + } + + @Bean + public FaultInjectionProperties scbFaultInjectionProperties() { + return new FaultInjectionProperties(); + } + + @Bean + public LoadBalanceProperties scbLoadBalanceProperties() { + return new LoadBalanceProperties(); + } + + @Bean + public MapperProperties scbMapperProperties() { + return new MapperProperties(); + } + + // handlers configuration + @Bean + public BulkheadHandler scbBulkheadHandler(BulkheadProperties scbBulkheadProperties) { + return new BulkheadHandler(scbBulkheadProperties); + } + + @Bean + public InstanceBulkheadHandler scbInstanceBulkheadHandler(InstanceBulkheadProperties scbInstanceBulkheadProperties) { + return new InstanceBulkheadHandler(scbInstanceBulkheadProperties); + } + + @Bean + public LoadBalanceHandler scbLoadBalanceHandler(LoadBalanceProperties loadBalanceProperties) { + return new LoadBalanceHandler(loadBalanceProperties); + } + + @Bean + public CircuitBreakerHandler scbCircuitBreakerHandler(CircuitBreakerProperties scbCircuitBreakerProperties, + AbstractCircuitBreakerExtension circuitBreakerExtension) { + return new CircuitBreakerHandler(scbCircuitBreakerProperties, circuitBreakerExtension); + } + + @Bean + public InstanceIsolationHandler scbInstanceIsolationHandler(InstanceIsolationProperties scbInstanceIsolationProperties, + AbstractInstanceIsolationExtension isolationExtension, + ObjectProvider meterRegistry) { + return new InstanceIsolationHandler(scbInstanceIsolationProperties, isolationExtension, meterRegistry); + } + + @Bean + public RateLimitingHandler scbRateLimitingHandler(RateLimitProperties rateLimitProperties) { + return new RateLimitingHandler(rateLimitProperties); + } + + @Bean + public IdentifierRateLimitingHandler scbIdentifierRateLimitingHandler( + IdentifierRateLimitProperties identifierRateLimitProperties) { + return new IdentifierRateLimitingHandler(identifierRateLimitProperties); + } + + @Bean + public RetryHandler scbRetryHandler(RetryProperties retryProperties, AbstractRetryExtension retryExtension) { + return new RetryHandler(retryProperties, retryExtension); + } + + @Bean + public TimeLimiterHandler scbTimeLimiterHandler(TimeLimiterProperties timeLimiterProperties) { + return new TimeLimiterHandler(timeLimiterProperties); + } + + @Bean + public GovernanceCacheHandler scbGovernanceCacheHandler(GovernanceCacheProperties cacheProperties) { + return new GovernanceCacheHandler(cacheProperties); + } + + @Bean + public FaultInjectionHandler scbFaultInjectionHandler(FaultInjectionProperties scbFaultInjectionProperties) { + return new FaultInjectionHandler(scbFaultInjectionProperties); + } + + @Bean + public MapperHandler scbMapperHandler(MapperProperties scbMapperProperties) { + return new MapperHandler(scbMapperProperties); + } + + // request processor + @Bean + public RequestProcessor scbRequestProcessor(Map operatorMap) { + return new RequestProcessor(operatorMap); + } + + // matchers + @Bean + public MatchersService scbMatchersService(RequestProcessor requestProcessor, MatchProperties scbMatchProperties) { + return new MatchersServiceImpl(requestProcessor, scbMatchProperties); + } + + @Bean + public MatchersManager scbMatchersManager(MatchersService matchersService) { + return new MatchersManager(matchersService); + } + + // operators + @Bean + public CompareOperator scbCompareOperator() { + return new CompareOperator(); + } + + @Bean + public ContainsOperator scbContainsOperator() { + return new ContainsOperator(); + } + + @Bean + public ExactOperator scbExactOperator() { + return new ExactOperator(); + } + + @Bean + public PrefixOperator scbPrefixOperator() { + return new PrefixOperator(); + } + + @Bean + public SuffixOperator scbSuffixOperator() { + return new SuffixOperator(); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/InvocationContext.java b/governance/src/main/java/org/apache/servicecomb/governance/InvocationContext.java deleted file mode 100644 index 07d03ceecb8..00000000000 --- a/governance/src/main/java/org/apache/servicecomb/governance/InvocationContext.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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.governance; - -import java.util.Map; - -public interface InvocationContext { - Map getCalculatedMatches(); - - void addMatch(String key, Boolean value); -} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java b/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java index 821a65e742f..00caaafdbff 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/MatchersManager.java @@ -16,40 +16,28 @@ */ package org.apache.servicecomb.governance; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.policy.AbstractPolicy; import org.apache.servicecomb.governance.service.MatchersService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -@Component public class MatchersManager { - - @Autowired private MatchersService matchersService; - @Autowired - private InvocationContext invocationContext; - - public MatchersManager() { + public MatchersManager(MatchersService matchersService) { + this.matchersService = matchersService; } - public T match(GovernanceRequest request, Map policies) { - Map calculatedMatches = invocationContext.getCalculatedMatches(); - - for (Entry entry : policies.entrySet()) { - T policy = entry.getValue(); - - if (calculatedMatches.containsKey(entry.getKey())) { - return policy; - } + public T match(GovernanceRequestExtractor requestExtractor, Map policies) { + List sortPolicies = new ArrayList<>(policies.size()); + sortPolicies.addAll(policies.values()); + sortPolicies.sort(T::compareTo); - boolean keyMatch = matchersService.checkMatch(request, entry.getKey()); - invocationContext.addMatch(entry.getKey(), keyMatch); - if (keyMatch) { + for (T policy : sortPolicies) { + if (matchersService.checkMatch(requestExtractor, policy.getName())) { return policy; } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceConfigurationChangedEvent.java b/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceConfigurationChangedEvent.java index 492a6ca2b28..bce4ec729e7 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceConfigurationChangedEvent.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceConfigurationChangedEvent.java @@ -20,7 +20,7 @@ import java.util.Set; public class GovernanceConfigurationChangedEvent { - private Set changedConfigurations; + private final Set changedConfigurations; public GovernanceConfigurationChangedEvent(Set changedConfigurations) { this.changedConfigurations = changedConfigurations; @@ -29,4 +29,4 @@ public GovernanceConfigurationChangedEvent(Set changedConfigurations) { public Set getChangedConfigurations() { return changedConfigurations; } -} \ No newline at end of file +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceEventManager.java b/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceEventManager.java index 01bdfaae82f..a89103174a2 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceEventManager.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/event/GovernanceEventManager.java @@ -20,7 +20,7 @@ import com.google.common.eventbus.EventBus; public class GovernanceEventManager { - private static EventBus eventBus = new EventBus(); + private static final EventBus eventBus = new EventBus(); public static EventBus getEventBus() { return eventBus; diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/AbstractGovernanceHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/AbstractGovernanceHandler.java index ce46f373298..d28392e413c 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/AbstractGovernanceHandler.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/AbstractGovernanceHandler.java @@ -17,58 +17,87 @@ package org.apache.servicecomb.governance.handler; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - import org.apache.servicecomb.governance.MatchersManager; import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; import org.apache.servicecomb.governance.event.GovernanceEventManager; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.policy.AbstractPolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import com.google.common.eventbus.Subscribe; +import io.micrometer.core.instrument.MeterRegistry; + public abstract class AbstractGovernanceHandler { - private Map map = new ConcurrentHashMap<>(); + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGovernanceHandler.class); + + protected final DisposableMap processors; private final Object lock = new Object(); - @Autowired protected MatchersManager matchersManager; + protected MeterRegistry meterRegistry; + protected AbstractGovernanceHandler() { GovernanceEventManager.register(this); + processors = new DisposableMap<>(this::onConfigurationChanged); } - public PROCESSOR getActuator(GovernanceRequest governanceRequest) { - POLICY policy = matchPolicy(governanceRequest); + @Autowired + public void setMatchersManager(MatchersManager matchersManager) { + this.matchersManager = matchersManager; + } + + @Autowired(required = false) + public void setMeterRegistry(MeterRegistry meterRegistry) { + this.meterRegistry = meterRegistry; + } + + public PROCESSOR getActuator(GovernanceRequestExtractor requestExtractor) { + POLICY policy = matchPolicy(requestExtractor); if (policy == null) { return null; } - String key = createKey(policy); - PROCESSOR processor = map.get(key); + String key = createKey(requestExtractor, policy); + if (key == null) { + return null; + } + + Disposable processor = processors.get(key); if (processor == null) { synchronized (lock) { - processor = map.get(key); + processor = processors.get(key); if (processor == null) { - processor = createProcessor(policy); - map.put(key, processor); + processor = createProcessor(key, requestExtractor, policy); + processors.put(key, processor); } } } - return processor; + + return processor.get(); } - abstract protected String createKey(POLICY policy); + protected abstract String createKey(GovernanceRequestExtractor requestExtractor, POLICY policy); + + protected abstract POLICY matchPolicy(GovernanceRequestExtractor requestExtractor); - abstract protected POLICY matchPolicy(GovernanceRequest governanceRequest); + protected abstract Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + POLICY policy); - abstract protected PROCESSOR createProcessor(POLICY policy); + protected void onConfigurationChanged(String key) { + Disposable processor = processors.remove(key); + if (processor != null) { + LOGGER.info("remove governance processor {}", key); + processor.dispose(); + } + } @Subscribe public void onDynamicConfigurationListener(GovernanceConfigurationChangedEvent event) { - event.getChangedConfigurations().forEach(v -> map.remove(v)); + event.getChangedConfigurations().forEach(this::onConfigurationChanged); } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/BulkheadHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/BulkheadHandler.java index 53bef0db2a1..12d9ddc4eb2 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/BulkheadHandler.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/BulkheadHandler.java @@ -19,42 +19,44 @@ import java.time.Duration; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.policy.BulkheadPolicy; import org.apache.servicecomb.governance.properties.BulkheadProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import io.github.resilience4j.bulkhead.Bulkhead; import io.github.resilience4j.bulkhead.BulkheadConfig; import io.github.resilience4j.bulkhead.BulkheadRegistry; +import io.github.resilience4j.micrometer.tagged.BulkheadMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedBulkheadMetrics; -@Component public class BulkheadHandler extends AbstractGovernanceHandler { private static final Logger LOGGER = LoggerFactory.getLogger(BulkheadHandler.class); - @Autowired - private BulkheadProperties bulkheadProperties; + private final BulkheadProperties bulkheadProperties; + + public BulkheadHandler(BulkheadProperties bulkheadProperties) { + this.bulkheadProperties = bulkheadProperties; + } @Override - protected String createKey(BulkheadPolicy policy) { - return "servicecomb.bulkhead." + policy.getName(); + protected String createKey(GovernanceRequestExtractor requestExtractor, BulkheadPolicy policy) { + return bulkheadProperties.getConfigKey() + "." + policy.getName(); } @Override - public BulkheadPolicy matchPolicy(GovernanceRequest governanceRequest) { - return matchersManager.match(governanceRequest, bulkheadProperties.getParsedEntity()); + public BulkheadPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, bulkheadProperties.getParsedEntity()); } @Override - protected Bulkhead createProcessor(BulkheadPolicy policy) { - return getBulkhead(policy); + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, BulkheadPolicy policy) { + return getBulkhead(key, policy); } - private Bulkhead getBulkhead(BulkheadPolicy policy) { - LOGGER.info("applying new policy: {}", policy.toString()); + private Disposable getBulkhead(String key, BulkheadPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); BulkheadConfig config = BulkheadConfig.custom() .maxConcurrentCalls(policy.getMaxConcurrentCalls()) @@ -62,7 +64,14 @@ private Bulkhead getBulkhead(BulkheadPolicy policy) { .build(); BulkheadRegistry registry = BulkheadRegistry.of(config); - - return registry.bulkhead(policy.getName()); + if (meterRegistry != null) { + TaggedBulkheadMetrics + .ofBulkheadRegistry(BulkheadMetricNames.custom() + .availableConcurrentCallsMetricName(bulkheadProperties.getConfigKey() + ".available.concurrent.calls") + .maxAllowedConcurrentCallsMetricName( + bulkheadProperties.getConfigKey() + ".max.allowed.concurrent.calls").build(), registry) + .bindTo(meterRegistry); + } + return new DisposableBulkhead(key, registry, registry.bulkhead(key)); } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/CircuitBreakerHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/CircuitBreakerHandler.java index bf7c0e92640..39082661b24 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/CircuitBreakerHandler.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/CircuitBreakerHandler.java @@ -18,62 +18,78 @@ import java.time.Duration; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.handler.ext.AbstractCircuitBreakerExtension; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy; import org.apache.servicecomb.governance.properties.CircuitBreakerProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import io.github.resilience4j.circuitbreaker.CircuitBreaker; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; +import io.github.resilience4j.micrometer.tagged.CircuitBreakerMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedCircuitBreakerMetrics; -@Component public class CircuitBreakerHandler extends AbstractGovernanceHandler { private static final Logger LOGGER = LoggerFactory.getLogger(CircuitBreakerHandler.class); - @Autowired - private CircuitBreakerProperties circuitBreakerProperties; + private final CircuitBreakerProperties circuitBreakerProperties; + + private final AbstractCircuitBreakerExtension circuitBreakerExtension; + + public CircuitBreakerHandler(CircuitBreakerProperties circuitBreakerProperties, + AbstractCircuitBreakerExtension circuitBreakerExtension) { + this.circuitBreakerProperties = circuitBreakerProperties; + this.circuitBreakerExtension = circuitBreakerExtension; + } @Override - protected String createKey(CircuitBreakerPolicy policy) { - return "servicecomb.circuitBreaker." + policy.getName(); + protected String createKey(GovernanceRequestExtractor requestExtractor, CircuitBreakerPolicy policy) { + return this.circuitBreakerProperties.getConfigKey() + "." + policy.getName(); } @Override - public CircuitBreakerPolicy matchPolicy(GovernanceRequest governanceRequest) { - return matchersManager.match(governanceRequest, circuitBreakerProperties.getParsedEntity()); + public CircuitBreakerPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, circuitBreakerProperties.getParsedEntity()); } @Override - protected CircuitBreaker createProcessor(CircuitBreakerPolicy policy) { - return getCircuitBreaker(policy); + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + CircuitBreakerPolicy policy) { + return getCircuitBreaker(key, policy); } - private CircuitBreaker getCircuitBreaker(CircuitBreakerPolicy policy) { - LOGGER.info("applying new policy: {}", policy.toString()); + private Disposable getCircuitBreaker(String key, CircuitBreakerPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy); CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() - //熔断 失败率(请求)百分比阈值 .failureRateThreshold(policy.getFailureRateThreshold()) - //熔断 慢请求百分比阈值 .slowCallRateThreshold(policy.getSlowCallRateThreshold()) - //从开过渡到半开的等待时间 .waitDurationInOpenState(Duration.parse(policy.getWaitDurationInOpenState())) - //请求时间定义 .slowCallDurationThreshold(Duration.parse(policy.getSlowCallDurationThreshold())) - //进入半开状态时 允许的请求数量 .permittedNumberOfCallsInHalfOpenState(policy.getPermittedNumberOfCallsInHalfOpenState()) - //可以达到熔断条件的请求数量下限 .minimumNumberOfCalls(policy.getMinimumNumberOfCalls()) - //可以选择基于时间的滑动窗口计数或者基于请求数量的滑动窗口计数 .slidingWindowType(policy.getSlidingWindowTypeEnum()) - //滑动窗口,单位可能是请求数或者秒 - .slidingWindowSize(Integer.valueOf(policy.getSlidingWindowSize())) + .slidingWindowSize(Integer.parseInt(policy.getSlidingWindowSize())) + .recordException(e -> circuitBreakerExtension.isFailedResult(policy.getRecordFailureStatus(), e)) + .recordResult(r -> circuitBreakerExtension.isFailedResult(policy.getRecordFailureStatus(), r)) .build(); CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig); - return circuitBreakerRegistry.circuitBreaker(policy.getName(), circuitBreakerConfig); + if (meterRegistry != null) { + TaggedCircuitBreakerMetrics + .ofCircuitBreakerRegistry(CircuitBreakerMetricNames.custom() + .callsMetricName(this.circuitBreakerProperties.getConfigKey() + ".calls") + .notPermittedCallsMetricName(this.circuitBreakerProperties.getConfigKey() + ".not.permitted.calls") + .stateMetricName(this.circuitBreakerProperties.getConfigKey() + ".state") + .bufferedCallsMetricName(this.circuitBreakerProperties.getConfigKey() + ".buffered.calls") + .slowCallsMetricName(this.circuitBreakerProperties.getConfigKey() + ".slow.calls") + .failureRateMetricName(this.circuitBreakerProperties.getConfigKey() + ".failure.rate") + .slowCallRateMetricName(this.circuitBreakerProperties.getConfigKey() + ".slow.call.rate") + .build(), circuitBreakerRegistry) + .bindTo(meterRegistry); + } + return new DisposableCircuitBreaker(key, circuitBreakerRegistry, + circuitBreakerRegistry.circuitBreaker(key, circuitBreakerConfig)); } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/Disposable.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/Disposable.java new file mode 100644 index 00000000000..8f6e68909da --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/Disposable.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.governance.handler; + +public abstract class Disposable { + private long lastAccessed; + + protected Disposable() { + lastAccessed = System.currentTimeMillis(); + } + + public abstract void dispose(); + + public V get() { + lastAccessed = System.currentTimeMillis(); + return getValue(); + } + + public abstract V getValue(); + + public abstract String getKey(); + + public long lastAccessed() { + return lastAccessed; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableBulkhead.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableBulkhead.java new file mode 100644 index 00000000000..41f7ccc5212 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableBulkhead.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.governance.handler; + +import io.github.resilience4j.bulkhead.Bulkhead; +import io.github.resilience4j.bulkhead.BulkheadRegistry; + +public class DisposableBulkhead extends Disposable { + private final String key; + + private final BulkheadRegistry bulkheadRegistry; + + private final Bulkhead bulkhead; + + public DisposableBulkhead(String key, BulkheadRegistry bulkheadRegistry, + Bulkhead bulkhead) { + this.key = key; + this.bulkheadRegistry = bulkheadRegistry; + this.bulkhead = bulkhead; + } + + @Override + public void dispose() { + bulkheadRegistry.remove(key); + } + + @Override + public Bulkhead getValue() { + return bulkhead; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableCircuitBreaker.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableCircuitBreaker.java new file mode 100644 index 00000000000..d85292ee593 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableCircuitBreaker.java @@ -0,0 +1,50 @@ +/* + * 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.governance.handler; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; + +public class DisposableCircuitBreaker extends Disposable { + private final CircuitBreaker circuitBreaker; + + private final CircuitBreakerRegistry circuitBreakerRegistry; + + private final String key; + + public DisposableCircuitBreaker(String key, CircuitBreakerRegistry registry, CircuitBreaker circuitBreaker) { + this.key = key; + this.circuitBreaker = circuitBreaker; + this.circuitBreakerRegistry = registry; + } + + @Override + public void dispose() { + this.circuitBreakerRegistry.remove(key); + } + + @Override + public CircuitBreaker getValue() { + return circuitBreaker; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableHolder.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableHolder.java new file mode 100644 index 00000000000..9108df2a91a --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableHolder.java @@ -0,0 +1,43 @@ +/* + * 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.governance.handler; + +public class DisposableHolder extends Disposable { + private final E e; + + private final String key; + + public DisposableHolder(String key, E e) { + this.key = key; + this.e = e; + } + + @Override + public void dispose() { + + } + + @Override + public E getValue() { + return e; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableMap.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableMap.java new file mode 100644 index 00000000000..d5d78668fe0 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableMap.java @@ -0,0 +1,65 @@ +/* + * 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.governance.handler; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * check if some items are expired when put new item to map and remove expired items. + */ +public class DisposableMap extends ConcurrentHashMap> { + private static final long serialVersionUID = 7249069246763182397L; + + public interface RemoveListener { + void onRemoveEntry(String k); + } + + private static final int EXPIRE_TIME = 10 * 60 * 1000; + + private final RemoveListener listener; + + public DisposableMap(RemoveListener listener) { + this.listener = listener; + } + + @Override + public Disposable put(String key, Disposable value) { + Disposable result = super.put(key, value); + + checkExpired(); + + return result; + } + + private void checkExpired() { + List expired = new ArrayList<>(); + this.values().forEach(v -> { + if (System.currentTimeMillis() - v.lastAccessed() >= EXPIRE_TIME) { + expired.add(v.getKey()); + } + }); + expired.forEach(listener::onRemoveEntry); + } + + @Override + public Disposable get(Object key) { + return super.get(key); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableRateLimiter.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableRateLimiter.java new file mode 100644 index 00000000000..a078cb58215 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableRateLimiter.java @@ -0,0 +1,50 @@ +/* + * 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.governance.handler; + +import io.github.resilience4j.ratelimiter.RateLimiter; +import io.github.resilience4j.ratelimiter.RateLimiterRegistry; + +public class DisposableRateLimiter extends Disposable { + private final String key; + + private final RateLimiter rateLimiter; + + private final RateLimiterRegistry registry; + + public DisposableRateLimiter(String key, RateLimiter rateLimiter, + RateLimiterRegistry registry) { + this.key = key; + this.rateLimiter = rateLimiter; + this.registry = registry; + } + + @Override + public void dispose() { + registry.remove(key); + } + + @Override + public RateLimiter getValue() { + return rateLimiter; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableRetry.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableRetry.java new file mode 100644 index 00000000000..c7e7be86b6f --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableRetry.java @@ -0,0 +1,50 @@ +/* + * 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.governance.handler; + +import io.github.resilience4j.retry.Retry; +import io.github.resilience4j.retry.RetryRegistry; + +public class DisposableRetry extends Disposable { + private final String key; + + private final RetryRegistry registry; + + private final Retry retry; + + public DisposableRetry(String key, RetryRegistry registry, Retry retry) { + this.key = key; + this.registry = registry; + this.retry = retry; + } + + @Override + public void dispose() { + registry.remove(key); + } + + @Override + public Retry getValue() { + return retry; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableTimeLimiter.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableTimeLimiter.java new file mode 100644 index 00000000000..4a23b72d69c --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableTimeLimiter.java @@ -0,0 +1,49 @@ +/* + * 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.governance.handler; + +import io.github.resilience4j.timelimiter.TimeLimiter; +import io.github.resilience4j.timelimiter.TimeLimiterRegistry; + +public class DisposableTimeLimiter extends Disposable { + private final String key; + + private final TimeLimiterRegistry timeLimiterRegistry; + + private final TimeLimiter timeLimiter; + + public DisposableTimeLimiter(String key, TimeLimiterRegistry registry, TimeLimiter timeLimiter) { + this.key = key; + this.timeLimiterRegistry = registry; + this.timeLimiter = timeLimiter; + } + + @Override + public void dispose() { + timeLimiterRegistry.remove(key); + } + + @Override + public TimeLimiter getValue() { + return timeLimiter; + } + + @Override + public String getKey() { + return key; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/FaultInjectionHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/FaultInjectionHandler.java new file mode 100644 index 00000000000..e44b1685fe5 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/FaultInjectionHandler.java @@ -0,0 +1,49 @@ +/* + * 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.governance.handler; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; +import org.apache.servicecomb.governance.processor.injection.Fault; +import org.apache.servicecomb.governance.processor.injection.FaultInjectionUtil; +import org.apache.servicecomb.governance.properties.FaultInjectionProperties; + +public class FaultInjectionHandler extends AbstractGovernanceHandler { + + private final FaultInjectionProperties faultInjectionProperties; + + public FaultInjectionHandler(FaultInjectionProperties faultInjectionProperties) { + this.faultInjectionProperties = faultInjectionProperties; + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, FaultInjectionPolicy policy) { + return FaultInjectionProperties.MATCH_FAULT_INJECTION_KEY + "." + policy.getName(); + } + + @Override + public FaultInjectionPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, faultInjectionProperties.getParsedEntity()); + } + + @Override + protected DisposableHolder createProcessor(String key, GovernanceRequestExtractor requestExtractor, + FaultInjectionPolicy policy) { + return new DisposableHolder<>(key, FaultInjectionUtil.getFault(key, policy)); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/GovernanceCacheHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/GovernanceCacheHandler.java new file mode 100644 index 00000000000..7e7b6e6dd72 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/GovernanceCacheHandler.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.governance.handler; + +import java.time.Duration; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.GovernanceCachePolicy; +import org.apache.servicecomb.governance.properties.GovernanceCacheProperties; +import org.apache.servicecomb.governance.service.GovernanceCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +public class GovernanceCacheHandler + extends AbstractGovernanceHandler, GovernanceCachePolicy> { + private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceCacheHandler.class); + + private final GovernanceCacheProperties cacheProperties; + + public GovernanceCacheHandler(GovernanceCacheProperties cacheProperties) { + this.cacheProperties = cacheProperties; + } + + @Override + public GovernanceCachePolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, cacheProperties.getParsedEntity()); + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, GovernanceCachePolicy policy) { + return cacheProperties.getConfigKey() + "." + policy.getName(); + } + + @Override + protected Disposable> createProcessor(String key, GovernanceRequestExtractor requestExtractor, + GovernanceCachePolicy policy) { + return getGovernanceCache(key, policy); + } + + protected Disposable> getGovernanceCache(String key, GovernanceCachePolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); + Cache cache = CacheBuilder.newBuilder() + .expireAfterWrite(Duration.parse(policy.getTtl())) + .maximumSize(policy.getMaximumSize()) + .concurrencyLevel(policy.getConcurrencyLevel()) + .build(); + GovernanceCache governanceCache = GovernanceCache.of(cache); + return new DisposableHolder<>(key, governanceCache); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/HandlerType.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/HandlerType.java deleted file mode 100644 index 5ae9b9ddb87..00000000000 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/HandlerType.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.governance.handler; - -public enum HandlerType { - CLIENT, - SERVER, - BOTH -} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/IdentifierRateLimitingHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/IdentifierRateLimitingHandler.java new file mode 100644 index 00000000000..26751c64dfa --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/IdentifierRateLimitingHandler.java @@ -0,0 +1,104 @@ +/* + * 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.governance.handler; + +import java.time.Duration; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.IdentifierRateLimitingPolicy; +import org.apache.servicecomb.governance.properties.IdentifierRateLimitProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.resilience4j.micrometer.tagged.RateLimiterMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedRateLimiterMetrics; +import io.github.resilience4j.ratelimiter.RateLimiter; +import io.github.resilience4j.ratelimiter.RateLimiterConfig; +import io.github.resilience4j.ratelimiter.RateLimiterRegistry; + +public class IdentifierRateLimitingHandler extends + AbstractGovernanceHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(IdentifierRateLimitingHandler.class); + + private final IdentifierRateLimitProperties rateLimitProperties; + + public IdentifierRateLimitingHandler(IdentifierRateLimitProperties rateLimitProperties) { + this.rateLimitProperties = rateLimitProperties; + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, IdentifierRateLimitingPolicy policy) { + if (StringUtils.isEmpty(policy.getIdentifier()) || + StringUtils.isEmpty(requestExtractor.header(policy.getIdentifier()))) { + LOGGER.info("identifier rate limiting is not properly configured, identifier is empty."); + return null; + } + return this.rateLimitProperties.getConfigKey() + + "." + policy.getName() + + "." + requestExtractor.header(policy.getIdentifier()); + } + + @Override + protected void onConfigurationChanged(String key) { + if (key.startsWith(this.rateLimitProperties.getConfigKey())) { + for (String processorKey : processors.keySet()) { + if (processorKey.startsWith(key)) { + Disposable processor = processors.remove(processorKey); + if (processor != null) { + LOGGER.info("remove identifier rate limiting processor {}", key); + processor.dispose(); + } + } + } + } + } + + @Override + public IdentifierRateLimitingPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, rateLimitProperties.getParsedEntity()); + } + + @Override + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + IdentifierRateLimitingPolicy policy) { + return getRateLimiter(key, policy); + } + + private Disposable getRateLimiter(String key, IdentifierRateLimitingPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); + + RateLimiterConfig config = RateLimiterConfig.custom() + .limitForPeriod(policy.getRate()) + .limitRefreshPeriod(Duration.parse(policy.getLimitRefreshPeriod())) + .timeoutDuration(Duration.parse(policy.getTimeoutDuration())) + .build(); + RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(config); + if (meterRegistry != null) { + TaggedRateLimiterMetrics + .ofRateLimiterRegistry(RateLimiterMetricNames.custom() + .availablePermissionsMetricName( + this.rateLimitProperties.getConfigKey() + ".available.permissions") + .waitingThreadsMetricName(this.rateLimitProperties.getConfigKey() + ".waiting.threads") + .build(), + rateLimiterRegistry) + .bindTo(meterRegistry); + } + return new DisposableRateLimiter(key, rateLimiterRegistry.rateLimiter(key), rateLimiterRegistry); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/InstanceBulkheadHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/InstanceBulkheadHandler.java new file mode 100644 index 00000000000..e90f2472915 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/InstanceBulkheadHandler.java @@ -0,0 +1,103 @@ +/* + * 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.governance.handler; + +import java.time.Duration; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.BulkheadPolicy; +import org.apache.servicecomb.governance.properties.InstanceBulkheadProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.resilience4j.bulkhead.Bulkhead; +import io.github.resilience4j.bulkhead.BulkheadConfig; +import io.github.resilience4j.bulkhead.BulkheadRegistry; +import io.github.resilience4j.micrometer.tagged.BulkheadMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedBulkheadMetrics; + +public class InstanceBulkheadHandler extends AbstractGovernanceHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(InstanceBulkheadHandler.class); + + private final InstanceBulkheadProperties bulkheadProperties; + + public InstanceBulkheadHandler(InstanceBulkheadProperties bulkheadProperties) { + this.bulkheadProperties = bulkheadProperties; + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, BulkheadPolicy policy) { + return this.bulkheadProperties.getConfigKey() + + "." + policy.getName() + + "." + requestExtractor.serviceName() + + "." + requestExtractor.instanceId(); + } + + @Override + protected void onConfigurationChanged(String key) { + if (key.startsWith(this.bulkheadProperties.getConfigKey())) { + for (String processorKey : processors.keySet()) { + if (processorKey.startsWith(key)) { + Disposable processor = processors.remove(processorKey); + if (processor != null) { + LOGGER.info("remove instance bulkhead processor {}", key); + processor.dispose(); + } + } + } + } + } + + @Override + public BulkheadPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + if (StringUtils.isEmpty(requestExtractor.serviceName()) || StringUtils.isEmpty( + requestExtractor.instanceId())) { + LOGGER.info("Instance bulkhead is not properly configured, service id or instance id is empty."); + return null; + } + return matchersManager.match(requestExtractor, bulkheadProperties.getParsedEntity()); + } + + @Override + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, BulkheadPolicy policy) { + return getBulkhead(key, policy); + } + + private Disposable getBulkhead(String key, BulkheadPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); + + BulkheadConfig config = BulkheadConfig.custom() + .maxConcurrentCalls(policy.getMaxConcurrentCalls()) + .maxWaitDuration(Duration.parse(policy.getMaxWaitDuration())) + .build(); + + BulkheadRegistry registry = BulkheadRegistry.of(config); + if (meterRegistry != null) { + TaggedBulkheadMetrics + .ofBulkheadRegistry(BulkheadMetricNames.custom() + .availableConcurrentCallsMetricName( + this.bulkheadProperties.getConfigKey() + ".available.concurrent.calls") + .maxAllowedConcurrentCallsMetricName( + this.bulkheadProperties.getConfigKey() + ".max.allowed.concurrent.calls").build(), + registry) + .bindTo(meterRegistry); + } + return new DisposableBulkhead(key, registry, registry.bulkhead(key, config)); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/InstanceIsolationHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/InstanceIsolationHandler.java new file mode 100644 index 00000000000..894dd170e99 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/InstanceIsolationHandler.java @@ -0,0 +1,127 @@ +/* + * 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.governance.handler; + +import java.time.Duration; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.governance.handler.ext.AbstractInstanceIsolationExtension; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy; +import org.apache.servicecomb.governance.properties.InstanceIsolationProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.ObjectProvider; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig; +import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; +import io.github.resilience4j.micrometer.tagged.CircuitBreakerMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedCircuitBreakerMetrics; +import io.micrometer.core.instrument.MeterRegistry; + +public final class InstanceIsolationHandler extends AbstractGovernanceHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(InstanceIsolationHandler.class); + + private final InstanceIsolationProperties instanceIsolationProperties; + + private final AbstractInstanceIsolationExtension isolationExtension; + + private final MeterRegistry meterRegistry; + + public InstanceIsolationHandler(InstanceIsolationProperties instanceIsolationProperties, + AbstractInstanceIsolationExtension isolationExtension, + ObjectProvider meterRegistry) { + this.instanceIsolationProperties = instanceIsolationProperties; + this.isolationExtension = isolationExtension; + this.meterRegistry = meterRegistry.getIfAvailable(); + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, CircuitBreakerPolicy policy) { + return this.instanceIsolationProperties.getConfigKey() + + "." + policy.getName() + + "." + requestExtractor.serviceName() + + "." + requestExtractor.instanceId(); + } + + @Override + protected void onConfigurationChanged(String key) { + if (key.startsWith(this.instanceIsolationProperties.getConfigKey())) { + for (String processorKey : processors.keySet()) { + if (processorKey.startsWith(key)) { + Disposable circuitBreaker = processors.remove(processorKey); + if (circuitBreaker != null) { + LOGGER.info("remove instance isolation processor {}", key); + circuitBreaker.dispose(); + } + } + } + } + } + + @Override + public CircuitBreakerPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + if (StringUtils.isEmpty(requestExtractor.serviceName()) || StringUtils.isEmpty( + requestExtractor.instanceId())) { + LOGGER.debug("Isolation is not properly configured, service id or instance id is empty."); + return null; + } + return matchersManager.match(requestExtractor, instanceIsolationProperties.getParsedEntity()); + } + + @Override + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + CircuitBreakerPolicy policy) { + return getCircuitBreaker(key, policy); + } + + private Disposable getCircuitBreaker(String key, CircuitBreakerPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); + + CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom() + .failureRateThreshold(policy.getFailureRateThreshold()) + .slowCallRateThreshold(policy.getSlowCallRateThreshold()) + .waitDurationInOpenState(Duration.parse(policy.getWaitDurationInOpenState())) + .slowCallDurationThreshold(Duration.parse(policy.getSlowCallDurationThreshold())) + .permittedNumberOfCallsInHalfOpenState(policy.getPermittedNumberOfCallsInHalfOpenState()) + .minimumNumberOfCalls(policy.getMinimumNumberOfCalls()) + .slidingWindowType(policy.getSlidingWindowTypeEnum()) + .slidingWindowSize(Integer.parseInt(policy.getSlidingWindowSize())) + .recordException(e -> isolationExtension.isFailedResult(policy.getRecordFailureStatus(), e)) + .recordResult(r -> isolationExtension.isFailedResult(policy.getRecordFailureStatus(), r)) + .build(); + CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig); + if (meterRegistry != null) { + TaggedCircuitBreakerMetrics + .ofCircuitBreakerRegistry(CircuitBreakerMetricNames.custom() + .callsMetricName(this.instanceIsolationProperties.getConfigKey() + ".calls") + .notPermittedCallsMetricName( + this.instanceIsolationProperties.getConfigKey() + ".not.permitted.calls") + .stateMetricName(this.instanceIsolationProperties.getConfigKey() + ".state") + .bufferedCallsMetricName(this.instanceIsolationProperties.getConfigKey() + ".buffered.calls") + .slowCallsMetricName(this.instanceIsolationProperties.getConfigKey() + ".slow.calls") + .failureRateMetricName(this.instanceIsolationProperties.getConfigKey() + ".failure.rate") + .slowCallRateMetricName(this.instanceIsolationProperties.getConfigKey() + ".slow.call.rate") + .build(), circuitBreakerRegistry) + .bindTo(meterRegistry); + } + return new DisposableCircuitBreaker(key, circuitBreakerRegistry, + circuitBreakerRegistry.circuitBreaker(key, circuitBreakerConfig)); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/LoadBalanceHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/LoadBalanceHandler.java new file mode 100644 index 00000000000..ab549c759f2 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/LoadBalanceHandler.java @@ -0,0 +1,48 @@ +/* + * 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.governance.handler; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.LoadBalancerPolicy; +import org.apache.servicecomb.governance.processor.loadbanlance.LoadBalance; +import org.apache.servicecomb.governance.properties.LoadBalanceProperties; + +public class LoadBalanceHandler extends AbstractGovernanceHandler { + + private final LoadBalanceProperties loadBalanceProperties; + + public LoadBalanceHandler(LoadBalanceProperties loadBalanceProperties) { + this.loadBalanceProperties = loadBalanceProperties; + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, LoadBalancerPolicy policy) { + return this.loadBalanceProperties.getConfigKey() + "." + policy.getName(); + } + + @Override + public LoadBalancerPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, loadBalanceProperties.getParsedEntity()); + } + + @Override + protected DisposableHolder createProcessor(String key, GovernanceRequestExtractor requestExtractor, + LoadBalancerPolicy policy) { + return new DisposableHolder<>(key, LoadBalance.getLoadBalance(key, policy)); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/MapperHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/MapperHandler.java new file mode 100644 index 00000000000..53726a2b0e4 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/MapperHandler.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.governance.handler; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.MapperPolicy; +import org.apache.servicecomb.governance.processor.mapping.Mapper; +import org.apache.servicecomb.governance.properties.MapperProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MapperHandler extends AbstractGovernanceHandler { + private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitingHandler.class); + + private final MapperProperties mapperProperties; + + public MapperHandler(MapperProperties mapperProperties) { + this.mapperProperties = mapperProperties; + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, MapperPolicy policy) { + return mapperProperties.getConfigKey() + "." + policy.getName(); + } + + @Override + public MapperPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, mapperProperties.getParsedEntity()); + } + + @Override + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + MapperPolicy policy) { + return getMapper(key, policy); + } + + private Disposable getMapper(String key, MapperPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); + + return new DisposableHolder<>(key, Mapper.create(policy.getTarget())); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/RateLimitingHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/RateLimitingHandler.java index 7e71a7cecfe..e70ae60f78e 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/RateLimitingHandler.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/RateLimitingHandler.java @@ -18,50 +18,62 @@ import java.time.Duration; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.policy.RateLimitingPolicy; import org.apache.servicecomb.governance.properties.RateLimitProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import io.github.resilience4j.micrometer.tagged.RateLimiterMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedRateLimiterMetrics; import io.github.resilience4j.ratelimiter.RateLimiter; import io.github.resilience4j.ratelimiter.RateLimiterConfig; import io.github.resilience4j.ratelimiter.RateLimiterRegistry; -@Component public class RateLimitingHandler extends AbstractGovernanceHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RateLimitingHandler.class); - @Autowired - private RateLimitProperties rateLimitProperties; + private final RateLimitProperties rateLimitProperties; + + public RateLimitingHandler(RateLimitProperties rateLimitProperties) { + this.rateLimitProperties = rateLimitProperties; + } @Override - protected String createKey(RateLimitingPolicy policy) { - return "servicecomb.rateLimiting." + policy.getName(); + protected String createKey(GovernanceRequestExtractor requestExtractor, RateLimitingPolicy policy) { + return this.rateLimitProperties.getConfigKey() + "." + policy.getName(); } @Override - public RateLimitingPolicy matchPolicy(GovernanceRequest governanceRequest) { - return matchersManager.match(governanceRequest, rateLimitProperties.getParsedEntity()); + public RateLimitingPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, rateLimitProperties.getParsedEntity()); } @Override - protected RateLimiter createProcessor(RateLimitingPolicy policy) { - return getRateLimiter(policy); + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + RateLimitingPolicy policy) { + return getRateLimiter(key, policy); } - private RateLimiter getRateLimiter(RateLimitingPolicy policy) { - LOGGER.info("applying new policy: {}", policy.toString()); + private Disposable getRateLimiter(String key, RateLimitingPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy.toString()); - RateLimiterConfig config; - config = RateLimiterConfig.custom() + RateLimiterConfig config = RateLimiterConfig.custom() .limitForPeriod(policy.getRate()) .limitRefreshPeriod(Duration.parse(policy.getLimitRefreshPeriod())) .timeoutDuration(Duration.parse(policy.getTimeoutDuration())) .build(); RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(config); - return rateLimiterRegistry.rateLimiter(policy.getName()); + if (meterRegistry != null) { + TaggedRateLimiterMetrics + .ofRateLimiterRegistry(RateLimiterMetricNames.custom() + .availablePermissionsMetricName( + this.rateLimitProperties.getConfigKey() + ".available.permissions") + .waitingThreadsMetricName(this.rateLimitProperties.getConfigKey() + ".waiting.threads") + .build(), + rateLimiterRegistry) + .bindTo(meterRegistry); + } + return new DisposableRateLimiter(key, rateLimiterRegistry.rateLimiter(key), rateLimiterRegistry); } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/RetryHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/RetryHandler.java index fed065e53b0..f7f2476f667 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/RetryHandler.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/RetryHandler.java @@ -17,63 +17,72 @@ package org.apache.servicecomb.governance.handler; import java.time.Duration; -import java.util.List; -import java.util.function.Predicate; -import io.github.resilience4j.core.IntervalFunction; - -import org.apache.servicecomb.governance.handler.ext.RetryExtension; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.policy.RetryPolicy; import org.apache.servicecomb.governance.properties.RetryProperties; import org.apache.servicecomb.governance.utils.GovernanceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import io.github.resilience4j.core.IntervalFunction; +import io.github.resilience4j.micrometer.tagged.RetryMetricNames; +import io.github.resilience4j.micrometer.tagged.TaggedRetryMetrics; import io.github.resilience4j.retry.Retry; import io.github.resilience4j.retry.RetryConfig; import io.github.resilience4j.retry.RetryRegistry; -@Component public class RetryHandler extends AbstractGovernanceHandler { private static final Logger LOGGER = LoggerFactory.getLogger(RetryHandler.class); - @Autowired - private RetryProperties retryProperties; + private final RetryProperties retryProperties; + + private final AbstractRetryExtension retryExtension; - @Autowired - private RetryExtension retryExtension; + public RetryHandler(RetryProperties retryProperties, AbstractRetryExtension retryExtension) { + this.retryProperties = retryProperties; + this.retryExtension = retryExtension; + } @Override - protected String createKey(RetryPolicy policy) { - return "servicecomb.retry." + policy.getName(); + protected String createKey(GovernanceRequestExtractor requestExtractor, RetryPolicy policy) { + return this.retryProperties.getConfigKey() + "." + policy.getName(); } @Override - public RetryPolicy matchPolicy(GovernanceRequest governanceRequest) { - return matchersManager.match(governanceRequest, retryProperties.getParsedEntity()); + public RetryPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, retryProperties.getParsedEntity()); } @Override - protected Retry createProcessor(RetryPolicy policy) { - return getRetry(policy); + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + RetryPolicy policy) { + return getRetry(key, policy); } - private Retry getRetry(RetryPolicy retryPolicy) { - LOGGER.info("applying new policy: {}", retryPolicy.toString()); + private Disposable getRetry(String key, RetryPolicy retryPolicy) { + LOGGER.info("applying new policy {} for {}", key, retryPolicy.toString()); RetryConfig config = RetryConfig.custom() .maxAttempts(retryPolicy.getMaxAttempts() + 1) - .retryOnResult(getPredicate(retryPolicy.getRetryOnResponseStatus())) - .retryExceptions(retryExtension.retryExceptions()) + .retryOnResult(response -> retryExtension.isFailedResult(retryPolicy.getRetryOnResponseStatus(), response)) + .retryOnException(exception -> retryExtension.isFailedResult(retryPolicy.getRetryOnResponseStatus(), exception)) .intervalFunction(getIntervalFunction(retryPolicy)) + .failAfterMaxAttempts(retryPolicy.isFailAfterMaxAttempts()) .build(); RetryRegistry registry = RetryRegistry.of(config); - return registry.retry(retryPolicy.getName()); + if (meterRegistry != null) { + TaggedRetryMetrics + .ofRetryRegistry(RetryMetricNames.custom() + .callsMetricName(this.retryProperties.getConfigKey() + ".calls") + .build(), + registry) + .bindTo(meterRegistry); + } + return new DisposableRetry(key, registry, registry.retry(key)); } private IntervalFunction getIntervalFunction(RetryPolicy retryPolicy) { @@ -83,8 +92,4 @@ private IntervalFunction getIntervalFunction(RetryPolicy retryPolicy) { } return IntervalFunction.of(Duration.parse(retryPolicy.getWaitDuration())); } - - private Predicate getPredicate(List statusList) { - return response -> retryExtension.isRetry(statusList, response); - } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/TimeLimiterHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/TimeLimiterHandler.java new file mode 100644 index 00000000000..d9f03034d07 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/TimeLimiterHandler.java @@ -0,0 +1,74 @@ +/* + * 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.governance.handler; + +import java.time.Duration; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.TimeLimiterPolicy; +import org.apache.servicecomb.governance.properties.TimeLimiterProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.resilience4j.micrometer.tagged.TaggedTimeLimiterMetrics; +import io.github.resilience4j.micrometer.tagged.TimeLimiterMetricNames; +import io.github.resilience4j.timelimiter.TimeLimiter; +import io.github.resilience4j.timelimiter.TimeLimiterConfig; +import io.github.resilience4j.timelimiter.TimeLimiterRegistry; + +public class TimeLimiterHandler extends AbstractGovernanceHandler { + + private static final Logger LOGGER = LoggerFactory.getLogger(TimeLimiterHandler.class); + + private final TimeLimiterProperties timeLimiterProperties; + + public TimeLimiterHandler(TimeLimiterProperties timeLimiterProperties) { + this.timeLimiterProperties = timeLimiterProperties; + } + + @Override + protected String createKey(GovernanceRequestExtractor requestExtractor, TimeLimiterPolicy policy) { + return timeLimiterProperties.getConfigKey() + "." + policy.getName(); + } + + @Override + public TimeLimiterPolicy matchPolicy(GovernanceRequestExtractor requestExtractor) { + return matchersManager.match(requestExtractor, timeLimiterProperties.getParsedEntity()); + } + + @Override + public Disposable createProcessor(String key, GovernanceRequestExtractor requestExtractor, + TimeLimiterPolicy policy) { + return getTimeLimiter(key, policy); + } + + private Disposable getTimeLimiter(String key, TimeLimiterPolicy policy) { + LOGGER.info("applying new policy {} for {}", key, policy); + TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom() + .timeoutDuration(Duration.parse(policy.getTimeoutDuration())) + .cancelRunningFuture(policy.isCancelRunningFuture()) + .build(); + TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry.of(timeLimiterConfig); + if (meterRegistry != null) { + TaggedTimeLimiterMetrics.ofTimeLimiterRegistry(TimeLimiterMetricNames.custom() + .callsMetricName(timeLimiterProperties.getConfigKey() + ".calls") + .build(), timeLimiterRegistry).bindTo(meterRegistry); + } + return new DisposableTimeLimiter(key, timeLimiterRegistry, timeLimiterRegistry.timeLimiter(key)); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractCircuitBreakerExtension.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractCircuitBreakerExtension.java new file mode 100644 index 00000000000..bf885a9003d --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractCircuitBreakerExtension.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.governance.handler.ext; + +public abstract class AbstractCircuitBreakerExtension extends AbstractFailurePredictor { + +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractFailurePredictor.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractFailurePredictor.java new file mode 100644 index 00000000000..e7fea24f962 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractFailurePredictor.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.governance.handler.ext; + +import java.util.List; +import java.util.stream.IntStream; + +import org.apache.commons.lang3.StringUtils; + +public abstract class AbstractFailurePredictor implements FailurePredictor { + @Override + public boolean isFailedResult(List statusList, Object result) { + String statusCode = extractStatusCode(result); + if (StringUtils.isEmpty(statusCode)) { + return false; + } + return statusCodeContains(statusList, statusCode); + } + + protected abstract String extractStatusCode(Object result); + + protected static boolean statusCodeContains(List statusList, String responseStatus) { + return statusList.stream().anyMatch(status -> statusCodeMatch(status, responseStatus)); + } + + private static boolean statusCodeMatch(String status, String responseStatus) { + if (status == null) { + return false; + } + if (responseStatus.length() != status.length()) { + return false; + } + char[] statusChar = status.toCharArray(); + char[] responseChar = responseStatus.toCharArray(); + return IntStream.range(0, statusChar.length).noneMatch(i -> + statusChar[i] != responseChar[i] && statusChar[i] != 'x'); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractInstanceIsolationExtension.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractInstanceIsolationExtension.java new file mode 100644 index 00000000000..6b4a5a9934d --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractInstanceIsolationExtension.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.governance.handler.ext; + +public abstract class AbstractInstanceIsolationExtension extends AbstractFailurePredictor { + +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractRetryExtension.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractRetryExtension.java index 18d3e1e8e88..cd21bdacc24 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractRetryExtension.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/AbstractRetryExtension.java @@ -17,33 +17,6 @@ package org.apache.servicecomb.governance.handler.ext; -import org.apache.commons.lang3.StringUtils; +public abstract class AbstractRetryExtension extends AbstractFailurePredictor { -import java.util.List; -import java.util.stream.IntStream; - -public abstract class AbstractRetryExtension implements RetryExtension { - public boolean isRetry(List statusList, Object result) { - String statusCode = extractStatusCode(result); - if (StringUtils.isEmpty(statusCode)) { - return false; - } - return statusCodeContains(statusList, statusCode); - } - - protected abstract String extractStatusCode(Object result); - - protected static boolean statusCodeContains(List statusList, String responseStatus) { - return statusList.stream().anyMatch(status -> statusCodeMatch(status, responseStatus)); - } - - private static boolean statusCodeMatch(String status, String responseStatus) { - if (3 != status.length()) { - return false; - } - char[] statusChar = status.toCharArray(); - char[] responseChar = responseStatus.toCharArray(); - return IntStream.range(0, 3).noneMatch(i -> - statusChar[i] != responseChar[i] && statusChar[i] != 'x'); - } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/FailurePredictor.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/FailurePredictor.java new file mode 100644 index 00000000000..c07ebe39bdd --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/FailurePredictor.java @@ -0,0 +1,81 @@ +/* + * 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.governance.handler.ext; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.NoRouteToHostException; +import java.net.SocketTimeoutException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.net.ssl.SSLHandshakeException; + +import com.google.common.collect.ImmutableMap; + +import io.netty.handler.ssl.SslHandshakeTimeoutException; +import io.vertx.core.VertxException; + +public interface FailurePredictor { + Map, List> STRICT_RETRIABLE = + ImmutableMap., List>builder() + .put(ConnectException.class, Collections.emptyList()) + .put(SocketTimeoutException.class, Collections.emptyList()) + /* + * deal with some special exceptions caused by the server side close the connection + */ + .put(IOException.class, Collections.singletonList("Connection reset by peer")) + .put(VertxException.class, Collections.singletonList("Connection was closed")) + .put(NoRouteToHostException.class, Collections.emptyList()) + .put(SSLHandshakeException.class, Collections.emptyList()) + .put(SslHandshakeTimeoutException.class, Collections.emptyList()) + .build(); + + boolean isFailedResult(List statusList, Object result); + + default boolean isFailedResult(List statusList, Throwable e) { + return canRetryForException(STRICT_RETRIABLE, e); + } + + static boolean canRetryForException(Map, List> retryList, + Throwable throwableToSearchIn) { + // retry on exception type on message match + int infiniteLoopPreventionCounter = 10; + while (throwableToSearchIn != null && infiniteLoopPreventionCounter > 0) { + infiniteLoopPreventionCounter--; + for (Entry, List> c : retryList.entrySet()) { + Class key = c.getKey(); + if (key.isAssignableFrom(throwableToSearchIn.getClass())) { + if (c.getValue() == null || c.getValue().isEmpty()) { + return true; + } else { + String msg = throwableToSearchIn.getMessage(); + for (String val : c.getValue()) { + if (val.equals(msg)) { + return true; + } + } + } + } + } + throwableToSearchIn = throwableToSearchIn.getCause(); + } + return false; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/RetryExtension.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/RetryExtension.java deleted file mode 100644 index c7cd145aa7f..00000000000 --- a/governance/src/main/java/org/apache/servicecomb/governance/handler/ext/RetryExtension.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.governance.handler.ext; - -import java.util.List; - -public interface RetryExtension { - boolean isRetry(List statusList, Object result); - - Class[] retryExceptions(); - -} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/CustomMatcher.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/CustomMatcher.java new file mode 100644 index 00000000000..c6ec5363791 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/CustomMatcher.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.governance.marker; + +public class CustomMatcher { + + private String customMatcherHandler; + + private String customMatcherParameters; + + public String getCustomMatcherHandler() { + return customMatcherHandler; + } + + public void setCustomMatcherHandler(String customMatcherHandler) { + this.customMatcherHandler = customMatcherHandler; + } + + public String getCustomMatcherParameters() { + return customMatcherParameters; + } + + public void setCustomMatcherParameters(String customMatcherParameters) { + this.customMatcherParameters = customMatcherParameters; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java index b88adb8ca51..e3ac0b2abce 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java @@ -16,40 +16,135 @@ */ package org.apache.servicecomb.governance.marker; +import java.util.Collections; import java.util.Map; import org.springframework.util.LinkedCaseInsensitiveMap; -public class GovernanceRequest { - private Map headers; +public class GovernanceRequest implements GovernanceRequestExtractor { + /** + * headers with this request, maybe null. + * For provider: headers indicates the request headers to me. + * For consumer: headers indicates the request headers to the target. + */ + private Map headers = Collections.emptyMap(); - private String uri; + /** + * Queries with this request, maybe null. + * For provider: Queries indicates the request params to me. + * For consumer: Queries indicates the request params to the target. + */ + private Map queries = Collections.emptyMap(); + /** + * api path with this request, maybe null. For REST, e.g. /foo/bar; For RPC, e.g. MySchema.sayHello + * For provider: uri indicates the request uri to me. + * For consumer: uri indicates the request uri to the target. + */ + private String apiPath; + + /** + * method with this request, maybe null. + * For provider: method indicates the request method to me. + * For consumer: method indicates the request method to the target. + */ private String method; + /** + * instance id with this request, maybe null. + * For provider: instanceId indicates who calls me. + * For consumer: instanceId indicates the target instance. + */ + private String instanceId; + + /** + * microservice id (microservice name or application name + microservice name) with this request, maybe null. + * For provider: serviceName indicates who calls me. + * For consumer: serviceName indicates the target service. + */ + private String serviceName; + + /** + * sourceRequest the source request for creating this governanceRequest + * For provider: uri indicates the request to me. + * For consumer: uri indicates the request to the target. + * the type of sourceRequest could be ClientRequest, ServerWebExchange, HttpRequest, HttpServletRequest and so on, + * User will use this request to extract the information he need + */ + private Object sourceRequest; + + @Override + public String header(String key) { + return headers.get(key); + } + + @Override + public String query(String key) { + return queries.get(key); + } + public Map getHeaders() { return headers; } + public Map getQueries() { + return queries; + } + public void setHeaders(Map headers) { Map temp = new LinkedCaseInsensitiveMap<>(); temp.putAll(headers); this.headers = temp; } - public String getUri() { - return uri; + public void setQueries(Map queries) { + Map temp = new LinkedCaseInsensitiveMap<>(); + temp.putAll(queries); + this.queries = temp; + } + + @Override + public String apiPath() { + return apiPath; } - public void setUri(String uri) { - this.uri = uri; + public void setApiPath(String apiPath) { + this.apiPath = apiPath; } - public String getMethod() { + @Override + public String method() { return method; } public void setMethod(String method) { this.method = method; } + + @Override + public String instanceId() { + return instanceId; + } + + public void setInstanceId(String instanceId) { + this.instanceId = instanceId; + } + + @Override + public String serviceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + @Override + public Object sourceRequest() { + return sourceRequest; + } + + public void setSourceRequest(Object sourceRequest) { + this.sourceRequest = sourceRequest; + } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.java new file mode 100644 index 00000000000..28beb8e8384 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.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.governance.marker; + +public interface GovernanceRequestExtractor { + String apiPath(); + + String method(); + + String header(String key); + + String query(String key); + + String instanceId(); + + String serviceName(); + + Object sourceRequest(); +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java index 95184a4dfaf..6fb18fada3d 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java @@ -26,10 +26,24 @@ public class Matcher { private Map headers; + private Map queries; + private RawOperator apiPath; private List method; + private String serviceName; + + private CustomMatcher customMatcher; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + public Map getHeaders() { return headers; } @@ -38,6 +52,14 @@ public void setHeaders(Map headers) { this.headers = headers; } + public Map getQueries() { + return queries; + } + + public void setQueries(Map queries) { + this.queries = queries; + } + public RawOperator getApiPath() { return apiPath; } @@ -54,11 +76,19 @@ public void setMethod(List method) { this.method = method; } - public String getName() { - return name; + public String getServiceName() { + return serviceName; } - public void setName(String name) { - this.name = name; + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public CustomMatcher getCustomMatcher() { + return customMatcher; + } + + public void setCustomMatcher(CustomMatcher customMatcher) { + this.customMatcher = customMatcher; } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java index f0431aa9ef4..9651d8a7740 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java @@ -16,52 +16,119 @@ */ package org.apache.servicecomb.governance.marker; +import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.governance.marker.operator.MatchOperator; import org.apache.servicecomb.governance.marker.operator.RawOperator; +import org.apache.servicecomb.governance.utils.CustomMatch; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; -@Component -public class RequestProcessor { +/** + * Request Processor checks if a request matches a configuration. + */ +public class RequestProcessor implements ApplicationContextAware { private static final Logger LOGGER = LoggerFactory.getLogger(RequestProcessor.class); - private static final String OPERATOR_SUFFIX = "Operator"; + public static final String errorMessageForNotImplements = " didn't implement interface org.apache.servicecomb.governance.utils.CustomMatch"; + + public static final String errorMessageForAbstractClass = " should be a instantiable class rather than abstract class or other else"; + + public static final String infoMessageForCreatingClass = "is not in spring container, create one and register it to spring container"; + + private final Map operatorMap; - @Autowired - private Map operatorMap; + private ApplicationContext applicationContext; - public boolean match(GovernanceRequest request, Matcher matcher) { - if ((matcher.getMethod() != null && !matcher.getMethod().contains(request.getMethod())) || - (matcher.getApiPath() != null && !operatorMatch(request.getUri(), matcher.getApiPath()))) { + public RequestProcessor(Map operatorMap) { + this.operatorMap = new HashMap<>(operatorMap.size()); + operatorMap.forEach((k, v) -> this.operatorMap.put(v.name(), v)); + } + + public boolean match(GovernanceRequestExtractor request, Matcher matcher) { + if (!methodMatch(request, matcher)) { + return false; + } + if (!apiPathMatch(request, matcher)) { return false; } + if (!headersMatch(request, matcher)) { + return false; + } + if (!queriesMatch(request, matcher)) { + return false; + } + if (!serviceNameMatch(request, matcher)) { + return false; + } + return customMatch(request, matcher); + } + + private boolean serviceNameMatch(GovernanceRequestExtractor request, Matcher matcher) { + if (matcher.getServiceName() == null) { + return true; + } + return matcher.getServiceName().equals(request.serviceName()); + } + + private boolean headersMatch(GovernanceRequestExtractor request, Matcher matcher) { if (matcher.getHeaders() == null) { return true; } for (Entry entry : matcher.getHeaders().entrySet()) { - if (!request.getHeaders().containsKey(entry.getKey()) || - !operatorMatch(request.getHeaders().get(entry.getKey()), entry.getValue())) { + if (request.header(entry.getKey()) == null || + !operatorMatch(request.header(entry.getKey()), entry.getValue())) { return false; } } return true; } + private boolean queriesMatch(GovernanceRequestExtractor request, Matcher matcher) { + if (matcher.getQueries() == null) { + return true; + } + for (Entry entry : matcher.getQueries().entrySet()) { + if (request.query(entry.getKey()) == null || + !operatorMatch(request.query(entry.getKey()), entry.getValue())) { + return false; + } + } + return true; + } + + private boolean apiPathMatch(GovernanceRequestExtractor request, Matcher matcher) { + if (matcher.getApiPath() == null) { + return true; + } + return operatorMatch(request.apiPath(), matcher.getApiPath()); + } + + private boolean methodMatch(GovernanceRequestExtractor request, Matcher matcher) { + if (matcher.getMethod() == null) { + return true; + } + return matcher.getMethod().contains(request.method()); + } + private boolean operatorMatch(String str, RawOperator rawOperator) { if (rawOperator.isEmpty()) { return false; } for (Entry entry : rawOperator.entrySet()) { - MatchOperator operator = operatorMap.get(entry.getKey() + OPERATOR_SUFFIX); + MatchOperator operator = operatorMap.get(entry.getKey()); if (operator == null) { - LOGGER.error("unsupported operator:" + entry.getKey() + ", plz use one of :" + operatorMap.keySet().toString()); + LOGGER.error("unsupported operator:" + entry.getKey() + ", please use one of :" + operatorMap.keySet()); return false; } if (!operator.match(str, entry.getValue())) { @@ -70,4 +137,69 @@ private boolean operatorMatch(String str, RawOperator rawOperator) { } return true; } + + private boolean customMatch(GovernanceRequestExtractor request, Matcher matcher) { + if (matcher.getCustomMatcher() == null) { + return true; + } + String customMatcherHandlerName = matcher.getCustomMatcher().getCustomMatcherHandler(); + String customMatcherParameters = matcher.getCustomMatcher().getCustomMatcherParameters(); + + if (StringUtils.isEmpty(customMatcherHandlerName) || StringUtils.isEmpty(customMatcherParameters)) { + return true; + } + + CustomMatch customMatcherHandler = generateHandler(customMatcherHandlerName); + return customMatcherHandler.matchRequest(request, customMatcherParameters); + } + + private CustomMatch getBeanByHandlerName(String customMatcherHandler) { + Object extractObject = null; + if (applicationContext.containsBean(customMatcherHandler)) { + extractObject = applicationContext.getBean(customMatcherHandler); + if (!(extractObject instanceof CustomMatch)) { + LOGGER.error("{} {}", customMatcherHandler, errorMessageForNotImplements); + throw new RuntimeException(customMatcherHandler + errorMessageForNotImplements); + } + return (CustomMatch) extractObject; + } + return null; + } + + + public CustomMatch generateHandler(String customMatcherHandler) { + CustomMatch extractObject = getBeanByHandlerName(customMatcherHandler); + if (extractObject != null) { + return extractObject; + } + + LOGGER.info("{} {}", customMatcherHandler, infoMessageForCreatingClass); + Class extractionHandlerClass = null; + try { + extractionHandlerClass = Class.forName(customMatcherHandler); + } catch (ClassNotFoundException e) { + LOGGER.error(e.getMessage(), e); + throw new RuntimeException(e); + } + + if (!CustomMatch.class.isAssignableFrom(extractionHandlerClass)) { + LOGGER.error("{} {}", customMatcherHandler, errorMessageForNotImplements); + throw new RuntimeException(customMatcherHandler + errorMessageForNotImplements); + } + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(extractionHandlerClass); + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) applicationContext; + registry.registerBeanDefinition(customMatcherHandler, builder.getBeanDefinition()); + try { + extractObject = (CustomMatch) applicationContext.getBean(customMatcherHandler); + return extractObject; + } catch (BeansException e) { + LOGGER.error(e.getMessage(), e); + throw new RuntimeException(customMatcherHandler + errorMessageForAbstractClass, e); + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java index 9dbaf4d73a8..73dcd526c9a 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/TrafficMarker.java @@ -21,8 +21,6 @@ import org.apache.servicecomb.governance.entity.Configurable; public class TrafficMarker extends Configurable { - private String name; - private List matches; @Override @@ -41,18 +39,7 @@ public void setMatches(List matches) { this.matches = matches; } - @Override - public String getName() { - return name; - } - - @Override - public void setName(String name) { - this.name = name; - } - - public boolean checkMatch(GovernanceRequest governanceRequest, RequestProcessor requestProcessor) { - return this.matches.stream().anyMatch(match -> - this.name.equals(name) && requestProcessor.match(governanceRequest, match)); + public boolean checkMatch(GovernanceRequestExtractor extractor, RequestProcessor requestProcessor) { + return this.matches.stream().anyMatch(match -> requestProcessor.match(extractor, match)); } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/CompareOperator.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/CompareOperator.java index 6750a9b5dd7..5b73b9aa939 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/CompareOperator.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/CompareOperator.java @@ -19,15 +19,11 @@ import java.util.HashSet; import java.util.Set; -import org.springframework.stereotype.Component; - import org.apache.servicecomb.governance.exception.IllegalArgsOperatorException; - -@Component public class CompareOperator implements MatchOperator { - private Set charSet = new HashSet<>(); + private final Set charSet = new HashSet<>(); public CompareOperator() { charSet.add('>'); @@ -36,8 +32,13 @@ public CompareOperator() { charSet.add('!'); } + @Override + public String name() { + return "compare"; + } + /** - * 支持 > < = >= <= ! 后面加数字 + * 支持 {@code > < = >= <= !} 后面加数字 * * @param targetStr * @param patternStr diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ContainsOperator.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ContainsOperator.java index 8e8327069e7..faa40521441 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ContainsOperator.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ContainsOperator.java @@ -16,11 +16,13 @@ */ package org.apache.servicecomb.governance.marker.operator; -import org.springframework.stereotype.Component; - -@Component public class ContainsOperator implements MatchOperator { + @Override + public String name() { + return "contains"; + } + @Override public boolean match(String targetStr, String patternStr) { return targetStr.contains(patternStr); diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ExactOperator.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ExactOperator.java index 0a614279e98..cee8d48a27e 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ExactOperator.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/ExactOperator.java @@ -17,11 +17,14 @@ package org.apache.servicecomb.governance.marker.operator; import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Component; -@Component public class ExactOperator implements MatchOperator { + @Override + public String name() { + return "exact"; + } + @Override public boolean match(String targetStr, String patternStr) { return StringUtils.equals(targetStr, patternStr); diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/MatchOperator.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/MatchOperator.java index c4f157c4732..28abc1b8df5 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/MatchOperator.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/MatchOperator.java @@ -17,6 +17,7 @@ package org.apache.servicecomb.governance.marker.operator; public interface MatchOperator { + String name(); boolean match(String targetStr, String patternStr); -} \ No newline at end of file +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/PrefixOperator.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/PrefixOperator.java index 5fbf61107fb..6bb84c45a53 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/PrefixOperator.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/PrefixOperator.java @@ -18,10 +18,13 @@ package org.apache.servicecomb.governance.marker.operator; import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Component; -@Component public class PrefixOperator implements MatchOperator { + @Override + public String name() { + return "prefix"; + } + @Override public boolean match(String requestValue, String patternValue) { return StringUtils.startsWith(requestValue, patternValue); diff --git a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/SuffixOperator.java b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/SuffixOperator.java index 3e4a2241cb8..99adf9fed1e 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/SuffixOperator.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/marker/operator/SuffixOperator.java @@ -18,10 +18,13 @@ package org.apache.servicecomb.governance.marker.operator; import org.apache.commons.lang3.StringUtils; -import org.springframework.stereotype.Component; -@Component public class SuffixOperator implements MatchOperator { + @Override + public String name() { + return "suffix"; + } + @Override public boolean match(String requestValue, String patternValue) { return StringUtils.endsWith(requestValue, patternValue); diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java index 5ccf4f3a3b9..c1638bde086 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/AbstractPolicy.java @@ -16,28 +16,42 @@ */ package org.apache.servicecomb.governance.policy; +import java.time.Duration; + import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.governance.entity.Configurable; import org.apache.servicecomb.governance.utils.GovernanceUtils; -import java.time.Duration; - -public abstract class AbstractPolicy extends Configurable { +public abstract class AbstractPolicy extends Configurable implements Comparable { + protected int order = 0; @Override public boolean isValid() { return !StringUtils.isEmpty(name); } + @Override + public int compareTo(AbstractPolicy o) { + return this.order - o.order; + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + private Duration parseToDuration(String time, Duration defaultValue) { if (StringUtils.isEmpty(time)) { return defaultValue; } if (time.matches(GovernanceUtils.DIGIT_REGEX)) { - if (Long.valueOf(time) < 0) { + if (Long.parseLong(time) < 0) { throw new RuntimeException("The value of time should not be less than 0."); } - return Duration.ofMillis(Long.valueOf(time)); + return Duration.ofMillis(Long.parseLong(time)); } return Duration.parse(GovernanceUtils.DIGIT_PREFIX + time); } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/CircuitBreakerPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/CircuitBreakerPolicy.java index 56c87c69af3..1d1bdfeec79 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/policy/CircuitBreakerPolicy.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/CircuitBreakerPolicy.java @@ -16,13 +16,17 @@ */ package org.apache.servicecomb.governance.policy; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.governance.utils.GovernanceUtils; -import org.springframework.util.StringUtils; +import org.springframework.util.CollectionUtils; import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig.SlidingWindowType; -import java.time.Duration; - public class CircuitBreakerPolicy extends AbstractPolicy { public static final float DEFAULT_FAILURE_RATE_THRESHOLD = 50; @@ -41,6 +45,13 @@ public class CircuitBreakerPolicy extends AbstractPolicy { public static final String DEFAULT_SLIDING_WINDOW_SIZE = "100"; + public static final String DEFAULT_FAILURE_RESPONSE_STATUS_502 = "502"; + + public static final String DEFAULT_FAILURE_RESPONSE_STATUS_503 = "503"; + + public static final List DEFAULT_STATUS_LIST = Arrays.asList(DEFAULT_FAILURE_RESPONSE_STATUS_502, + DEFAULT_FAILURE_RESPONSE_STATUS_503); + private float failureRateThreshold = DEFAULT_FAILURE_RATE_THRESHOLD; private float slowCallRateThreshold = DEFAULT_SLOW_CALL_RATE_THRESHOLD; @@ -57,6 +68,15 @@ public class CircuitBreakerPolicy extends AbstractPolicy { private String slidingWindowSize = DEFAULT_SLIDING_WINDOW_SIZE; + //status code that need record as a failure + private List recordFailureStatus = DEFAULT_STATUS_LIST; + + //force close this circuit breaker. This parameter is not used by circuit breaker directly + private boolean forceClosed = false; + + //force open this circuit breaker. This parameter is not used by circuit breaker directly + private boolean forceOpen = false; + public CircuitBreakerPolicy() { } @@ -136,10 +156,12 @@ public SlidingWindowType getSlidingWindowTypeEnum() { if (StringUtils.isEmpty(slidingWindowType)) { return SlidingWindowType.TIME_BASED; } - if (SlidingWindowType.COUNT_BASED.equals(slidingWindowType)) { - return SlidingWindowType.COUNT_BASED; + + try { + return SlidingWindowType.valueOf(slidingWindowType); + } catch (Exception e) { + return SlidingWindowType.TIME_BASED; } - return SlidingWindowType.TIME_BASED; } public String getSlidingWindowType() { @@ -164,7 +186,7 @@ private String getValue(String slidingWindowSize) { return DEFAULT_SLIDING_WINDOW_SIZE; } if (slidingWindowSize.matches(GovernanceUtils.DIGIT_REGEX)) { - if (Long.valueOf(slidingWindowSize) < 0) { + if (Long.parseLong(slidingWindowSize) < 0) { throw new RuntimeException("The value should be more than 0."); } return slidingWindowSize; @@ -173,6 +195,37 @@ private String getValue(String slidingWindowSize) { return String.valueOf(duration.getSeconds()); } + public List getRecordFailureStatus() { + if (CollectionUtils.isEmpty(this.recordFailureStatus)) { + return DEFAULT_STATUS_LIST; + } + return this.recordFailureStatus; + } + + public void setRecordFailureStatus(List recordFailureStatus) { + if (recordFailureStatus == null) { + return; + } + this.recordFailureStatus = recordFailureStatus.stream().filter(e -> !StringUtils.isEmpty(e)) + .collect(Collectors.toList()); + } + + public boolean isForceClosed() { + return forceClosed; + } + + public void setForceClosed(boolean forceClosed) { + this.forceClosed = forceClosed; + } + + public boolean isForceOpen() { + return forceOpen; + } + + public void setForceOpen(boolean forceOpen) { + this.forceOpen = forceOpen; + } + @Override public String toString() { return "CircuitBreakerPolicy{" + @@ -184,6 +237,7 @@ public String toString() { ", minimumNumberOfCalls=" + minimumNumberOfCalls + ", slidingWindowType='" + slidingWindowType + '\'' + ", slidingWindowSize=" + slidingWindowSize + + ", recordFailureStatus=" + recordFailureStatus + '}'; } } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/FaultInjectionPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/FaultInjectionPolicy.java new file mode 100644 index 00000000000..4f9500d692e --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/FaultInjectionPolicy.java @@ -0,0 +1,113 @@ +/* + * 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.governance.policy; + +import java.time.Duration; + +import org.apache.servicecomb.governance.processor.injection.FaultInjectionConst; + +public class FaultInjectionPolicy extends AbstractPolicy { + public static final Duration DEFAULT_TIMEOUT_DURATION = Duration.ofMillis(0); + + private String type = FaultInjectionConst.TYPE_DELAY; + + private String delayTime = DEFAULT_TIMEOUT_DURATION.toString(); + + private int percentage = -1; + + private int errorCode = 500; + + private boolean forceClosed = false; + + private String fallbackType = FaultInjectionConst.FALLBACK_THROWEXCEPTION; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getDelayTime() { + return delayTime; + } + + public void setDelayTime(String delayTime) { + this.delayTime = stringOfDuration(delayTime, Duration.ofMillis(-1)); + } + + public int getPercentage() { + return percentage; + } + + public void setPercentage(int percentage) { + this.percentage = percentage; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public long getDelayTimeToMillis() { + return Duration.parse(delayTime).toMillis(); + } + + public boolean isForceClosed() { + return forceClosed; + } + + public void setForceClosed(boolean forceClosed) { + this.forceClosed = forceClosed; + } + + public String getFallbackType() { + return fallbackType; + } + + public void setFallbackType(String fallbackType) { + this.fallbackType = fallbackType; + } + + @Override + public boolean isValid() { + if (getDelayTimeToMillis() < 0 && FaultInjectionConst.TYPE_DELAY.equals(type)) { + return false; + } + if ((getErrorCode() < FaultInjectionConst.ERROR_CODE_MIN + || getErrorCode() > FaultInjectionConst.ERROR_CODE_MAX) + && FaultInjectionConst.TYPE_ABORT.equals(type)) { + return false; + } + return super.isValid(); + } + + @Override + public String toString() { + return "FaultInjectionPolicy{" + + "type=" + type + + ", delayTime=" + delayTime + + ", percentage=" + percentage + + ", errorCode=" + errorCode + + '}'; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceCachePolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceCachePolicy.java new file mode 100644 index 00000000000..719c9cf4134 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceCachePolicy.java @@ -0,0 +1,64 @@ +/* + * 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.governance.policy; + +import java.time.Duration; + +public class GovernanceCachePolicy extends AbstractPolicy { + public static final Duration DEFAULT_TTL = Duration.ofMillis(21600000); + + public static final long DEFAULT_MAXIMUM_SIZE = 60000; + + public static final int DEFAULT_CONCURRENCY_LEVEL = 8; + + private String ttl = DEFAULT_TTL.toString(); + + private long maximumSize = DEFAULT_MAXIMUM_SIZE; + + private int concurrencyLevel = DEFAULT_CONCURRENCY_LEVEL; + + public String getTtl() { + return ttl; + } + + public void setTtl(String ttl) { + this.ttl = stringOfDuration(ttl, DEFAULT_TTL); + } + + public Long getMaximumSize() { + return maximumSize; + } + + public void setMaximumSize(Long maximumSize) { + this.maximumSize = maximumSize; + } + + public int getConcurrencyLevel() { + return concurrencyLevel; + } + + public void setConcurrencyLevel(int concurrencyLevel) { + this.concurrencyLevel = concurrencyLevel; + } + + @Override + public String toString() { + return "CachePolicy{" + "ttl=" + ttl + ",concurrencyLevel=" + concurrencyLevel + ", maximumSize=" + maximumSize + + '}'; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/IdentifierRateLimitingPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/IdentifierRateLimitingPolicy.java new file mode 100644 index 00000000000..e49da76ffff --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/IdentifierRateLimitingPolicy.java @@ -0,0 +1,42 @@ +/* + * 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.governance.policy; + +import org.apache.commons.lang3.StringUtils; + +public class IdentifierRateLimitingPolicy extends RateLimitingPolicy { + /** + * header name used to identify this rate limiter + */ + protected String identifier; + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + @Override + public boolean isValid() { + if (StringUtils.isEmpty(identifier)) { + return false; + } + return super.isValid(); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/LoadBalancerPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/LoadBalancerPolicy.java new file mode 100644 index 00000000000..4e7e07e9f58 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/LoadBalancerPolicy.java @@ -0,0 +1,30 @@ +/* + * 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.governance.policy; + +public class LoadBalancerPolicy extends AbstractPolicy { + private String rule; + + public String getRule() { + return rule; + } + + public void setRule(String rule) { + this.rule = rule; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/MapperPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/MapperPolicy.java new file mode 100644 index 00000000000..76db6933602 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/MapperPolicy.java @@ -0,0 +1,32 @@ +/* + * 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.governance.policy; + +import java.util.Map; + +public class MapperPolicy extends AbstractPolicy { + private Map target; + + public Map getTarget() { + return target; + } + + public void setTarget(Map target) { + this.target = target; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/RateLimitingPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/RateLimitingPolicy.java index 1c6fb0e1b6c..29a9f6d9f69 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/policy/RateLimitingPolicy.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/RateLimitingPolicy.java @@ -26,12 +26,12 @@ public class RateLimitingPolicy extends AbstractPolicy { public static final int DEFAULT_LIMIT_FOR_PERIOD = 1000; - private String timeoutDuration = DEFAULT_TIMEOUT_DURATION.toString(); + protected String timeoutDuration = DEFAULT_TIMEOUT_DURATION.toString(); - private String limitRefreshPeriod = DEFAULT_LIMIT_REFRESH_PERIOD.toString(); + protected String limitRefreshPeriod = DEFAULT_LIMIT_REFRESH_PERIOD.toString(); // 配置项名称使用 rate, 对应于 resilience4j 的 limitForPeriod - private int rate = DEFAULT_LIMIT_FOR_PERIOD; + protected int rate = DEFAULT_LIMIT_FOR_PERIOD; public String getTimeoutDuration() { return timeoutDuration; diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/RetryPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/RetryPolicy.java index 59d5e85ce40..726121a2c20 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/policy/RetryPolicy.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/RetryPolicy.java @@ -16,20 +16,26 @@ */ package org.apache.servicecomb.governance.policy; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; - import java.time.Duration; -import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.CollectionUtils; public class RetryPolicy extends AbstractPolicy { public static final int DEFAULT_MAX_ATTEMPTS = 3; - public static final Duration DEFAULT_WAIT_DURATION = Duration.ofMillis(10); + public static final Duration DEFAULT_WAIT_DURATION = Duration.ofMillis(1); + + public static final String DEFAULT_RETRY_ON_RESPONSE_STATUS_502 = "502"; - public static final String DEFAULT_RETRY_ON_RESPONSE_STATUS = "502"; + public static final String DEFAULT_RETRY_ON_RESPONSE_STATUS_503 = "503"; + + public static final List DEFAULT_STATUS_LIST = Arrays.asList(DEFAULT_RETRY_ON_RESPONSE_STATUS_502, + DEFAULT_RETRY_ON_RESPONSE_STATUS_503); private static final Duration INITIAL_INTERVAL = Duration.ofMillis(1000); @@ -39,32 +45,47 @@ public class RetryPolicy extends AbstractPolicy { private static final String DEFAULT_RETRY_STRATEGY = "FixedInterval"; - //最多尝试次数 + //max retry attempts private int maxAttempts = DEFAULT_MAX_ATTEMPTS; - //每次重试尝试等待的时间。 + //wait duration for each retry private String waitDuration = DEFAULT_WAIT_DURATION.toString(); - //需要重试的http status, 逗号分隔 - private List retryOnResponseStatus = new ArrayList<>(); + //status code that need retry + private List retryOnResponseStatus = DEFAULT_STATUS_LIST; + //retry strategy private String retryStrategy = DEFAULT_RETRY_STRATEGY; + // initial interval for backoff retry private String initialInterval = INITIAL_INTERVAL.toString(); + // multiplier for backoff retry private float multiplier = MULTIPLIER; + // randomization factor for backoff retry private double randomizationFactor = RANDOMIZATION_FACTOR; + // if throw an MaxRetriesExceededException if retry condition is based on result + private boolean failAfterMaxAttempts = false; + + // if retry on the same instance. This property is not directly used in + // RetryHandler, but used for loadbalancers + private int retryOnSame = 0; + public List getRetryOnResponseStatus() { if (CollectionUtils.isEmpty(retryOnResponseStatus)) { - this.retryOnResponseStatus.add(DEFAULT_RETRY_ON_RESPONSE_STATUS); + return DEFAULT_STATUS_LIST; } return retryOnResponseStatus; } public void setRetryOnResponseStatus(List retryOnResponseStatus) { - this.retryOnResponseStatus = retryOnResponseStatus; + if (retryOnResponseStatus == null) { + return; + } + this.retryOnResponseStatus = retryOnResponseStatus.stream().filter(e -> !StringUtils.isEmpty(e)) + .collect(Collectors.toList()); } public int getMaxAttempts() { @@ -76,7 +97,7 @@ public void setMaxAttempts(int maxAttempts) { } public String getWaitDuration() { - return Duration.parse(waitDuration).toMillis() < 10 ? DEFAULT_WAIT_DURATION.toString() : waitDuration; + return Duration.parse(waitDuration).toMillis() < 1 ? DEFAULT_WAIT_DURATION.toString() : waitDuration; } public void setWaitDuration(String waitDuration) { @@ -118,6 +139,22 @@ public void setRandomizationFactor(double randomizationFactor) { this.randomizationFactor = randomizationFactor; } + public boolean isFailAfterMaxAttempts() { + return failAfterMaxAttempts; + } + + public void setFailAfterMaxAttempts(boolean failAfterMaxAttempts) { + this.failAfterMaxAttempts = failAfterMaxAttempts; + } + + public int getRetryOnSame() { + return retryOnSame; + } + + public void setRetryOnSame(int retryOnSame) { + this.retryOnSame = retryOnSame; + } + @Override public boolean isValid() { if (maxAttempts < 1) { diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/TimeLimiterPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/TimeLimiterPolicy.java new file mode 100644 index 00000000000..e00300127d6 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/TimeLimiterPolicy.java @@ -0,0 +1,45 @@ +/* + * 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.governance.policy; + +import java.time.Duration; + +public class TimeLimiterPolicy extends AbstractPolicy { + public static final Duration DEFAULT_TIMEOUT_DURATION = Duration.ofMillis(1000); + + public static final boolean DEFAULT_CANCEL_RUNNING_FUTURE = true; + + private String timeoutDuration = DEFAULT_TIMEOUT_DURATION.toString(); + + private boolean cancelRunningFuture = DEFAULT_CANCEL_RUNNING_FUTURE; + + public String getTimeoutDuration() { + return timeoutDuration; + } + + public void setTimeoutDuration(String timeoutDuration) { + this.timeoutDuration = stringOfDuration(timeoutDuration, DEFAULT_TIMEOUT_DURATION); + } + + public boolean isCancelRunningFuture() { + return cancelRunningFuture; + } + + public void setCancelRunningFuture(boolean cancelRunningFuture) { + this.cancelRunningFuture = cancelRunningFuture; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/AbortFault.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/AbortFault.java new file mode 100644 index 00000000000..c6423967601 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/AbortFault.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.governance.processor.injection; + +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AbortFault extends AbstractFault { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbortFault.class); + + public static final String ABORTED_ERROR_MSG = "aborted by fault inject"; + + public AbortFault(String key, FaultInjectionPolicy policy) { + super(key, policy); + } + + @Override + public boolean injectFault(FaultParam faultParam) { + return shouldAbort(faultParam, policy); + } + + private boolean shouldAbort(FaultParam param, FaultInjectionPolicy policy) { + // get the config values related to abort. + int abortPercent = policy.getPercentage(); + if (abortPercent == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: Abort percentage is not configured"); + return false; + } + + // check fault abort condition. + return FaultInjectionUtil.isFaultNeedToInject(param.getReqCount(), abortPercent); + } + + @Override + public int getOrder() { + return 200; + } + + @Override + public String getName() { + return FaultInjectionConst.TYPE_ABORT; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/AbstractFault.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/AbstractFault.java new file mode 100644 index 00000000000..c225ea9a2c6 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/AbstractFault.java @@ -0,0 +1,50 @@ +/* + * 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.governance.processor.injection; + +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; + +public abstract class AbstractFault implements Fault { + protected String key; + + protected FaultInjectionPolicy policy; + + public AbstractFault(String key, FaultInjectionPolicy policy) { + this.key = key; + this.policy = policy; + } + + @Override + public boolean injectFault() { + if (policy.isForceClosed()) { + return false; + } + FaultParam faultParam = FaultInjectionUtil.initFaultParam(key); + return injectFault(faultParam); + } + + @Override + public String getKey() { + return key; + } + + @Override + public FaultInjectionPolicy getPolicy() { + return policy; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/DelayFault.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/DelayFault.java new file mode 100644 index 00000000000..bc82c9178ff --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/DelayFault.java @@ -0,0 +1,74 @@ +/* + * 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.governance.processor.injection; + +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DelayFault extends AbstractFault { + private static final Logger LOGGER = LoggerFactory.getLogger(DelayFault.class); + + public DelayFault(String key, FaultInjectionPolicy policy) { + super(key, policy); + } + + @Override + public int getOrder() { + return 100; + } + + @Override + public boolean injectFault(FaultParam faultParam) { + if (!shouldDelay(faultParam, policy)) { + return false; + } + + LOGGER.debug("Fault injection: delay is added for the request by fault inject handler"); + long delay = policy.getDelayTimeToMillis(); + if (delay == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: delay is not configured"); + return false; + } + + executeDelay(faultParam, delay); + return false; + } + + private void executeDelay(FaultParam faultParam, long delay) { + Sleepable sleepable = faultParam.getSleepable(); + if (sleepable != null) { + sleepable.sleep(delay); + } + } + + private boolean shouldDelay(FaultParam param, FaultInjectionPolicy policy) { + int delayPercent = policy.getPercentage(); + if (delayPercent == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: delay percentage is not configured"); + return false; + } + // check fault delay condition. + return FaultInjectionUtil.isFaultNeedToInject(param.getReqCount(), delayPercent); + } + + @Override + public String getName() { + return FaultInjectionConst.TYPE_DELAY; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/Fault.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/Fault.java new file mode 100644 index 00000000000..204186eaed4 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/Fault.java @@ -0,0 +1,58 @@ +/* + * 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.governance.processor.injection; + +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; + +import io.vavr.CheckedFunction0; + +public interface Fault { + static CheckedFunction0 decorateCheckedSupplier(Fault fault, CheckedFunction0 supplier) { + return () -> { + if (fault.injectFault()) { + if (FaultInjectionConst.FALLBACK_THROWEXCEPTION.equals(fault.getPolicy().getFallbackType())) { + throw new FaultInjectionException( + FaultResponse.createFail(fault.getPolicy().getErrorCode(), AbortFault.ABORTED_ERROR_MSG)); + } else { + return null; + } + } + return supplier.apply(); + }; + } + + int getOrder(); + + String getName(); + + /* + * If true is returned,the downgrade governance policy is executed. + * Otherwise,the original request is directly executed. + * */ + boolean injectFault(); + + /* + * If true is returned,the downgrade governance policy is executed. + * Otherwise,the original request is directly executed. + * */ + boolean injectFault(FaultParam faultParam); + + String getKey(); + + FaultInjectionPolicy getPolicy(); +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionConst.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionConst.java new file mode 100644 index 00000000000..35f27691028 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionConst.java @@ -0,0 +1,38 @@ +/* + * 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.governance.processor.injection; + +/** + * Handles the all constant values for fault injection. + */ +public class FaultInjectionConst { + + public static final int FAULT_INJECTION_DEFAULT_VALUE = -1; + + public static final String TYPE_DELAY = "delay"; + + public static final String TYPE_ABORT = "abort"; + + public static final String FALLBACK_THROWEXCEPTION = "ThrowException"; + + public static final String FALLBACK_RETURNNULL = "ReturnNull"; + + public static final int ERROR_CODE_MIN = 200; + + public static final int ERROR_CODE_MAX = 600; +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionDecorators.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionDecorators.java new file mode 100644 index 00000000000..e5eb7e0ffce --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionDecorators.java @@ -0,0 +1,45 @@ +/* + * 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.governance.processor.injection; + +import io.vavr.CheckedFunction0; + +public interface FaultInjectionDecorators { + static FaultInjectionDecorateCheckedSupplier ofCheckedSupplier(CheckedFunction0 supplier) { + return new FaultInjectionDecorateCheckedSupplier<>(supplier); + } + + class FaultInjectionDecorateCheckedSupplier { + + private CheckedFunction0 supplier; + + protected FaultInjectionDecorateCheckedSupplier(CheckedFunction0 supplier) { + this.supplier = supplier; + } + + public FaultInjectionDecorateCheckedSupplier withFaultInjection(Fault fault) { + supplier = Fault.decorateCheckedSupplier(fault, supplier); + return this; + } + + public T get() throws Throwable { + return supplier.apply(); + } + } + +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionException.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionException.java new file mode 100644 index 00000000000..13058eca196 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionException.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.governance.processor.injection; + +public class FaultInjectionException extends RuntimeException { + private static final long serialVersionUID = 1675558351029273343L; + + private final FaultResponse faultResponse; + + public FaultInjectionException(FaultResponse faultResponse) { + super(faultResponse.getErrorMsg()); + this.faultResponse = faultResponse; + } + + public FaultResponse getFaultResponse() { + return faultResponse; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionUtil.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionUtil.java new file mode 100644 index 00000000000..c7a1fdb6d7d --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultInjectionUtil.java @@ -0,0 +1,104 @@ +/* + * 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.governance.processor.injection; + +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; + +import io.vertx.core.Context; +import io.vertx.core.Vertx; + +/** + * Handles the count for all request based key[transport + microservice qualified name]. + */ +public final class FaultInjectionUtil { + + private FaultInjectionUtil() { + } + + /** + * key is transport+operQualifiedName + */ + private static final Map REQUEST_COUNT = new ConcurrentHashMapEx<>(); + + /** + * Returns total requests per provider for operational level. + * + * @param key + * transport+operational name + * @return long total requests + */ + public static AtomicLong getOperMetTotalReq(String key) { + return REQUEST_COUNT.computeIfAbsent(key, p -> new AtomicLong(1)); + } + + /** + * It will check the delay/abort condition based on request count and percentage + * received. + * + * @param reqCount total request count of the uri + * @param percentage the percentage of hitting fault injection + * @return true: delay/abort is needed. false: delay/abort is not needed. + */ + public static boolean isFaultNeedToInject(long reqCount, int percentage) { + /* + * Example: delay/abort percentage configured is 10% and Get the count(suppose + * if it is 10th request) from map and calculate resultNew(10th request) and + * requestOld(9th request). Like this for every request it will calculate + * current request count and previous count. if both not matched need to add + * delay/abort otherwise no need to add. + */ + + // calculate the value with current request count. + long resultNew = (reqCount * percentage) / 100; + + // calculate the value with previous count value. + long resultOld = ((reqCount - 1) * percentage) / 100; + + // if both are not matching then delay/abort should be added. + return (resultNew != resultOld); + } + + public static Fault getFault(String key, FaultInjectionPolicy policy) { + Fault fault = null; + if (FaultInjectionConst.TYPE_DELAY.equals(policy.getType())) { + fault = new DelayFault(key, policy); + } else if (FaultInjectionConst.TYPE_ABORT.equals(policy.getType())) { + fault = new AbortFault(key, policy); + } + return fault; + } + + public static FaultParam initFaultParam(String key) { + AtomicLong reqCount = FaultInjectionUtil.getOperMetTotalReq(key); + // increment the request count here after checking the delay/abort condition. + long reqCountCurrent = reqCount.getAndIncrement(); + + FaultParam param = new FaultParam(reqCountCurrent); + Context currentContext = Vertx.currentContext(); + if (currentContext != null && currentContext.owner() != null && currentContext.isEventLoopContext()) { + param.setSleepable( + (delay) -> currentContext.owner().setTimer(delay, timeId -> {})); + } + return param; + } + +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultParam.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultParam.java new file mode 100644 index 00000000000..9cd4c6611cb --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultParam.java @@ -0,0 +1,54 @@ +/* + * 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.governance.processor.injection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Fault injection parameters which decides the fault injection condition. + */ +public class FaultParam { + private static final Logger LOGGER = LoggerFactory.getLogger(FaultParam.class); + + private final long reqCount; + + private Sleepable sleepable = (delay) -> { + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + LOGGER.info("Interrupted exception is received"); + } + }; + + public long getReqCount() { + return reqCount; + } + + public FaultParam(long reqCount) { + this.reqCount = reqCount; + } + + public Sleepable getSleepable() { + return sleepable; + } + + public void setSleepable(Sleepable sleepable) { + this.sleepable = sleepable; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultResponse.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultResponse.java new file mode 100644 index 00000000000..01b8fc8d263 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/FaultResponse.java @@ -0,0 +1,48 @@ +/* + * 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.governance.processor.injection; + +public class FaultResponse { + + private int errorCode; + + private String errorMsg; + + public static FaultResponse createFail(int errorCode, String errorMsg) { + FaultResponse faultResponse = new FaultResponse(); + faultResponse.setErrorCode(errorCode); + faultResponse.setErrorMsg(errorMsg); + return faultResponse; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/Sleepable.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/Sleepable.java new file mode 100644 index 00000000000..22a95074f29 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/injection/Sleepable.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.governance.processor.injection; + +public interface Sleepable { + /** + * sleep some time + * @param delay time unit is millisecond + */ + void sleep(long delay); +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/loadbanlance/LoadBalance.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/loadbanlance/LoadBalance.java new file mode 100644 index 00000000000..105c4fc59dc --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/loadbanlance/LoadBalance.java @@ -0,0 +1,30 @@ +/* + * 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.governance.processor.loadbanlance; + +import org.apache.servicecomb.governance.policy.LoadBalancerPolicy; + +public interface LoadBalance { + + static LoadBalance getLoadBalance(String key, LoadBalancerPolicy policy) { + LoadBalance loadBalance = new LoadBalanceImpl(policy.getRule()); + return loadBalance; + } + + String getRule(); +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/loadbanlance/LoadBalanceImpl.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/loadbanlance/LoadBalanceImpl.java new file mode 100644 index 00000000000..48fb023fac7 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/loadbanlance/LoadBalanceImpl.java @@ -0,0 +1,30 @@ +/* + * 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.governance.processor.loadbanlance; + +public class LoadBalanceImpl implements LoadBalance { + private final String rule; + + public LoadBalanceImpl(String rule) { + this.rule = rule; + } + + public String getRule() { + return rule; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/processor/mapping/Mapper.java b/governance/src/main/java/org/apache/servicecomb/governance/processor/mapping/Mapper.java new file mode 100644 index 00000000000..f9c435ecec1 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/processor/mapping/Mapper.java @@ -0,0 +1,28 @@ +/* + * 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.governance.processor.mapping; + +import java.util.Map; + +public interface Mapper { + static Mapper create(Map target) { + return () -> target; + } + + Map target(); +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java index 2e340b7861f..62d6cc2c7e9 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/BulkheadProperties.java @@ -18,14 +18,16 @@ package org.apache.servicecomb.governance.properties; import org.apache.servicecomb.governance.policy.BulkheadPolicy; -import org.springframework.stereotype.Component; -@Component public class BulkheadProperties extends PolicyProperties { - public static final String MATCH_BULKHEAD__KEY = "servicecomb.bulkhead"; + public static final String MATCH_BULKHEAD_KEY = "servicecomb.bulkhead"; public BulkheadProperties() { - super(MATCH_BULKHEAD__KEY); + super(MATCH_BULKHEAD_KEY); + } + + public BulkheadProperties(String key) { + super(key); } @Override diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java index 578d34604ae..96aa701ad70 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/CircuitBreakerProperties.java @@ -17,9 +17,7 @@ package org.apache.servicecomb.governance.properties; import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy; -import org.springframework.stereotype.Component; -@Component public class CircuitBreakerProperties extends PolicyProperties { public static final String MATCH_CIRCUITBREAKER_KEY = "servicecomb.circuitBreaker"; @@ -27,6 +25,10 @@ public CircuitBreakerProperties() { super(MATCH_CIRCUITBREAKER_KEY); } + public CircuitBreakerProperties(String key) { + super(key); + } + @Override public Class getEntityClass() { return CircuitBreakerPolicy.class; diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/FaultInjectionProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/FaultInjectionProperties.java new file mode 100644 index 00000000000..3a881352cb4 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/FaultInjectionProperties.java @@ -0,0 +1,37 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; + +public class FaultInjectionProperties extends PolicyProperties { + public static final String MATCH_FAULT_INJECTION_KEY = "servicecomb.faultInjection"; + + public FaultInjectionProperties() { + super(MATCH_FAULT_INJECTION_KEY); + } + + public FaultInjectionProperties(String key) { + super(key); + } + + @Override + public Class getEntityClass() { + return FaultInjectionPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceCacheProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceCacheProperties.java new file mode 100644 index 00000000000..9ae9a8daa96 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceCacheProperties.java @@ -0,0 +1,36 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.GovernanceCachePolicy; + +public class GovernanceCacheProperties extends PolicyProperties { + public static final String MATCH_CACHE_KEY = "servicecomb.cache"; + + public GovernanceCacheProperties() { + super(MATCH_CACHE_KEY); + } + + public GovernanceCacheProperties(String key) { + super(key); + } + + @Override + public Class getEntityClass() { + return GovernanceCachePolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java index ef1d0d99a92..05f42dfa5b1 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceProperties.java @@ -24,6 +24,7 @@ import java.util.Map.Entry; import java.util.Set; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.governance.MicroserviceMeta; import org.apache.servicecomb.governance.entity.Configurable; import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; @@ -38,7 +39,8 @@ import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; @@ -49,16 +51,24 @@ public abstract class GovernanceProperties implements InitializingBean { private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceProperties.class); - private final Representer representer = new Representer(); + private final Representer representer = new Representer(new DumperOptions()); private final String configKey; - @Autowired protected Environment environment; - @Autowired private MicroserviceMeta microserviceMeta; + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Autowired + public void setMicroserviceMeta(MicroserviceMeta microserviceMeta) { + this.microserviceMeta = microserviceMeta; + } + protected Map parsedEntity; protected Class entityClass; @@ -70,6 +80,10 @@ protected GovernanceProperties(String key) { entityClass = getEntityClass(); } + public String getConfigKey() { + return this.configKey; + } + @Override public void afterPropertiesSet() { parsedEntity = parseEntity(readPropertiesFromPrefix()); @@ -160,7 +174,8 @@ protected T parseEntityItem(String key, String value) { } try { - Yaml entityParser = new Yaml(new Constructor(new TypeDescription(entityClass, entityClass)), representer); + Yaml entityParser = new Yaml(new Constructor(new TypeDescription(entityClass, entityClass), new LoaderOptions()), + representer); T result = entityParser.loadAs(value, entityClass); result.setName(key); @@ -184,8 +199,8 @@ private boolean servicesMatch(String services) { return true; } - return Arrays.stream(services.split(",")).anyMatch(ser -> { - String[] serviceAndVersion = ser.split(":"); + return Arrays.stream(services.split(",")).anyMatch(service -> { + String[] serviceAndVersion = service.split(":"); if (serviceAndVersion.length == 1) { return microserviceMeta.getName().equals(serviceAndVersion[0]); } else if (serviceAndVersion.length == 2) { diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/IdentifierRateLimitProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/IdentifierRateLimitProperties.java new file mode 100644 index 00000000000..7db52c45b4b --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/IdentifierRateLimitProperties.java @@ -0,0 +1,36 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.IdentifierRateLimitingPolicy; + +public class IdentifierRateLimitProperties extends PolicyProperties { + public static final String MATCH_RATE_LIMIT_KEY = "servicecomb.identifierRateLimiting"; + + public IdentifierRateLimitProperties() { + super(MATCH_RATE_LIMIT_KEY); + } + + public IdentifierRateLimitProperties(String key) { + super(key); + } + + @Override + public Class getEntityClass() { + return IdentifierRateLimitingPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/InstanceBulkheadProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/InstanceBulkheadProperties.java new file mode 100644 index 00000000000..12627046745 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/InstanceBulkheadProperties.java @@ -0,0 +1,37 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.BulkheadPolicy; + +public class InstanceBulkheadProperties extends PolicyProperties { + public static final String MATCH_INSTANCE_BULKHEAD_KEY = "servicecomb.instanceBulkhead"; + + public InstanceBulkheadProperties() { + super(MATCH_INSTANCE_BULKHEAD_KEY); + } + + public InstanceBulkheadProperties(String key) { + super(key); + } + + @Override + public Class getEntityClass() { + return BulkheadPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/InstanceIsolationProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/InstanceIsolationProperties.java new file mode 100644 index 00000000000..e47193fd340 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/InstanceIsolationProperties.java @@ -0,0 +1,37 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy; + +public class InstanceIsolationProperties extends PolicyProperties { + public static final String MATCH_INSTANCE_ISOLATION_KEY = "servicecomb.instanceIsolation"; + + public InstanceIsolationProperties() { + super(MATCH_INSTANCE_ISOLATION_KEY); + } + + public InstanceIsolationProperties(String key) { + super(key); + } + + @Override + public Class getEntityClass() { + return CircuitBreakerPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/LoadBalanceProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/LoadBalanceProperties.java new file mode 100644 index 00000000000..892bbb8a580 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/LoadBalanceProperties.java @@ -0,0 +1,37 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.LoadBalancerPolicy; + +public class LoadBalanceProperties extends PolicyProperties { + public static final String MATCH_LOADBANLANCER_KEY = "servicecomb.loadbalance"; + + public LoadBalanceProperties() { + super(MATCH_LOADBANLANCER_KEY); + } + + public LoadBalanceProperties(String key) { + super(key); + } + + @Override + protected Class getEntityClass() { + return LoadBalancerPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/MapperProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/MapperProperties.java new file mode 100644 index 00000000000..5a20d4dd346 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/MapperProperties.java @@ -0,0 +1,37 @@ +/* + * 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.governance.properties; + +import org.apache.servicecomb.governance.policy.MapperPolicy; + +public class MapperProperties extends PolicyProperties { + public static final String MATCH_MAPPER_KEY = "servicecomb.mapper"; + + public MapperProperties() { + super(MATCH_MAPPER_KEY); + } + + public MapperProperties(String key) { + super(key); + } + + @Override + protected Class getEntityClass() { + return MapperPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java index 3188f90df1e..ca551e9c781 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/MatchProperties.java @@ -17,9 +17,7 @@ package org.apache.servicecomb.governance.properties; import org.apache.servicecomb.governance.marker.TrafficMarker; -import org.springframework.stereotype.Component; -@Component public class MatchProperties extends GovernanceProperties { public static final String MATCH_POLICY_KEY = "servicecomb.matchGroup"; diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java index 472901cf846..c3c09434636 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/RateLimitProperties.java @@ -18,9 +18,7 @@ import org.apache.servicecomb.governance.policy.RateLimitingPolicy; -import org.springframework.stereotype.Component; -@Component public class RateLimitProperties extends PolicyProperties { public static final String MATCH_RATE_LIMIT_KEY = "servicecomb.rateLimiting"; @@ -28,6 +26,10 @@ public RateLimitProperties() { super(MATCH_RATE_LIMIT_KEY); } + public RateLimitProperties(String key) { + super(key); + } + @Override public Class getEntityClass() { return RateLimitingPolicy.class; diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java index 483ea529706..50106c2a003 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/RetryProperties.java @@ -17,9 +17,7 @@ package org.apache.servicecomb.governance.properties; import org.apache.servicecomb.governance.policy.RetryPolicy; -import org.springframework.stereotype.Component; -@Component public class RetryProperties extends PolicyProperties { public static final String MATCH_RETRY_KEY = "servicecomb.retry"; @@ -27,6 +25,10 @@ public RetryProperties() { super(MATCH_RETRY_KEY); } + public RetryProperties(String key) { + super(key); + } + @Override public Class getEntityClass() { return RetryPolicy.class; diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/TimeLimiterProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/TimeLimiterProperties.java new file mode 100644 index 00000000000..daca14f57f4 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/TimeLimiterProperties.java @@ -0,0 +1,37 @@ +/* + * 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.governance.properties; + + +import org.apache.servicecomb.governance.policy.TimeLimiterPolicy; + +public class TimeLimiterProperties extends PolicyProperties { + public static final String MATCH_TIMELIMITER_KEY = "servicecomb.timeLimiter"; + + public TimeLimiterProperties() { + super(MATCH_TIMELIMITER_KEY); + } + + public TimeLimiterProperties(String key) { + super(key); + } + + @Override + public Class getEntityClass() { + return TimeLimiterPolicy.class; + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCache.java b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCache.java new file mode 100644 index 00000000000..35014272fd9 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCache.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.governance.service; + +import com.google.common.cache.Cache; + +import java.util.Objects; + +public interface GovernanceCache { + static GovernanceCache of(Cache cache) { + Objects.requireNonNull(cache, "Cache must not be null"); + return new GovernanceCacheImpl<>(cache); + } + + V getValueFromCache(K cacheKey); + + void putValueIntoCache(K cacheKey, V value); +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCacheImpl.java b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCacheImpl.java new file mode 100644 index 00000000000..a7dcfa5d4e7 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCacheImpl.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.governance.service; + +import com.google.common.cache.Cache; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GovernanceCacheImpl implements GovernanceCache { + + private static final Logger LOG = LoggerFactory.getLogger(GovernanceCacheImpl.class); + + private final Cache cache; + + public GovernanceCacheImpl(Cache cache) { + this.cache = cache; + } + + public V getValueFromCache(K cacheKey) { + try { + return cache.getIfPresent(cacheKey); + } catch (Exception exception) { + LOG.warn("Failed to get a value from Cache", exception); + return null; + } + } + + @Override + public void putValueIntoCache(K cacheKey, V value) { + try { + cache.put(cacheKey, value); + } catch (Exception exception) { + LOG.warn("Failed to put a value into Cache {}", exception); + } + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java index 43d2756558d..1b0f0b42f9a 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersService.java @@ -16,8 +16,8 @@ */ package org.apache.servicecomb.governance.service; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; public interface MatchersService { - boolean checkMatch(GovernanceRequest governanceRequest, String key); + boolean checkMatch(GovernanceRequestExtractor governanceRequest, String key); } diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java index 5a6ca5b2429..cc851f16892 100644 --- a/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java +++ b/governance/src/main/java/org/apache/servicecomb/governance/service/MatchersServiceImpl.java @@ -19,23 +19,23 @@ import java.util.Map; -import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.governance.marker.RequestProcessor; import org.apache.servicecomb.governance.marker.TrafficMarker; import org.apache.servicecomb.governance.properties.MatchProperties; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -@Component public class MatchersServiceImpl implements MatchersService { - @Autowired - private RequestProcessor requestProcessor; + private final RequestProcessor requestProcessor; - @Autowired - private MatchProperties matchProperties; + private final MatchProperties matchProperties; + + public MatchersServiceImpl(RequestProcessor requestProcessor, MatchProperties matchProperties) { + this.requestProcessor = requestProcessor; + this.matchProperties = matchProperties; + } @Override - public boolean checkMatch(GovernanceRequest governanceRequest, String key) { + public boolean checkMatch(GovernanceRequestExtractor governanceRequest, String key) { Map parsedEntity = matchProperties.getParsedEntity(); TrafficMarker trafficMarker = parsedEntity.get(key); diff --git a/governance/src/main/java/org/apache/servicecomb/governance/utils/CustomMatch.java b/governance/src/main/java/org/apache/servicecomb/governance/utils/CustomMatch.java new file mode 100644 index 00000000000..d2627e82af8 --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/governance/utils/CustomMatch.java @@ -0,0 +1,24 @@ +/* + * 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.governance.utils; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; + +public interface CustomMatch { + boolean matchRequest(GovernanceRequestExtractor requestExtractor, String parameters); +} diff --git a/governance/src/main/java/org/apache/servicecomb/router/RouterCommonConfiguration.java b/governance/src/main/java/org/apache/servicecomb/router/RouterCommonConfiguration.java new file mode 100644 index 00000000000..9aa881ee8df --- /dev/null +++ b/governance/src/main/java/org/apache/servicecomb/router/RouterCommonConfiguration.java @@ -0,0 +1,42 @@ +/* + * 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.router; + +import org.apache.servicecomb.governance.marker.RequestProcessor; +import org.apache.servicecomb.router.cache.RouterRuleCache; +import org.apache.servicecomb.router.match.RouterRuleMatcher; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class RouterCommonConfiguration { + @Bean + public RouterRuleCache scbRouterRuleCache(Environment environment) { + return new RouterRuleCache(environment); + } + + @Bean + public RouterRuleMatcher scbRouterRuleMatcher(RouterRuleCache routerRuleCache, RequestProcessor requestProcessor) { + return new RouterRuleMatcher(routerRuleCache, requestProcessor); + } + + @Bean + public RouterFilter scbRouterFilter(RouterRuleMatcher routerRuleMatcher, RouterRuleCache routerRuleCache) { + return new RouterFilter(routerRuleMatcher, routerRuleCache); + } +} diff --git a/governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java b/governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java index 11eb8219680..ab742e8613d 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java +++ b/governance/src/main/java/org/apache/servicecomb/router/RouterFilter.java @@ -17,49 +17,45 @@ package org.apache.servicecomb.router; import java.util.List; -import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; import org.apache.servicecomb.router.cache.RouterRuleCache; import org.apache.servicecomb.router.distribute.RouterDistributor; import org.apache.servicecomb.router.match.RouterRuleMatcher; import org.apache.servicecomb.router.model.PolicyRuleItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; -@Component public class RouterFilter { private static final Logger LOGGER = LoggerFactory.getLogger(RouterFilter.class); - @Autowired - private RouterRuleMatcher routerRuleMatcher; + private final RouterRuleMatcher routerRuleMatcher; - @Autowired - private RouterRuleCache routerRuleCache; + private final RouterRuleCache routerRuleCache; - public List getFilteredListOfServers(List list, - String targetServiceName, Map headers, RouterDistributor distributer) { + public RouterFilter(RouterRuleMatcher routerRuleMatcher, RouterRuleCache routerRuleCache) { + this.routerRuleMatcher = routerRuleMatcher; + this.routerRuleCache = routerRuleCache; + } + + public List getFilteredListOfServers(List list, + String targetServiceName, GovernanceRequestExtractor extractor, RouterDistributor distributor) { if (CollectionUtils.isEmpty(list)) { return list; } if (StringUtils.isEmpty(targetServiceName)) { return list; } - /** - * 1.init and cache - */ + // 1.init and cache if (!routerRuleCache.doInit(targetServiceName)) { LOGGER.debug("route management init failed"); return list; } - /** - * 2.match rule - */ - PolicyRuleItem invokeRule = routerRuleMatcher.match(targetServiceName, headers); + // 2.match rule + PolicyRuleItem invokeRule = routerRuleMatcher.match(targetServiceName, extractor); if (invokeRule == null) { LOGGER.debug("route management match rule failed"); @@ -68,10 +64,8 @@ public List getFilteredListOfServers(List list, LOGGER.debug("route management match rule success: {}", invokeRule); - /** - * 3.distribute select endpoint - */ - List resultList = distributer.distribute(targetServiceName, list, invokeRule); + // 3.distribute select endpoint + List resultList = distributor.distribute(targetServiceName, list, invokeRule); LOGGER.debug("route management distribute rule success: {}", resultList); diff --git a/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java b/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java index d4a162c5be1..7828c82d3a7 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java +++ b/governance/src/main/java/org/apache/servicecomb/router/cache/RouterRuleCache.java @@ -27,10 +27,10 @@ import org.apache.servicecomb.router.model.ServiceInfoCache; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; -import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; +import org.yaml.snakeyaml.DumperOptions; +import org.yaml.snakeyaml.LoaderOptions; import org.yaml.snakeyaml.TypeDescription; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.constructor.Constructor; @@ -39,7 +39,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.eventbus.Subscribe; -@Component public class RouterRuleCache { private static final Logger LOGGER = LoggerFactory.getLogger(RouterRuleCache.class); @@ -47,16 +46,18 @@ public class RouterRuleCache { private static final String ROUTE_RULE = "servicecomb.routeRule.%s"; - @Autowired - private Environment environment; + public static final String GLOBAL_ROUTE_RULE_KEY = "servicecomb.globalRouteRule"; + + private final Environment environment; private final ConcurrentHashMap serviceInfoCacheMap = new ConcurrentHashMap<>(); private final Object lock = new Object(); - private final Representer representer = new Representer(); + private final Representer representer = new Representer(new DumperOptions()); - public RouterRuleCache() { + public RouterRuleCache(Environment environment) { + this.environment = environment; representer.getPropertyUtils().setSkipMissingProperties(true); GovernanceEventManager.register(this); } @@ -75,7 +76,7 @@ public boolean doInit(String targetServiceName) { if (serviceInfoCacheMap.containsKey(targetServiceName)) { return true; } - return addAllRule(targetServiceName, environment.getProperty(String.format(ROUTE_RULE, targetServiceName), "")); + return addAllRule(targetServiceName); } } return true; @@ -87,17 +88,25 @@ public void onConfigurationChangedEvent(GovernanceConfigurationChangedEvent even if (key.startsWith(ROUTE_RULE_PREFIX)) { serviceInfoCacheMap.remove(key.substring(ROUTE_RULE_PREFIX.length())); } + if (key.equals(GLOBAL_ROUTE_RULE_KEY)) { + serviceInfoCacheMap.clear(); + } } } - private boolean addAllRule(String targetServiceName, String ruleStr) { + private boolean addAllRule(String targetServiceName) { + String ruleStr = environment.getProperty(String.format(ROUTE_RULE, targetServiceName), ""); + if (StringUtils.isEmpty(ruleStr)) { + ruleStr = environment.getProperty(GLOBAL_ROUTE_RULE_KEY, ""); + } if (StringUtils.isEmpty(ruleStr)) { return false; } List policyRuleItemList; try { Yaml entityParser = new Yaml( - new Constructor(new TypeDescription(PolicyRuleItem[].class, PolicyRuleItem[].class)), representer); + new Constructor(new TypeDescription(PolicyRuleItem[].class, PolicyRuleItem[].class), new LoaderOptions()), + representer); policyRuleItemList = Arrays .asList(entityParser.loadAs(ruleStr, PolicyRuleItem[].class)); } catch (Exception e) { @@ -110,6 +119,8 @@ private boolean addAllRule(String targetServiceName, String ruleStr) { } ServiceInfoCache serviceInfoCache = new ServiceInfoCache(policyRuleItemList); serviceInfoCacheMap.put(targetServiceName, serviceInfoCache); + LOGGER.info("Route management serialization service {} rules success, content: {}", targetServiceName, + serviceInfoCache.getAllrule()); return true; } @@ -117,7 +128,8 @@ private boolean addAllRule(String targetServiceName, String ruleStr) { * if a server don't have rule , avoid registered too many callback , it may cause memory leak */ private boolean isServerContainRule(String targetServiceName) { - return !StringUtils.isEmpty(environment.getProperty(String.format(ROUTE_RULE, targetServiceName), "")); + return !StringUtils.isEmpty(environment.getProperty(String.format(ROUTE_RULE, targetServiceName), "")) || + !StringUtils.isEmpty(environment.getProperty(GLOBAL_ROUTE_RULE_KEY, "")); } public ConcurrentHashMap getServiceInfoCacheMap() { diff --git a/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java b/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java index dd9b072c0bd..d3905dfb133 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java +++ b/governance/src/main/java/org/apache/servicecomb/router/distribute/AbstractRouterDistributor.java @@ -17,144 +17,164 @@ package org.apache.servicecomb.router.distribute; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; -import java.util.stream.Collectors; import org.apache.servicecomb.router.cache.RouterRuleCache; import org.apache.servicecomb.router.model.PolicyRuleItem; import org.apache.servicecomb.router.model.RouteItem; import org.apache.servicecomb.router.model.TagItem; -import org.apache.servicecomb.router.util.VersionCompareUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; -public abstract class AbstractRouterDistributor implements - RouterDistributor { +public abstract class AbstractRouterDistributor implements + RouterDistributor { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractRouterDistributor.class); - private Function getIns; + private Function getVersion; - private Function getVersion; + private Function getServerName; - private Function getServerName; + private Function> getProperties; - private Function> getProperties; + private RouterRuleCache routerRuleCache; @Autowired - private RouterRuleCache routerRuleCache; + public void setRouterRuleCache(RouterRuleCache routerRuleCache) { + this.routerRuleCache = routerRuleCache; + } + + protected AbstractRouterDistributor() { + } + /** + * distribute logic: + * 1、First according to the set route rules to choose target instances, if have just return. + * 2、if route rules not match instance, check if fallback rules are set, if set and match instances then return. + * 3、if route and fallback routes all have not match instance, then if route rules weight count less 100, return + * unset instances, otherwise return all instances. + * @param targetServiceName + * @param list + * @param invokeRule + * @return + */ @Override - public List distribute(String targetServiceName, List list, PolicyRuleItem invokeRule) { - //init LatestVersion - initLatestVersion(targetServiceName, list); + public List distribute(String targetServiceName, List list, PolicyRuleItem invokeRule) { + invokeRule.check(); - invokeRule.check( - routerRuleCache.getServiceInfoCacheMap().get(targetServiceName).getLatestVersionTag()); + // unSetTags instance list + List unSetTagInstances = new ArrayList<>(); - // get tag list - Map> versionServerMap = getDistributList(targetServiceName, list, invokeRule); + // record fallback router targItem instance + Map> fallbackVersionServerMap = new HashMap<>(); - if (CollectionUtils.isEmpty(versionServerMap)) { - LOGGER.debug("route management can not match any rule and route the latest version"); - return getLatestVersionList(list, targetServiceName); - } + // get tag instance map, fallbackVersionServerMap, unSetTagInstances + Map> versionServerMap = getDistributList(targetServiceName, list, invokeRule, + unSetTagInstances, fallbackVersionServerMap); - TagItem targetTag = getFiltedServerTagItem(invokeRule, targetServiceName); - if (versionServerMap.containsKey(targetTag)) { + // weight calculation to obtain the next tags instance + TagItem targetTag = getFilteredServerTagItem(invokeRule, targetServiceName); + if (targetTag != null && versionServerMap.containsKey(targetTag)) { return versionServerMap.get(targetTag); } - return getLatestVersionList(list, targetServiceName); + + if (!fallbackVersionServerMap.isEmpty()) { + // weight calculation to obtain the next fallback tags instance + TagItem fallbackTargetTag = getFallbackFilteredServerTagItem(invokeRule, targetServiceName); + if (fallbackTargetTag != null && fallbackVersionServerMap.containsKey(fallbackTargetTag)) { + return fallbackVersionServerMap.get(fallbackTargetTag); + } + } + + // has weightLess situation and unSetTagInstances has values + if (invokeRule.isWeightLess() && !unSetTagInstances.isEmpty()) { + return unSetTagInstances; + } + if (invokeRule.isEmptyProtection()) { + return list; + } + + // weight set 100 but not matched any instance, then return empty when emptyProtection close + return Collections.emptyList(); } @Override - public void init(Function getIns, - Function getVersion, - Function getServerName, - Function> getProperties) { - this.getIns = getIns; + public void init(Function getVersion, + Function getServerName, + Function> getProperties) { this.getVersion = getVersion; this.getServerName = getServerName; this.getProperties = getProperties; } - public TagItem getFiltedServerTagItem(PolicyRuleItem rule, String targetServiceName) { + public TagItem getFilteredServerTagItem(PolicyRuleItem rule, String targetServiceName) { return routerRuleCache.getServiceInfoCacheMap().get(targetServiceName) .getNextInvokeVersion(rule); } + public TagItem getFallbackFilteredServerTagItem(PolicyRuleItem rule, String targetServiceName) { + return routerRuleCache.getServiceInfoCacheMap().get(targetServiceName) + .getFallbackNextInvokeVersion(rule); + } + /** - * 1.filter targetService + * 1.filter set route rules targetService, build fallback targetService map and unSetTagInstances list. * 2.establish map is a more complicate way than direct traversal, because of multiple matches. * * the method getProperties() contains other field that we don't need. */ - private Map> getDistributList(String serviceName, - List list, - PolicyRuleItem invokeRule) { - String latestV = routerRuleCache.getServiceInfoCacheMap().get(serviceName).getLatestVersionTag() - .getVersion(); - Map> versionServerMap = new HashMap<>(); - for (T server : list) { + private Map> getDistributList(String serviceName, List list, + PolicyRuleItem invokeRule, List unSetTagInstances, Map> fallbackVersionMap) { + Map> versionServerMap = new HashMap<>(); + for (INSTANCE instance : list) { //get server - E ms = getIns.apply(server); - if (getServerName.apply(ms).equals(serviceName)) { - //most matching - TagItem tagItem = new TagItem(getVersion.apply(ms), getProperties.apply(ms)); - TagItem targetTag = null; - int maxMatch = 0; - for (RouteItem entry : invokeRule.getRoute()) { - int nowMatch = entry.getTagitem().matchNum(tagItem); - if (nowMatch > maxMatch) { - maxMatch = nowMatch; - targetTag = entry.getTagitem(); - } - } - if (invokeRule.isWeightLess() && getVersion.apply(ms).equals(latestV)) { - TagItem latestVTag = invokeRule.getRoute().get(invokeRule.getRoute().size() - 1) - .getTagitem(); - if (!versionServerMap.containsKey(latestVTag)) { - versionServerMap.put(latestVTag, new ArrayList<>()); - } - versionServerMap.get(latestVTag).add(server); - } + if (getServerName.apply(instance).equals(serviceName)) { + TagItem tagItem = new TagItem(getVersion.apply(instance), getProperties.apply(instance)); + // route most matching TagItem + TagItem targetTag = buildTargetTag(invokeRule.getRoute(), tagItem); if (targetTag != null) { if (!versionServerMap.containsKey(targetTag)) { versionServerMap.put(targetTag, new ArrayList<>()); } - versionServerMap.get(targetTag).add(server); + versionServerMap.get(targetTag).add(instance); + } else { + // not matched, placed in the unset tag instances collection + unSetTagInstances.add(instance); + } + // ensure the tags can build when set for both route and fallback at the same time + if (!CollectionUtils.isEmpty(invokeRule.getFallback())) { + // fallback most matching TagItem + TagItem targetTagFallback = buildTargetTag(invokeRule.getFallback(), tagItem); + if (!fallbackVersionMap.containsKey(targetTagFallback)) { + fallbackVersionMap.put(targetTagFallback, new ArrayList<>()); + } + fallbackVersionMap.get(targetTagFallback).add(instance); } } } return versionServerMap; } - - public void initLatestVersion(String serviceName, List list) { - String latestVersion = null; - for (T server : list) { - E ms = getIns.apply(server); - if (getServerName.apply(ms).equals(serviceName)) { - if (latestVersion == null || VersionCompareUtil - .compareVersion(latestVersion, getVersion.apply(ms)) == -1) { - latestVersion = getVersion.apply(ms); - } + private TagItem buildTargetTag(List route, TagItem tagItem) { + int maxMatch = 0; + TagItem targetTag = null; + // obtain the rule with the most parameter matches + for (RouteItem entry : route) { + if (entry.getTagitem() == null){ + continue; + } + int nowMatch = entry.getTagitem().matchNum(tagItem); + if (nowMatch > maxMatch) { + maxMatch = nowMatch; + targetTag = entry.getTagitem(); } } - TagItem tagitem = new TagItem(latestVersion); - routerRuleCache.getServiceInfoCacheMap().get(serviceName).setLatestVersionTag(tagitem); - } - - public List getLatestVersionList(List list, String targetServiceName) { - String latestV = routerRuleCache.getServiceInfoCacheMap().get(targetServiceName) - .getLatestVersionTag().getVersion(); - return list.stream().filter(server -> - getVersion.apply(getIns.apply(server)).equals(latestV) - ).collect(Collectors.toList()); + return targetTag; } } diff --git a/governance/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java b/governance/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java index fe5cf37b14f..5f5babdec34 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java +++ b/governance/src/main/java/org/apache/servicecomb/router/distribute/RouterDistributor.java @@ -19,17 +19,18 @@ import java.util.List; import java.util.Map; import java.util.function.Function; + import org.apache.servicecomb.router.model.PolicyRuleItem; /** - * @Author GuoYl123 - * @Date 2019/10/17 + * @author GuoYl123 + * @since 2019/10/17 **/ -public interface RouterDistributor { +public interface RouterDistributor { - void init(Function getIns, Function getVersion, - Function getServerName, - Function> getProperties); + void init(Function getVersion, + Function getServerName, + Function> getProperties); - List distribute(String targetServiceName, List list, PolicyRuleItem invokeRule); + List distribute(String targetServiceName, List list, PolicyRuleItem invokeRule); } diff --git a/governance/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java b/governance/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java index 61fda32c8e4..9647a853ea8 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java +++ b/governance/src/main/java/org/apache/servicecomb/router/exception/RouterIllegalParamException.java @@ -17,8 +17,8 @@ package org.apache.servicecomb.router.exception; /** - * @Author GuoYl123 - * @Date 2019/11/4 + * @author GuoYl123 + * @since 2019/11/4 **/ public class RouterIllegalParamException extends RuntimeException { diff --git a/governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java b/governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java index b043bfc8009..dd2ba78d7d3 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java +++ b/governance/src/main/java/org/apache/servicecomb/router/match/RouterRuleMatcher.java @@ -16,25 +16,25 @@ */ package org.apache.servicecomb.router.match; -import java.util.Map; - +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.marker.RequestProcessor; import org.apache.servicecomb.router.cache.RouterRuleCache; import org.apache.servicecomb.router.model.PolicyRuleItem; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -@Component public class RouterRuleMatcher { - @Autowired - private RouterRuleCache routerRuleCache; + private final RouterRuleCache routerRuleCache; + + private final RequestProcessor requestProcessor; - public RouterRuleMatcher() { + public RouterRuleMatcher(RouterRuleCache routerRuleCache, RequestProcessor requestProcessor) { + this.routerRuleCache = routerRuleCache; + this.requestProcessor = requestProcessor; } - public PolicyRuleItem match(String serviceName, Map invokeHeader) { + public PolicyRuleItem match(String serviceName, GovernanceRequestExtractor request) { for (PolicyRuleItem rule : routerRuleCache.getServiceInfoCacheMap().get(serviceName) .getAllrule()) { - if (rule.getMatch() == null || rule.getMatch().match(invokeHeader)) { + if (rule.getMatch() == null || requestProcessor.match(request, rule.getMatch())) { return rule; } } diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java b/governance/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java index 077baf730ac..7a8afeda77f 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java +++ b/governance/src/main/java/org/apache/servicecomb/router/model/HeaderRule.java @@ -21,8 +21,8 @@ import org.slf4j.LoggerFactory; /** - * @Author GuoYl123 - * @Date 2019/10/17 + * @author GuoYl123 + * @since 2019/10/17 **/ public class HeaderRule { @@ -30,11 +30,7 @@ public class HeaderRule { private String regex; - /** - * false distinct - * true Ignore - */ - private Boolean caseInsensitive = false; + private boolean caseInsensitive = true; private String exact; @@ -49,7 +45,7 @@ public boolean match(String str) { throw new RouterIllegalParamException( "route management regex and exact can not br null at same time."); } - if (!caseInsensitive) { + if (caseInsensitive) { str = str.toLowerCase(); exact = exact == null ? null : exact.toLowerCase(); regex = regex == null ? null : regex.toLowerCase(); @@ -76,11 +72,11 @@ public void setRegex(String regex) { this.regex = regex; } - public Boolean getCaseInsensitive() { + public boolean isCaseInsensitive() { return caseInsensitive; } - public void setCaseInsensitive(Boolean caseInsensitive) { + public void setCaseInsensitive(boolean caseInsensitive) { this.caseInsensitive = caseInsensitive; } diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/Matcher.java b/governance/src/main/java/org/apache/servicecomb/router/model/Matcher.java deleted file mode 100644 index 7db815dd267..00000000000 --- a/governance/src/main/java/org/apache/servicecomb/router/model/Matcher.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.router.model; - -import java.util.Map; -import org.springframework.util.CollectionUtils; - -/** - * @Author GuoYl123 - * @Date 2019/10/17 - **/ -public class Matcher { - - private String source; - - private Map sourceTags; - - private Map headers; - - private String refer; - - public Matcher() { - } - - public boolean match(Map realHeaders) { - if (CollectionUtils.isEmpty(headers)) { - return true; - } - for (Map.Entry entry : headers.entrySet()) { - if (!realHeaders.containsKey(entry.getKey()) || !entry.getValue() - .match(realHeaders.get(entry.getKey()))) { - return false; - } - } - return true; - } - - public String getSource() { - return source; - } - - public void setSource(String source) { - this.source = source; - } - - public Map getSourceTags() { - return sourceTags; - } - - public void setSourceTags(Map sourceTags) { - this.sourceTags = sourceTags; - } - - public Map getHeaders() { - return headers; - } - - public void setHeaders(Map headers) { - this.headers = headers; - } - - public String getRefer() { - return refer; - } - - public void setRefer(String refer) { - this.refer = refer; - } - - @Override - public String toString() { - return "Matcher{" + - "source='" + source + '\'' + - ", sourceTags=" + sourceTags + - ", headers=" + headers + - ", refer='" + refer + '\'' + - '}'; - } -} diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java index b13d599bbb3..0700a2618d8 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java +++ b/governance/src/main/java/org/apache/servicecomb/router/model/PolicyRuleItem.java @@ -17,14 +17,16 @@ package org.apache.servicecomb.router.model; import java.util.List; + +import org.apache.servicecomb.governance.marker.Matcher; import org.apache.servicecomb.router.exception.RouterIllegalParamException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.CollectionUtils; /** - * @Author GuoYl123 - * @Date 2019/10/17 + * @author GuoYl123 + * @since 2019/10/17 **/ public class PolicyRuleItem implements Comparable { @@ -34,29 +36,29 @@ public class PolicyRuleItem implements Comparable { private Matcher match; - // any match private List route; private Integer total; private boolean weightLess = false; + private List fallback; + + private Integer fallbackTotal; + + private boolean emptyProtection = true; + public PolicyRuleItem() { } /** * if weight is less than 100, fill with minimum version * - * @param latestVersionTag */ - public void check(TagItem latestVersionTag) { + public void check() { if (CollectionUtils.isEmpty(route)) { throw new RouterIllegalParamException("canary rule list can not be null"); } - if (route.size() == 1) { - route.get(0).setWeight(100); - return; - } int sum = 0; for (RouteItem item : route) { if (item.getWeight() == null) { @@ -67,21 +69,14 @@ public void check(TagItem latestVersionTag) { if (sum > 100) { LOGGER.warn("canary rule weight sum is more than 100"); } else if (sum < 100) { - if (latestVersionTag == null) { - LOGGER.warn("canary has some error when set default latestVersion"); - } weightLess = true; - route.add(new RouteItem(100 - sum, latestVersionTag)); + route.add(new RouteItem(100 - sum, null)); } } @Override public int compareTo(PolicyRuleItem param) { - if (param.precedence.equals(this.precedence)) { - LOGGER.warn("the same canary precedence is not recommended"); - return 0; - } - return param.precedence > this.precedence ? 1 : -1; + return Integer.compare(param.precedence, this.precedence); } public Integer getPrecedence() { @@ -124,6 +119,30 @@ public void setWeightLess(boolean weightLess) { this.weightLess = weightLess; } + public List getFallback() { + return fallback; + } + + public void setFallback(List fallback) { + this.fallback = fallback; + } + + public Integer getFallbackTotal() { + return fallbackTotal; + } + + public void setFallbackTotal(Integer fallbackTotal) { + this.fallbackTotal = fallbackTotal; + } + + public boolean isEmptyProtection() { + return emptyProtection; + } + + public void setEmptyProtection(boolean emptyProtection) { + this.emptyProtection = emptyProtection; + } + @Override public String toString() { return "PolicyRuleItem{" + @@ -132,6 +151,9 @@ public String toString() { ", route=" + route + ", total=" + total + ", weightLess=" + weightLess + + ", fallback=" + fallback + + ", fallbackTotal=" + fallbackTotal + + ", emptyProtection=" + emptyProtection + '}'; } } diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java index acabbfffebe..5f1d6e9f8df 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java +++ b/governance/src/main/java/org/apache/servicecomb/router/model/RouteItem.java @@ -19,8 +19,8 @@ import java.util.Map; /** - * @Author GuoYl123 - * @Date 2019/10/17 + * @author GuoYl123 + * @since 2019/10/17 **/ public class RouteItem implements Comparable { @@ -36,7 +36,7 @@ public class RouteItem implements Comparable { public void initTagItem() { - if (tags != null && tags.containsKey("version")) { + if (tags != null) { tagitem = new TagItem(tags); } } @@ -91,10 +91,7 @@ public void setTagitem(TagItem tagitem) { @Override public int compareTo(RouteItem param) { - if (param.weight == this.weight) { - return 0; - } - return param.weight > this.weight ? 1 : -1; + return Integer.compare(param.weight, this.weight); } @Override diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java b/governance/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java index a0a29524b2f..232f1da6338 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java +++ b/governance/src/main/java/org/apache/servicecomb/router/model/ServiceInfoCache.java @@ -19,34 +19,29 @@ import java.util.List; import java.util.stream.Collectors; +import org.springframework.util.CollectionUtils; + /** - * @Author GuoYl123 - * @Date 2019/10/17 + * @author GuoYl123 + * @since 2019/10/17 **/ public class ServiceInfoCache { - - private List allrule; + private final List allrule; /** * for default version */ private TagItem latestVersionTag; - public ServiceInfoCache() { - } - public ServiceInfoCache(List policyRuleItemList) { - this.setAllrule(policyRuleItemList); - // init tagitem - this.getAllrule().forEach(rule -> - rule.getRoute().forEach(RouteItem::initTagItem) - ); - // sort by precedence - this.sortRule(); - } + this.allrule = policyRuleItemList.stream().sorted().collect(Collectors.toList()); - public void sortRule() { - allrule = allrule.stream().sorted().collect(Collectors.toList()); + this.getAllrule().forEach(rule -> { + rule.getRoute().forEach(RouteItem::initTagItem); + if (!CollectionUtils.isEmpty(rule.getFallback())) { + rule.getFallback().forEach(RouteItem::initTagItem); + } + }); } public TagItem getNextInvokeVersion(PolicyRuleItem policyRuleItem) { @@ -54,7 +49,19 @@ public TagItem getNextInvokeVersion(PolicyRuleItem policyRuleItem) { if (policyRuleItem.getTotal() == null) { policyRuleItem.setTotal(rule.stream().mapToInt(RouteItem::getWeight).sum()); } - rule.stream().forEach(RouteItem::addCurrentWeight); + return calculateWeight(rule, policyRuleItem.getTotal()); + } + + public TagItem getFallbackNextInvokeVersion(PolicyRuleItem policyRuleItem) { + List rule = policyRuleItem.getFallback(); + if (policyRuleItem.getFallbackTotal() == null) { + policyRuleItem.setFallbackTotal(rule.stream().mapToInt(RouteItem::getWeight).sum()); + } + return calculateWeight(rule, policyRuleItem.getFallbackTotal()); + } + + private TagItem calculateWeight(List rule, int total) { + rule.forEach(RouteItem::addCurrentWeight); int maxIndex = 0, maxWeight = -1; for (int i = 0; i < rule.size(); i++) { if (maxWeight < rule.get(i).getCurrentWeight()) { @@ -62,7 +69,7 @@ public TagItem getNextInvokeVersion(PolicyRuleItem policyRuleItem) { maxWeight = rule.get(i).getCurrentWeight(); } } - rule.get(maxIndex).reduceCurrentWeight(policyRuleItem.getTotal()); + rule.get(maxIndex).reduceCurrentWeight(total); return rule.get(maxIndex).getTagitem(); } @@ -70,10 +77,6 @@ public List getAllrule() { return allrule; } - public void setAllrule(List allrule) { - this.allrule = allrule; - } - public TagItem getLatestVersionTag() { return latestVersionTag; } diff --git a/governance/src/main/java/org/apache/servicecomb/router/model/TagItem.java b/governance/src/main/java/org/apache/servicecomb/router/model/TagItem.java index 0fc610df769..a7a20fab7ea 100644 --- a/governance/src/main/java/org/apache/servicecomb/router/model/TagItem.java +++ b/governance/src/main/java/org/apache/servicecomb/router/model/TagItem.java @@ -21,8 +21,8 @@ import java.util.Objects; /** - * @Author GuoYl123 - * @Date 2019/10/17 + * @author GuoYl123 + * @since 2019/10/17 **/ public class TagItem { diff --git a/governance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/governance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..a67e4ed8d0a --- /dev/null +++ b/governance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -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.apache.servicecomb.governance.GovernanceCommonConfiguration +org.apache.servicecomb.router.RouterCommonConfiguration diff --git a/governance/src/test/java/org/apache/servicecomb/governance/AbstractFailurePredictorTest.java b/governance/src/test/java/org/apache/servicecomb/governance/AbstractFailurePredictorTest.java new file mode 100644 index 00000000000..dedeba80053 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/AbstractFailurePredictorTest.java @@ -0,0 +1,64 @@ +/* + * 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.governance; + +import java.util.Arrays; +import java.util.List; + +import org.apache.servicecomb.governance.handler.ext.AbstractFailurePredictor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class AbstractFailurePredictorTest { + class MyAbstractFailurePredictor extends AbstractFailurePredictor { + MyAbstractFailurePredictor() { + } + + @Override + protected String extractStatusCode(Object result) { + return (String) result; + } + + @Override + public boolean isFailedResult(List statusList, Throwable e) { + return super.isFailedResult(statusList, e); + } + } + + @Test + public void testCodeMatch() { + AbstractFailurePredictor predictor = new MyAbstractFailurePredictor(); + List statusList = Arrays.asList("500"); + Assertions.assertTrue(predictor.isFailedResult(statusList, "500")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "502")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "400")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "444")); + + statusList = Arrays.asList("5x0"); + Assertions.assertTrue(predictor.isFailedResult(statusList, "500")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "502")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "400")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "444")); + + statusList = Arrays.asList(null, "xx", "5x0"); + Assertions.assertTrue(predictor.isFailedResult(statusList, "500")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "502")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "400")); + Assertions.assertFalse(predictor.isFailedResult(statusList, "444")); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/BulkheadHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/BulkheadHandlerTest.java new file mode 100644 index 00000000000..59703d4ee7a --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/BulkheadHandlerTest.java @@ -0,0 +1,46 @@ +/* + * 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.governance; + +import org.apache.servicecomb.governance.handler.BulkheadHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.policy.BulkheadPolicy; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class BulkheadHandlerTest { + private BulkheadHandler bulkheadHandler; + + @Autowired + public void setInstanceIsolationHandler(BulkheadHandler scbBulkheadHandler) { + this.bulkheadHandler = scbBulkheadHandler; + } + + @Test + public void testMatchPriorityPolicy() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/bulkhead"); + BulkheadPolicy policy = bulkheadHandler.matchPolicy(request); + Assertions.assertEquals("demo-bulkhead-priority", policy.getName()); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/CustomMatchTest.java b/governance/src/test/java/org/apache/servicecomb/governance/CustomMatchTest.java new file mode 100644 index 00000000000..a0e0c2d8ab9 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/CustomMatchTest.java @@ -0,0 +1,100 @@ +/* + * 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.governance; + +import org.apache.servicecomb.governance.marker.CustomMatcher; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.Matcher; +import org.apache.servicecomb.governance.marker.RequestProcessor; +import org.apache.servicecomb.governance.mockclasses.service.MockConfigurationForCustomMatcher; +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.junit.jupiter.api.Assertions; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class, MockConfigurationForCustomMatcher.class}) +public class CustomMatchTest { + + private RequestProcessor requestProcessor; + + @Autowired + public void setRequestProcessor(RequestProcessor requestProcessor) { + this.requestProcessor = requestProcessor; + } + + private Matcher generateMatcher(String customMatcherHandler, String customMatcherParameters) { + CustomMatcher customMatcher = new CustomMatcher(); + customMatcher.setCustomMatcherHandler(customMatcherHandler); + customMatcher.setCustomMatcherParameters(customMatcherParameters); + Matcher matcher = new Matcher(); + matcher.setCustomMatcher(customMatcher); + return matcher; + } + + @Test + public void test_should_pass_when_value_class_empty() { + GovernanceRequest request = new GovernanceRequest(); + Matcher mockMatcher = generateMatcher("", ""); + Assert.assertTrue(this.requestProcessor.match(request, mockMatcher)); + mockMatcher = generateMatcher("", "bill"); + Assert.assertTrue(this.requestProcessor.match(request, mockMatcher)); + mockMatcher = generateMatcher("classWithAnnotation", ""); + Assert.assertTrue(this.requestProcessor.match(request, mockMatcher)); + } + + @Test + public void test_should_pass_when_value_class_match() { + GovernanceRequest request = new GovernanceRequest(); + Matcher mockMatcher = generateMatcher("classWithAnnotation", "bill"); + Assert.assertTrue(this.requestProcessor.match(request, mockMatcher)); + } + + @Test + public void test_should_throw_exception_when_class_not_found() { + GovernanceRequest request = new GovernanceRequest(); + try { + Matcher mockMatcher = generateMatcher("classWithAnnotationNotFound", "bill"); + this.requestProcessor.match(request, mockMatcher); + Assertions.fail("an exception is expected!"); + } catch (Exception e) { + Assert.assertTrue(e.getCause() instanceof ClassNotFoundException); + } + } + + @Test + public void test_should_pass_when_multiple_value() { + GovernanceRequest request = new GovernanceRequest(); + Matcher mockMatcher = generateMatcher("classWithAnnotation", "bill,bill2"); + Assert.assertTrue(this.requestProcessor.match(request, mockMatcher)); + } + + @Test + public void test_should_throw_exception_when_not_implements_interface() { + GovernanceRequest request = new GovernanceRequest(); + try { + Matcher mockMatcher = generateMatcher("classNotImplements", "bill,bill2"); + this.requestProcessor.match(request, mockMatcher); + Assertions.fail("an exception is expected!"); + } catch (Exception e) { + Assert.assertTrue(e.getMessage().contains(RequestProcessor.errorMessageForNotImplements)); + } + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/FaultInjectionTest.java b/governance/src/test/java/org/apache/servicecomb/governance/FaultInjectionTest.java new file mode 100644 index 00000000000..7733b8ed44f --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/FaultInjectionTest.java @@ -0,0 +1,205 @@ +/* + * 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.governance; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.servicecomb.governance.handler.FaultInjectionHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.processor.injection.Fault; +import org.apache.servicecomb.governance.processor.injection.FaultInjectionDecorators; +import org.apache.servicecomb.governance.processor.injection.FaultInjectionDecorators.FaultInjectionDecorateCheckedSupplier; +import org.apache.servicecomb.governance.processor.injection.FaultInjectionException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class FaultInjectionTest { + private FaultInjectionHandler faultInjectionHandler; + + private FaultInjectionHandler faultInjectionHandler2; + + @Autowired + public void setFaultInjectionHandler(FaultInjectionHandler scbFaultInjectionHandler, + @Qualifier("faultInjectionHandler2") FaultInjectionHandler faultInjectionHandler2) { + this.faultInjectionHandler = scbFaultInjectionHandler; + this.faultInjectionHandler2 = faultInjectionHandler2; + } + + public FaultInjectionTest() { + } + + @Test + public void test_delay_fault_injection_service_name_work() throws Throwable { + FaultInjectionDecorateCheckedSupplier ds = + FaultInjectionDecorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/faultInjectDelay"); + request.setServiceName("srcService"); + + Fault fault = faultInjectionHandler.getActuator(request); + ds.withFaultInjection(fault); + + Assertions.assertEquals("test", ds.get()); + + // flow control + CountDownLatch cd = new CountDownLatch(10); + AtomicBoolean expected = new AtomicBoolean(false); + AtomicBoolean notExpected = new AtomicBoolean(false); + for (int i = 0; i < 10; i++) { + new Thread(() -> { + try { + long startTime = System.currentTimeMillis(); + Object result = ds.get(); + if (!"test".equals(result)) { + notExpected.set(true); + } + // delayTime is 2S + if (System.currentTimeMillis() - startTime > 1000) { + expected.set(true); + } + } catch (Throwable e) { + notExpected.set(true); + } + cd.countDown(); + }).start(); + } + //timeout should be bigger than delayTime + cd.await(10, TimeUnit.SECONDS); + Assertions.assertFalse(notExpected.get()); + Assertions.assertTrue(expected.get()); + } + + @Test + public void test_abort_fault_injection_service_name_work() throws Throwable { + FaultInjectionDecorateCheckedSupplier ds = + FaultInjectionDecorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/faultInjectAbort"); + request.setServiceName("srcService"); + + Fault fault = faultInjectionHandler.getActuator(request); + ds.withFaultInjection(fault); + + Assertions.assertEquals("test", ds.get()); + + // flow control + CountDownLatch cd = new CountDownLatch(10); + AtomicBoolean expected = new AtomicBoolean(false); + AtomicBoolean notExpected = new AtomicBoolean(false); + for (int i = 0; i < 10; i++) { + new Thread(() -> { + try { + Object result = ds.get(); + if (!"test".equals(result)) { + notExpected.set(true); + } + } catch (FaultInjectionException e) { + expected.set(true); + } catch (Throwable e) { + notExpected.set(true); + } + cd.countDown(); + }).start(); + } + cd.await(1, TimeUnit.SECONDS); + Assertions.assertFalse(notExpected.get()); + Assertions.assertTrue(expected.get()); + } + + @Test + public void test_fallback_returnNull_work() throws Throwable { + FaultInjectionDecorateCheckedSupplier ds = + FaultInjectionDecorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/returnNull"); + request.setServiceName("returnNull"); + + Fault fault = faultInjectionHandler.getActuator(request); + ds.withFaultInjection(fault); + Assertions.assertEquals(null, ds.get()); + } + + @Test + public void test_fallback_ThrowException_work() throws Throwable { + FaultInjectionDecorateCheckedSupplier ds = + FaultInjectionDecorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/throwException"); + request.setServiceName("ThrowException"); + + Fault fault = faultInjectionHandler.getActuator(request); + ds.withFaultInjection(fault); + boolean expected = false; + try { + ds.get(); + } catch (FaultInjectionException e) { + if (e.getFaultResponse().getErrorCode() == 500) { + expected = true; + } + } + Assertions.assertEquals(true, expected); + } + + @Test + public void test_fallback_forceClosed_work() throws Throwable { + FaultInjectionDecorateCheckedSupplier ds = + FaultInjectionDecorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/forceClosed"); + request.setServiceName("forceClosed"); + + Fault fault = faultInjectionHandler.getActuator(request); + ds.withFaultInjection(fault); + Assertions.assertEquals("test", ds.get()); + } + + @Test + public void test_fallback_ThrowException_work_handler2() throws Throwable { + FaultInjectionDecorateCheckedSupplier ds = + FaultInjectionDecorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/throwException"); + request.setServiceName("ThrowException"); + + Fault fault = faultInjectionHandler2.getActuator(request); + ds.withFaultInjection(fault); + boolean expected = false; + try { + ds.get(); + } catch (FaultInjectionException e) { + if (e.getFaultResponse().getErrorCode() == 500) { + expected = true; + } + } + Assertions.assertEquals(true, expected); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java b/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java index c31c4ab25be..a4b751fd95d 100644 --- a/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java +++ b/governance/src/test/java/org/apache/servicecomb/governance/FlowControlTest.java @@ -23,71 +23,104 @@ import org.apache.servicecomb.governance.handler.RateLimitingHandler; import org.apache.servicecomb.governance.marker.GovernanceRequest; -import org.apache.servicecomb.governance.properties.RateLimitProperties; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import io.github.resilience4j.decorators.Decorators; import io.github.resilience4j.decorators.Decorators.DecorateCheckedSupplier; import io.github.resilience4j.ratelimiter.RateLimiter; import io.github.resilience4j.ratelimiter.RequestNotPermitted; -@RunWith(SpringRunner.class) -@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class) +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) public class FlowControlTest { - @Autowired private RateLimitingHandler rateLimitingHandler; @Autowired - private RateLimitProperties rateLimitProperties; + public void setRateLimitingHandler(RateLimitingHandler rateLimitingHandler) { + this.rateLimitingHandler = rateLimitingHandler; + } - @Autowired - private MatchersManager matchersManager; + public FlowControlTest() { + } @Test public void test_rate_limiting_work() throws Throwable { - DecorateCheckedSupplier ds = Decorators.ofCheckedSupplier(() -> { - return "test"; - }); + DecorateCheckedSupplier ds = Decorators.ofCheckedSupplier(() -> "test"); GovernanceRequest request = new GovernanceRequest(); - request.setUri("/hello"); + request.setApiPath("/hello"); RateLimiter rateLimiter = rateLimitingHandler.getActuator(request); ds.withRateLimiter(rateLimiter); - Assert.assertEquals("test", ds.get()); + Assertions.assertEquals("test", ds.get()); // flow control CountDownLatch cd = new CountDownLatch(10); AtomicBoolean expected = new AtomicBoolean(false); AtomicBoolean notExpected = new AtomicBoolean(false); for (int i = 0; i < 10; i++) { - new Thread() { - public void run() { - try { - Object result = ds.get(); - if (!"test".equals(result)) { - notExpected.set(true); - } - } catch (Throwable e) { - if (e instanceof RequestNotPermitted) { - expected.set(true); - } else { - notExpected.set(true); - } + new Thread(() -> { + try { + Object result = ds.get(); + if (!"test".equals(result)) { + notExpected.set(true); + } + } catch (Throwable e) { + if (e instanceof RequestNotPermitted) { + expected.set(true); + } else { + notExpected.set(true); + } + } + cd.countDown(); + }).start(); + } + cd.await(1, TimeUnit.SECONDS); + Assertions.assertTrue(expected.get()); + Assertions.assertFalse(notExpected.get()); + } + + @Test + public void test_rate_limiting_service_name_work() throws Throwable { + DecorateCheckedSupplier ds = Decorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/helloServiceName"); + request.setServiceName("srcService"); + + RateLimiter rateLimiter = rateLimitingHandler.getActuator(request); + ds.withRateLimiter(rateLimiter); + + Assertions.assertEquals("test", ds.get()); + + // flow control + CountDownLatch cd = new CountDownLatch(10); + AtomicBoolean expected = new AtomicBoolean(false); + AtomicBoolean notExpected = new AtomicBoolean(false); + for (int i = 0; i < 10; i++) { + new Thread(() -> { + try { + Object result = ds.get(); + if (!"test".equals(result)) { + notExpected.set(true); + } + } catch (Throwable e) { + if (e instanceof RequestNotPermitted) { + expected.set(true); + } else { + notExpected.set(true); } - cd.countDown(); } - }.start(); + cd.countDown(); + }).start(); } cd.await(1, TimeUnit.SECONDS); - Assert.assertTrue(expected.get()); - Assert.assertFalse(notExpected.get()); + Assertions.assertTrue(expected.get()); + Assertions.assertFalse(notExpected.get()); } } diff --git a/governance/src/test/java/org/apache/servicecomb/governance/GovernanceCacheHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/GovernanceCacheHandlerTest.java new file mode 100644 index 00000000000..ac26c3f3bdd --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/GovernanceCacheHandlerTest.java @@ -0,0 +1,54 @@ +/* + * 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.governance; + + +import org.apache.servicecomb.governance.handler.GovernanceCacheHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.policy.GovernanceCachePolicy; +import org.apache.servicecomb.governance.service.GovernanceCache; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class GovernanceCacheHandlerTest { + private GovernanceCacheHandler governanceCacheHandler; + + @Autowired + public void setInstanceIsolationHandler(@Autowired GovernanceCacheHandler governanceCacheHandler) { + this.governanceCacheHandler = governanceCacheHandler; + } + + @Test + public void testMatchPriorityPolicy() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/governanceCache"); + GovernanceCachePolicy policy = governanceCacheHandler.matchPolicy(request); + Assertions.assertEquals("demo-governanceCache", policy.getName()); + GovernanceCache governanceCache = governanceCacheHandler.getActuator(request); + governanceCache.putValueIntoCache("governance", "Cache"); + Object cache = governanceCache.getValueFromCache("governance"); + Assertions.assertEquals("Cache", cache); + governanceCache.putValueIntoCache("response", null); + Object response = governanceCache.getValueFromCache("response"); + Assertions.assertNull(response); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java b/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java index 3aa25b635a8..5b71a2ac3b8 100644 --- a/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java +++ b/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java @@ -31,57 +31,127 @@ import org.apache.servicecomb.governance.policy.AbstractPolicy; import org.apache.servicecomb.governance.policy.BulkheadPolicy; import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy; +import org.apache.servicecomb.governance.policy.FaultInjectionPolicy; +import org.apache.servicecomb.governance.policy.GovernanceCachePolicy; import org.apache.servicecomb.governance.policy.RateLimitingPolicy; import org.apache.servicecomb.governance.policy.RetryPolicy; +import org.apache.servicecomb.governance.policy.TimeLimiterPolicy; +import org.apache.servicecomb.governance.processor.injection.FaultInjectionConst; import org.apache.servicecomb.governance.properties.BulkheadProperties; import org.apache.servicecomb.governance.properties.CircuitBreakerProperties; +import org.apache.servicecomb.governance.properties.FaultInjectionProperties; +import org.apache.servicecomb.governance.properties.GovernanceCacheProperties; import org.apache.servicecomb.governance.properties.GovernanceProperties; +import org.apache.servicecomb.governance.properties.InstanceIsolationProperties; import org.apache.servicecomb.governance.properties.MatchProperties; import org.apache.servicecomb.governance.properties.RateLimitProperties; import org.apache.servicecomb.governance.properties.RetryProperties; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.apache.servicecomb.governance.properties.TimeLimiterProperties; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.Environment; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) -@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class) +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) public class GovernancePropertiesTest { + private List> propertiesList; + + private MatchProperties matchProperties; + + private BulkheadProperties bulkheadProperties; + + private CircuitBreakerProperties circuitBreakerProperties; + + private TimeLimiterProperties timeLimiterProperties; + + private GovernanceCacheProperties governanceCacheProperties; + + private InstanceIsolationProperties instanceIsolationProperties; + + private RateLimitProperties rateLimitProperties; + + private RetryProperties retryProperties; + + private FaultInjectionProperties faultInjectionProperties; + + private Environment environment; @Autowired - private List> propertiesList; + public void setPropertiesList(List> propertiesList) { + this.propertiesList = propertiesList; + } @Autowired - private MatchProperties matchProperties; + public void setMatchProperties(MatchProperties scbMatchProperties) { + this.matchProperties = scbMatchProperties; + } @Autowired - private BulkheadProperties bulkheadProperties; + public void setBulkheadProperties(BulkheadProperties scbBulkheadProperties) { + this.bulkheadProperties = scbBulkheadProperties; + } @Autowired - private CircuitBreakerProperties circuitBreakerProperties; + public void setCircuitBreakerProperties(CircuitBreakerProperties scbCircuitBreakerProperties) { + this.circuitBreakerProperties = scbCircuitBreakerProperties; + } @Autowired - private RateLimitProperties rateLimitProperties; + public void setTimeLimiterProperties(TimeLimiterProperties scbTimeLimiterProperties) { + this.timeLimiterProperties = scbTimeLimiterProperties; + } @Autowired - private RetryProperties retryProperties; + public void setGovernanceCacheProperties(GovernanceCacheProperties scbGovernanceCacheProperties) { + this.governanceCacheProperties = scbGovernanceCacheProperties; + } @Autowired - private Environment environment; + public void setRateLimitProperties(RateLimitProperties scbRateLimitProperties) { + this.rateLimitProperties = scbRateLimitProperties; + } + + @Autowired + public void setInstanceIsolationProperties(InstanceIsolationProperties scbInstanceIsolationProperties) { + this.instanceIsolationProperties = scbInstanceIsolationProperties; + } + + @Autowired + public void setRetryProperties(RetryProperties scbRetryProperties) { + this.retryProperties = scbRetryProperties; + } + + @Autowired + public void setFaultInjectionProperties( + FaultInjectionProperties scbFaultInjectionProperties) { + this.faultInjectionProperties = scbFaultInjectionProperties; + } + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Autowired + public void setDynamicValues(Map dynamicValues) { + this.dynamicValues = dynamicValues; + } + + public GovernancePropertiesTest() { + } private Map dynamicValues = new HashMap<>(); private static final float DELTA = 0.0000001f; - @Before + @BeforeEach public void setUp() { ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment; @@ -103,7 +173,7 @@ public String[] getPropertyNames() { }); } - @After + @AfterEach public void tearDown() { Set keys = dynamicValues.keySet(); keys.forEach(k -> dynamicValues.put(k, null)); @@ -112,41 +182,40 @@ public void tearDown() { @Test public void test_all_bean_is_loaded() { - Assert.assertEquals(4, propertiesList.size()); + Assertions.assertEquals(16, propertiesList.size()); } @Test public void test_match_properties_successfully_loaded() { Map markers = matchProperties.getParsedEntity(); - Assert.assertEquals(4, markers.size()); TrafficMarker demoRateLimiting = markers.get("demo-rateLimiting"); List matchers = demoRateLimiting.getMatches(); - Assert.assertEquals(1, matchers.size()); + Assertions.assertEquals(1, matchers.size()); Matcher matcher = matchers.get(0); - Assert.assertEquals("/hello", matcher.getApiPath().get("exact")); + Assertions.assertEquals("/hello", matcher.getApiPath().get("exact")); TrafficMarker demoBulkhead = markers.get("demo-bulkhead"); matchers = demoBulkhead.getMatches(); - Assert.assertEquals(2, matchers.size()); + Assertions.assertEquals(2, matchers.size()); matcher = matchers.get(0); - Assert.assertEquals("/bulkhead", matcher.getApiPath().get("exact")); - Assert.assertEquals("matchPath", matcher.getName()); + Assertions.assertEquals("/bulkhead", matcher.getApiPath().get("exact")); + Assertions.assertEquals("matchPath", matcher.getName()); } @Test public void test_match_properties_delete() { Map markers = matchProperties.getParsedEntity(); - Assert.assertEquals(4, markers.size()); + Assertions.assertEquals(null, markers.get("test")); dynamicValues.put("servicecomb.matchGroup.test", "matches:\n" + " - apiPath:\n" + " exact: \"/hello2\"\n" + " name: match0"); GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); markers = matchProperties.getParsedEntity(); - Assert.assertEquals(5, markers.size()); + Assertions.assertEquals(1, markers.get("test").getMatches().size()); tearDown(); markers = matchProperties.getParsedEntity(); - Assert.assertEquals(4, markers.size()); + Assertions.assertEquals(null, markers.get("test")); } @Test @@ -163,18 +232,17 @@ public void test_match_properties_changed() { GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); Map markers = matchProperties.getParsedEntity(); - Assert.assertEquals(5, markers.size()); TrafficMarker demoRateLimiting = markers.get("demo-rateLimiting"); List matchers = demoRateLimiting.getMatches(); - Assert.assertEquals(1, matchers.size()); + Assertions.assertEquals(1, matchers.size()); Matcher matcher = matchers.get(0); - Assert.assertEquals("/hello2", matcher.getApiPath().get("exact")); + Assertions.assertEquals("/hello2", matcher.getApiPath().get("exact")); demoRateLimiting = markers.get("demo-rateLimiting2"); matchers = demoRateLimiting.getMatches(); - Assert.assertEquals(1, matchers.size()); + Assertions.assertEquals(1, matchers.size()); matcher = matchers.get(0); - Assert.assertEquals("/hello2", matcher.getApiPath().get("exact")); + Assertions.assertEquals("/hello2", matcher.getApiPath().get("exact")); } @Test @@ -189,17 +257,17 @@ public void test_bulkhead_properties_changed() { GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); Map policies = bulkheadProperties.getParsedEntity(); - Assert.assertEquals(2, policies.size()); + Assertions.assertEquals(3, policies.size()); BulkheadPolicy policy = policies.get("demo-bulkhead"); - Assert.assertEquals(2, policy.getMaxConcurrentCalls()); - Assert.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals(2, policy.getMaxConcurrentCalls()); + Assertions.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); policies = bulkheadProperties.getParsedEntity(); - Assert.assertEquals(2, policies.size()); + Assertions.assertEquals(3, policies.size()); policy = policies.get("bulkhead1"); - Assert.assertEquals(3, policy.getMaxConcurrentCalls()); - Assert.assertEquals(3000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); - Assert.assertEquals("bulkhead1", policy.getName()); + Assertions.assertEquals(3, policy.getMaxConcurrentCalls()); + Assertions.assertEquals(3000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals("bulkhead1", policy.getName()); } @Test @@ -217,38 +285,89 @@ public void test_bulkhead_properties_bound() { GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); Map policies = bulkheadProperties.getParsedEntity(); - Assert.assertEquals(4, policies.size()); + Assertions.assertEquals(5, policies.size()); BulkheadPolicy policy = policies.get("test-bulkhead1"); - Assert.assertEquals(0, policy.getMaxConcurrentCalls()); - Assert.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals(0, policy.getMaxConcurrentCalls()); + Assertions.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); policy = policies.get("test-bulkhead2"); - Assert.assertEquals(1000, policy.getMaxConcurrentCalls()); - Assert.assertEquals(0, Duration.parse(policy.getMaxWaitDuration()).toMillis()); - Assert.assertEquals("test-bulkhead2", policy.getName()); + Assertions.assertEquals(1000, policy.getMaxConcurrentCalls()); + Assertions.assertEquals(0, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals("test-bulkhead2", policy.getName()); policy = policies.get("test-bulkhead3"); - Assert.assertEquals(0, policy.getMaxConcurrentCalls()); - Assert.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); - Assert.assertEquals("test-bulkhead3", policy.getName()); + Assertions.assertEquals(0, policy.getMaxConcurrentCalls()); + Assertions.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals("test-bulkhead3", policy.getName()); } @Test public void test_bulkhead_properties_successfully_loaded() { Map policies = bulkheadProperties.getParsedEntity(); - Assert.assertEquals(1, policies.size()); + Assertions.assertEquals(2, policies.size()); BulkheadPolicy policy = policies.get("demo-bulkhead"); - Assert.assertEquals(1, policy.getMaxConcurrentCalls()); - Assert.assertEquals(3000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals(1, policy.getMaxConcurrentCalls()); + Assertions.assertEquals(3000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + } + + @Test + public void test_timelimiter_properties_successfully_loaded() { + Map policies = timeLimiterProperties.getParsedEntity(); + Assertions.assertEquals(2, policies.size()); + TimeLimiterPolicy timeLimiterPolicy = policies.get("demo-timeLimiter-other"); + Assertions.assertEquals(2000, Duration.parse(timeLimiterPolicy.getTimeoutDuration()).toMillis()); + Assertions.assertEquals(false, timeLimiterPolicy.isCancelRunningFuture()); + } + + @Test + public void test_timelimiter_properties_bound() { + dynamicValues.put("servicecomb.timeLimiter.name1", "rules:\n" + + "timeoutDuration: 5000\n" + + "cancelRunningFuture: false"); + + GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); + + Map policies = timeLimiterProperties.getParsedEntity(); + Assertions.assertEquals(3, policies.size()); + TimeLimiterPolicy policy = policies.get("name1"); + Assertions.assertEquals(false, policy.isCancelRunningFuture()); + Assertions.assertEquals(5000, Duration.parse(policy.getTimeoutDuration()).toMillis()); + } + + @Test + public void test_governanceCache_properties_successfully_loaded() { + Map policies = governanceCacheProperties.getParsedEntity(); + Assertions.assertEquals(2, policies.size()); + GovernanceCachePolicy governanceCachePolicy = policies.get("demo-governanceCache-other"); + Assertions.assertEquals(15, governanceCachePolicy.getConcurrencyLevel()); + Assertions.assertEquals(50000, governanceCachePolicy.getMaximumSize()); + Assertions.assertEquals(666666, Duration.parse(governanceCachePolicy.getTtl()).toMillis()); + } + + @Test + public void test_governanceCache_properties_bound() { + dynamicValues.put("servicecomb.cache.name1", "rules:\n" + + "ttl: 3000000\n" + + "maximumSize: 2000\n" + + "concurrencyLevel: 6"); + + GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); + + Map policies = governanceCacheProperties.getParsedEntity(); + Assertions.assertEquals(3, policies.size()); + GovernanceCachePolicy policy = policies.get("name1"); + Assertions.assertEquals(3000000, Duration.parse(policy.getTtl()).toMillis()); + Assertions.assertEquals(2000, policy.getMaximumSize()); + Assertions.assertEquals(6, policy.getConcurrencyLevel()); } @Test public void test_circuit_breaker_properties_successfully_loaded() { Map policies = circuitBreakerProperties.getParsedEntity(); - Assert.assertEquals(1, policies.size()); + Assertions.assertEquals(1, policies.size()); CircuitBreakerPolicy policy = policies.get("demo-circuitBreaker"); - Assert.assertEquals(2, policy.getMinimumNumberOfCalls()); - Assert.assertEquals("2", policy.getSlidingWindowSize()); + Assertions.assertEquals(2, policy.getMinimumNumberOfCalls()); + Assertions.assertEquals("2", policy.getSlidingWindowSize()); } @Test @@ -266,17 +385,17 @@ public void test_circuit_breaker_properties_Of_windows_size() { GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); Map policies = circuitBreakerProperties.getParsedEntity(); - Assert.assertEquals(4, policies.size()); + Assertions.assertEquals(4, policies.size()); CircuitBreakerPolicy policy = policies.get("name1"); - Assert.assertEquals("count", policy.getSlidingWindowType()); - Assert.assertEquals("2", policy.getSlidingWindowSize()); + Assertions.assertEquals("count", policy.getSlidingWindowType()); + Assertions.assertEquals("2", policy.getSlidingWindowSize()); policy = policies.get("name2"); - Assert.assertEquals("time", policy.getSlidingWindowType()); - Assert.assertEquals("2", policy.getSlidingWindowSize()); + Assertions.assertEquals("time", policy.getSlidingWindowType()); + Assertions.assertEquals("2", policy.getSlidingWindowSize()); policy = policies.get("name3"); - Assert.assertEquals("60", policy.getSlidingWindowSize()); + Assertions.assertEquals("60", policy.getSlidingWindowSize()); } @Test @@ -292,28 +411,28 @@ public void test_circuit_breaker_properties_Of_type() { Map policies = circuitBreakerProperties.getParsedEntity(); CircuitBreakerPolicy policy = policies.get("type1"); - Assert.assertEquals(20.0f, policy.getFailureRateThreshold(), DELTA); - Assert.assertEquals(100.0f, policy.getSlowCallRateThreshold(), DELTA); + Assertions.assertEquals(20.0f, policy.getFailureRateThreshold(), DELTA); + Assertions.assertEquals(100.0f, policy.getSlowCallRateThreshold(), DELTA); policy = policies.get("type2"); - Assert.assertEquals(20.33f, policy.getFailureRateThreshold(), DELTA); - Assert.assertEquals(0.01f, policy.getSlowCallRateThreshold(), DELTA); + Assertions.assertEquals(20.33f, policy.getFailureRateThreshold(), DELTA); + Assertions.assertEquals(0.01f, policy.getSlowCallRateThreshold(), DELTA); } @Test public void test_rate_limit_properties_successfully_loaded() { Map policies = rateLimitProperties.getParsedEntity(); - Assert.assertEquals(1, policies.size()); + Assertions.assertEquals(2, policies.size()); RateLimitingPolicy policy = policies.get("demo-rateLimiting"); - Assert.assertEquals(1, policy.getRate()); + Assertions.assertEquals(1, policy.getRate()); } @Test public void test_retry_properties_successfully_loaded() { Map policies = retryProperties.getParsedEntity(); - Assert.assertEquals(1, policies.size()); + Assertions.assertEquals(1, policies.size()); RetryPolicy policy = policies.get("demo-retry"); - Assert.assertEquals(3, policy.getMaxAttempts()); + Assertions.assertEquals(3, policy.getMaxAttempts()); } @@ -329,13 +448,37 @@ public void test_properties_changed_to_duration() { GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet()))); Map policies = bulkheadProperties.getParsedEntity(); - Assert.assertEquals(3, policies.size()); + Assertions.assertEquals(4, policies.size()); BulkheadPolicy policy = policies.get("test1"); - Assert.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals(2000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); policies = bulkheadProperties.getParsedEntity(); - Assert.assertEquals(3, policies.size()); + Assertions.assertEquals(4, policies.size()); policy = policies.get("test2"); - Assert.assertEquals(60000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + Assertions.assertEquals(60000, Duration.parse(policy.getMaxWaitDuration()).toMillis()); + } + + @Test + public void test_instance_isolation_properties_successfully_loaded() { + Map policies = instanceIsolationProperties.getParsedEntity(); + Assertions.assertEquals(1, policies.size()); + CircuitBreakerPolicy policy = policies.get("demo-allOperation"); + Assertions.assertEquals(2, policy.getMinimumNumberOfCalls()); + Assertions.assertEquals("2", policy.getSlidingWindowSize()); + } + + @Test + public void test_fault_injection_properties_successfully_loaded() { + Map policies = faultInjectionProperties.getParsedEntity(); + Assertions.assertEquals(5, policies.size()); + FaultInjectionPolicy policy = policies.get("demo-faultInjectDelay"); + Assertions.assertEquals(FaultInjectionConst.TYPE_DELAY, policy.getType()); + Assertions.assertEquals(2000, policy.getDelayTimeToMillis()); + Assertions.assertEquals(100, policy.getPercentage()); + + policy = policies.get("demo-faultInjectAbort"); + Assertions.assertEquals(FaultInjectionConst.TYPE_ABORT, policy.getType()); + Assertions.assertEquals(50, policy.getPercentage()); + Assertions.assertEquals(500, policy.getErrorCode()); } } diff --git a/governance/src/test/java/org/apache/servicecomb/governance/IdentifierRateLimitingHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/IdentifierRateLimitingHandlerTest.java new file mode 100644 index 00000000000..1aed8e4a302 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/IdentifierRateLimitingHandlerTest.java @@ -0,0 +1,143 @@ +/* + * 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.governance; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.servicecomb.governance.handler.IdentifierRateLimitingHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCheckedSupplier; +import io.github.resilience4j.ratelimiter.RateLimiter; +import io.github.resilience4j.ratelimiter.RequestNotPermitted; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class IdentifierRateLimitingHandlerTest { + private IdentifierRateLimitingHandler rateLimitingHandler; + + @Autowired + public void setRateLimitingHandler(IdentifierRateLimitingHandler rateLimitingHandler) { + this.rateLimitingHandler = rateLimitingHandler; + } + + public IdentifierRateLimitingHandlerTest() { + } + + @Test + public void test_rate_limiting_work() throws Throwable { + DecorateCheckedSupplier ds = Decorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/hello"); + Map headers = new HashMap<>(); + headers.put("test", "1234"); + request.setHeaders(headers); + + RateLimiter rateLimiter = rateLimitingHandler.getActuator(request); + ds.withRateLimiter(rateLimiter); + + Assertions.assertEquals("test", ds.get()); + + // flow control + CountDownLatch cd = new CountDownLatch(10); + AtomicBoolean expected = new AtomicBoolean(false); + AtomicBoolean notExpected = new AtomicBoolean(false); + for (int i = 0; i < 10; i++) { + new Thread(() -> { + try { + Object result = ds.get(); + if (!"test".equals(result)) { + notExpected.set(true); + } + } catch (Throwable e) { + if (e instanceof RequestNotPermitted) { + expected.set(true); + } else { + notExpected.set(true); + } + } + cd.countDown(); + }).start(); + } + cd.await(1, TimeUnit.SECONDS); + Assertions.assertTrue(expected.get()); + Assertions.assertFalse(notExpected.get()); + } + + @Test + public void test_rate_limiting_service_name_work() throws Throwable { + DecorateCheckedSupplier ds = Decorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/helloServiceName"); + request.setServiceName("srcService"); + Map headers = new HashMap<>(); + headers.put("test", "1234"); + request.setHeaders(headers); + + RateLimiter rateLimiter = rateLimitingHandler.getActuator(request); + ds.withRateLimiter(rateLimiter); + + Assertions.assertEquals("test", ds.get()); + + headers = new HashMap<>(); + headers.put("test", "12345"); + request.setHeaders(headers); + + RateLimiter rateLimiter2 = rateLimitingHandler.getActuator(request); + DecorateCheckedSupplier ds2 = Decorators.ofCheckedSupplier(() -> "test2"); + ds2.withRateLimiter(rateLimiter2); + Assertions.assertEquals("test2", ds2.get()); + + // flow control + CountDownLatch cd = new CountDownLatch(10); + AtomicBoolean expected = new AtomicBoolean(false); + AtomicBoolean notExpected = new AtomicBoolean(false); + for (int i = 0; i < 10; i++) { + new Thread(() -> { + try { + Object result = ds.get(); + if (!"test".equals(result)) { + notExpected.set(true); + } + } catch (Throwable e) { + if (e instanceof RequestNotPermitted) { + expected.set(true); + } else { + notExpected.set(true); + } + } + cd.countDown(); + }).start(); + } + cd.await(1, TimeUnit.SECONDS); + Assertions.assertTrue(expected.get()); + Assertions.assertFalse(notExpected.get()); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/InstanceBulkheadHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/InstanceBulkheadHandlerTest.java new file mode 100644 index 00000000000..de5213ef520 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/InstanceBulkheadHandlerTest.java @@ -0,0 +1,119 @@ +/* + * 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.governance; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.servicecomb.governance.handler.InstanceBulkheadHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.github.resilience4j.bulkhead.Bulkhead; +import io.github.resilience4j.bulkhead.BulkheadFullException; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCheckedSupplier; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class InstanceBulkheadHandlerTest { + private InstanceBulkheadHandler instanceBulkheadHandler; + + @Autowired + public void setInstanceBulkheadHandler(InstanceBulkheadHandler instanceBulkheadHandler) { + this.instanceBulkheadHandler = instanceBulkheadHandler; + } + + @Test + public void test_instance_bulkhead_work() throws Throwable { + + // instance1 + DecorateCheckedSupplier dsInstance1 = Decorators.ofCheckedSupplier(() -> "wake"); + + GovernanceRequest requestInstance1 = new GovernanceRequest(); + requestInstance1.setInstanceId("instance01"); + requestInstance1.setServiceName("service01"); + requestInstance1.setApiPath("/test"); + + Bulkhead bulkheadInstance1 = instanceBulkheadHandler.getActuator(requestInstance1); + dsInstance1.withBulkhead(bulkheadInstance1); + + // instance2 + DecorateCheckedSupplier dsInstance2 = Decorators.ofCheckedSupplier(() -> { + Thread.sleep(1000); + return "sleep"; + }); + + GovernanceRequest requestInstance2 = new GovernanceRequest(); + requestInstance2.setInstanceId("instance02"); + requestInstance2.setServiceName("service01"); + requestInstance2.setApiPath("/test"); + + Bulkhead bulkheadInstance2 = instanceBulkheadHandler.getActuator(requestInstance2); + dsInstance2.withBulkhead(bulkheadInstance2); + + Executor executor = Executors.newFixedThreadPool(4); + AtomicInteger wakeCount = new AtomicInteger(0); + AtomicInteger sleepCount = new AtomicInteger(0); + AtomicInteger errorCount = new AtomicInteger(0); + AtomicInteger rejectCount = new AtomicInteger(0); + CountDownLatch countDownLatch = new CountDownLatch(100); + for (int i = 0; i < 100; i++) { + final int num = i; + executor.execute(() -> { + // 50% for each server + if (num % 2 == 0) { + runCommand(dsInstance1, wakeCount, sleepCount, errorCount, rejectCount, countDownLatch); + } else { + runCommand(dsInstance2, wakeCount, sleepCount, errorCount, rejectCount, countDownLatch); + } + }); + } + countDownLatch.await(100, TimeUnit.SECONDS); + Assertions.assertEquals(50, wakeCount.get()); + Assertions.assertEquals(2, sleepCount.get()); + Assertions.assertEquals(0, errorCount.get()); + Assertions.assertEquals(48, rejectCount.get()); + } + + private void runCommand(DecorateCheckedSupplier ds, AtomicInteger wakeCount, AtomicInteger sleepCount, + AtomicInteger errorCount, AtomicInteger rejectCount, CountDownLatch countDownLatch) { + try { + String result = ds.get(); + if ("wake".equals(result)) { + wakeCount.incrementAndGet(); + } else if ("sleep".equals(result)) { + sleepCount.incrementAndGet(); + } else { + errorCount.incrementAndGet(); + } + } catch (BulkheadFullException e) { + rejectCount.incrementAndGet(); + } catch (Throwable e) { + errorCount.incrementAndGet(); + } + countDownLatch.countDown(); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/InstanceIsolationTest.java b/governance/src/test/java/org/apache/servicecomb/governance/InstanceIsolationTest.java new file mode 100644 index 00000000000..0a6c8f23e14 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/InstanceIsolationTest.java @@ -0,0 +1,138 @@ +/* + * 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.governance; + +import java.net.ConnectException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.servicecomb.governance.handler.InstanceIsolationHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.github.resilience4j.circuitbreaker.CallNotPermittedException; +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCheckedSupplier; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.prometheusmetrics.PrometheusMeterRegistry; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class InstanceIsolationTest { + private InstanceIsolationHandler instanceIsolationHandler; + + private MeterRegistry meterRegistry; + + @Autowired + public void setInstanceIsolationHandler(InstanceIsolationHandler instanceIsolationHandler, + MeterRegistry meterRegistry) { + this.instanceIsolationHandler = instanceIsolationHandler; + this.meterRegistry = meterRegistry; + } + + @Test + public void test_instance_isolation_work() throws Throwable { + AtomicInteger counter = new AtomicInteger(0); + + DecorateCheckedSupplier ds = Decorators.ofCheckedSupplier(() -> { + int run = counter.getAndIncrement(); + if (run == 0) { + return "test"; + } + if (run == 1) { + throw new ConnectException("test exception"); + } + return "test"; + }); + + DecorateCheckedSupplier ds2 = Decorators.ofCheckedSupplier(() -> "test"); + + GovernanceRequest request = new GovernanceRequest(); + request.setInstanceId("instance01"); + request.setServiceName("service01"); + request.setApiPath("/test"); + + CircuitBreaker circuitBreaker = instanceIsolationHandler.getActuator(request); + ds.withCircuitBreaker(circuitBreaker); + + // isolation from error + Assertions.assertEquals("test", ds.get()); + Assertions.assertThrows(ConnectException.class, ds::get); + + Assertions.assertThrows(CallNotPermittedException.class, ds::get); + Assertions.assertThrows(CallNotPermittedException.class, ds::get); + + Assertions.assertThrows(CallNotPermittedException.class, ds::get); + Assertions.assertThrows(CallNotPermittedException.class, ds::get); + Assertions.assertThrows(CallNotPermittedException.class, ds::get); + + // isolation do not influence other instances + GovernanceRequest request2 = new GovernanceRequest(); + request2.setInstanceId("instance02"); + request2.setServiceName("service01"); + request2.setApiPath("/test"); + + CircuitBreaker circuitBreaker2 = instanceIsolationHandler.getActuator(request2); + ds2.withCircuitBreaker(circuitBreaker2); + + Assertions.assertEquals("test", ds2.get()); + Assertions.assertEquals("test", ds2.get()); + Assertions.assertEquals("test", ds2.get()); + Assertions.assertEquals("test", ds2.get()); + + assertMetricsNotFinish(); + + // recover from isolation + Thread.sleep(1000); + + Assertions.assertEquals("test", ds.get()); + Assertions.assertEquals("test", ds.get()); + Assertions.assertEquals("test", ds2.get()); + Assertions.assertEquals("test", ds2.get()); + + assertMetricsFinish(); + } + + private void assertMetricsNotFinish() { + String result = ((PrometheusMeterRegistry) meterRegistry).scrape(); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_state{name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance01\",state=\"open\"} 1.0")); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_state{name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance02\",state=\"closed\"} 1.0")); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_calls_seconds_count{kind=\"successful\",name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance01\"} 1")); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_calls_seconds_count{kind=\"successful\",name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance02\"} 4")); + } + + private void assertMetricsFinish() { + String result = ((PrometheusMeterRegistry) meterRegistry).scrape(); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_state{name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance01\",state=\"closed\"} 1.0")); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_state{name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance02\",state=\"closed\"} 1.0")); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_calls_seconds_count{kind=\"successful\",name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance01\"} 3")); + Assertions.assertTrue(result.contains( + "servicecomb_instanceIsolation_calls_seconds_count{kind=\"successful\",name=\"servicecomb.instanceIsolation.demo-allOperation.service01.instance02\"} 6")); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/LoadBalancerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/LoadBalancerTest.java new file mode 100644 index 00000000000..9973cbc56c7 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/LoadBalancerTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.governance; + +import org.apache.servicecomb.governance.handler.LoadBalanceHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.processor.loadbanlance.LoadBalance; +import org.junit.Assert; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class LoadBalancerTest { + private LoadBalanceHandler loadBalanceHandler; + + @Autowired + public void setLoadBalanceHandler(LoadBalanceHandler loadBalanceHandler) { + this.loadBalanceHandler = loadBalanceHandler; + } + + public LoadBalancerTest() { + + } + + @Test + public void test_loadbalance_random() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/loadrandom"); + request.setServiceName("loadrandom"); + LoadBalance loadBalance = loadBalanceHandler.getActuator(request); + Assert.assertEquals("Random", loadBalance.getRule()); + } + + @Test + public void test_loadbalance_roundRobin() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/loadroundRobin"); + request.setServiceName("loadroundRobin"); + LoadBalance loadBalance = loadBalanceHandler.getActuator(request); + Assert.assertEquals("RoundRobin", loadBalance.getRule()); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java b/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java new file mode 100644 index 00000000000..4a4607fefc3 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java @@ -0,0 +1,76 @@ +/* + * 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.governance; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.governance.handler.MapperHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.processor.mapping.Mapper; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class MapperTest { + private MapperHandler mapperHandler; + + private MapperHandler mapperHandler2; + + @Autowired + public void setMapperHandler(MapperHandler scbMapperHandler, @Qualifier("mapperHandler2") MapperHandler mapperHandler2) { + this.mapperHandler = scbMapperHandler; + this.mapperHandler2 = mapperHandler2; + } + + @Test + public void test_mapper_work() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/mapper/v1"); + Mapper mapper = mapperHandler.getActuator(request); + Assertions.assertEquals(2, mapper.target().size()); + Assertions.assertEquals("127.0.0.1", mapper.target().get("host")); + Assertions.assertEquals("8080", mapper.target().get("port")); + } + + @Test + public void test_mapper_query_work() { + GovernanceRequest request = new GovernanceRequest(); + Map queries = new HashMap<>(); + queries.put("name", "bob"); + request.setQueries(queries); + Mapper mapper = mapperHandler.getActuator(request); + Assertions.assertEquals(1, mapper.target().size()); + Assertions.assertEquals("$Q{name}", mapper.target().get("user-id")); + } + + @Test + public void test_mapper2_work() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/mapper/v1"); + Mapper mapper = mapperHandler2.getActuator(request); + Assertions.assertEquals(2, mapper.target().size()); + Assertions.assertEquals("127.0.0.1", mapper.target().get("host")); + Assertions.assertEquals("9090", mapper.target().get("port")); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockCircuitBreakerExtension.java b/governance/src/test/java/org/apache/servicecomb/governance/MockCircuitBreakerExtension.java new file mode 100644 index 00000000000..c66cac8fbfa --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/MockCircuitBreakerExtension.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.governance; + +import org.apache.servicecomb.governance.handler.ext.AbstractCircuitBreakerExtension; + +public class MockCircuitBreakerExtension extends AbstractCircuitBreakerExtension { + @Override + protected String extractStatusCode(Object result) { + return "200"; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockConfiguration.java b/governance/src/test/java/org/apache/servicecomb/governance/MockConfiguration.java new file mode 100644 index 00000000000..85c04f39590 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/MockConfiguration.java @@ -0,0 +1,106 @@ +/* + * 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.governance; + +import org.apache.servicecomb.governance.handler.BulkheadHandler; +import org.apache.servicecomb.governance.handler.CircuitBreakerHandler; +import org.apache.servicecomb.governance.handler.FaultInjectionHandler; +import org.apache.servicecomb.governance.handler.MapperHandler; +import org.apache.servicecomb.governance.handler.ext.AbstractCircuitBreakerExtension; +import org.apache.servicecomb.governance.properties.BulkheadProperties; +import org.apache.servicecomb.governance.properties.CircuitBreakerProperties; +import org.apache.servicecomb.governance.properties.FaultInjectionProperties; +import org.apache.servicecomb.governance.properties.MapperProperties; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import io.micrometer.prometheusmetrics.PrometheusConfig; +import io.micrometer.prometheusmetrics.PrometheusMeterRegistry; + + +@Configuration +public class MockConfiguration { + @Bean + public MockMicroserviceMeta mockMicroserviceMeta() { + return new MockMicroserviceMeta(); + } + + @Bean + public MockRetryExtension mockRetryExtension() { + return new MockRetryExtension(); + } + + @Bean + public MockCircuitBreakerExtension circuitBreakerExtension() { + return new MockCircuitBreakerExtension(); + } + + @Bean + public MockInstanceIsolationExtension instanceIsolationExtension() { + return new MockInstanceIsolationExtension(); + } + + @Bean + public PrometheusMeterRegistry meterRegistry() { + return new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + } + + @Bean + public MapperProperties mapperProperties2() { + return new MapperProperties(MapperProperties.MATCH_MAPPER_KEY + "2"); + } + + @Bean + public MapperHandler mapperHandler2(@Qualifier("mapperProperties2") MapperProperties mapperProperties) { + return new MapperHandler(mapperProperties); + } + + @Bean + public BulkheadProperties bulkheadProperties2() { + return new BulkheadProperties(BulkheadProperties.MATCH_BULKHEAD_KEY + "2"); + } + + @Bean + public BulkheadHandler bulkheadHandler2(@Qualifier("bulkheadProperties2") BulkheadProperties bulkheadProperties) { + return new BulkheadHandler(bulkheadProperties); + } + + @Bean + public CircuitBreakerProperties circuitBreakerProperties2() { + return new CircuitBreakerProperties(CircuitBreakerProperties.MATCH_CIRCUITBREAKER_KEY + "2"); + } + + @Bean + public CircuitBreakerHandler circuitBreakerHandler2( + @Qualifier("circuitBreakerProperties2") CircuitBreakerProperties circuitBreakerProperties, + AbstractCircuitBreakerExtension circuitBreakerExtension) { + return new CircuitBreakerHandler(circuitBreakerProperties, circuitBreakerExtension); + } + + @Bean + public FaultInjectionProperties faultInjectionProperties2() { + return new FaultInjectionProperties(FaultInjectionProperties.MATCH_FAULT_INJECTION_KEY + "2"); + } + + @Bean + public FaultInjectionHandler faultInjectionHandler2( + @Qualifier("faultInjectionProperties2") FaultInjectionProperties faultInjectionProperties) { + return new FaultInjectionHandler(faultInjectionProperties); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockInstanceIsolationExtension.java b/governance/src/test/java/org/apache/servicecomb/governance/MockInstanceIsolationExtension.java new file mode 100644 index 00000000000..86f0ce99b37 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/MockInstanceIsolationExtension.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.governance; + +import org.apache.servicecomb.governance.handler.ext.AbstractInstanceIsolationExtension; + +public class MockInstanceIsolationExtension extends AbstractInstanceIsolationExtension { + @Override + protected String extractStatusCode(Object result) { + return "200"; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockInvocationContext.java b/governance/src/test/java/org/apache/servicecomb/governance/MockInvocationContext.java deleted file mode 100644 index bde9b38dddb..00000000000 --- a/governance/src/test/java/org/apache/servicecomb/governance/MockInvocationContext.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.governance; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.springframework.stereotype.Component; - -@Component -public class MockInvocationContext implements InvocationContext { - private ThreadLocal> context = new ThreadLocal<>(); - - @Override - public Map getCalculatedMatches() { - Map result = context.get(); - if (result == null) { - return Collections.emptyMap(); - } - return result; - } - - @Override - public void addMatch(String key, Boolean value) { - Map result = context.get(); - if (result == null) { - result = new HashMap<>(); - context.set(result); - } - result.put(key, value); - } -} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockMicroserviceMeta.java b/governance/src/test/java/org/apache/servicecomb/governance/MockMicroserviceMeta.java index 552c5209dee..ca68e2b3a39 100644 --- a/governance/src/test/java/org/apache/servicecomb/governance/MockMicroserviceMeta.java +++ b/governance/src/test/java/org/apache/servicecomb/governance/MockMicroserviceMeta.java @@ -17,9 +17,6 @@ package org.apache.servicecomb.governance; -import org.springframework.stereotype.Component; - -@Component public class MockMicroserviceMeta implements MicroserviceMeta { @Override public String getName() { diff --git a/governance/src/test/java/org/apache/servicecomb/governance/MockRetryExtension.java b/governance/src/test/java/org/apache/servicecomb/governance/MockRetryExtension.java index 50e8fc43db8..2badc9c1548 100644 --- a/governance/src/test/java/org/apache/servicecomb/governance/MockRetryExtension.java +++ b/governance/src/test/java/org/apache/servicecomb/governance/MockRetryExtension.java @@ -19,19 +19,22 @@ import java.util.List; -import org.springframework.stereotype.Component; +import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension; -import org.apache.servicecomb.governance.handler.ext.RetryExtension; -@Component -public class MockRetryExtension implements RetryExtension { +public class MockRetryExtension extends AbstractRetryExtension { @Override - public boolean isRetry(List statusList, Object result) { + public boolean isFailedResult(List statusList, Object result) { return false; } @Override - public Class[] retryExceptions() { + protected String extractStatusCode(Object result) { return null; } + + @Override + public boolean isFailedResult(List statusList, Throwable e) { + return false; + } } diff --git a/governance/src/test/java/org/apache/servicecomb/governance/OperatorTest.java b/governance/src/test/java/org/apache/servicecomb/governance/OperatorTest.java index a389984f698..7c0670acb93 100644 --- a/governance/src/test/java/org/apache/servicecomb/governance/OperatorTest.java +++ b/governance/src/test/java/org/apache/servicecomb/governance/OperatorTest.java @@ -27,110 +27,112 @@ import org.apache.servicecomb.governance.marker.RequestProcessor; import org.apache.servicecomb.governance.marker.operator.RawOperator; import org.apache.servicecomb.governance.policy.RetryPolicy; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) -@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class) +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) public class OperatorTest { - @Autowired private RequestProcessor requestProcessor; + @Autowired + public void setRequestProcessor(RequestProcessor requestProcessor) { + this.requestProcessor = requestProcessor; + } + @Test public void test_unknown_operator() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/test"); + request.setApiPath("/test"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("unknown", "/test"); matcher.setApiPath(apiPath); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); } @Test public void test_exact_api_path_match() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/bulkhead"); + request.setApiPath("/bulkhead"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("exact", "/bulkhead"); matcher.setApiPath(apiPath); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); } @Test public void test_prefix_api_path_match() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/bulkhead/hello"); + request.setApiPath("/bulkhead/hello"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("prefix", "/bulkhead"); matcher.setApiPath(apiPath); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); } @Test public void test_prefix_api_path_not_match_null() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/bulkhead/hello"); + request.setApiPath("/bulkhead/hello"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("prefix", null); matcher.setApiPath(apiPath); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); } @Test public void test_suffix_api_path_match() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/api/bulkhead"); + request.setApiPath("/api/bulkhead"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("suffix", "/bulkhead"); matcher.setApiPath(apiPath); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); } @Test public void test_suffix_api_path_not_match_null() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/api/bulkhead"); + request.setApiPath("/api/bulkhead"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("suffix", null); matcher.setApiPath(apiPath); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); } @Test public void test_exact_api_path_not_match() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/bulkhead/"); + request.setApiPath("/bulkhead/"); Matcher matcher = new Matcher(); RawOperator apiPath = new RawOperator(); apiPath.put("exact", "/bulkhead"); matcher.setApiPath(apiPath); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); - request.setUri("/bulkhead"); - request.setUri(null); - Assert.assertFalse(requestProcessor.match(request, matcher)); + request.setApiPath("/bulkhead"); + request.setApiPath(null); + Assertions.assertFalse(requestProcessor.match(request, matcher)); - request.setUri("/bulkhead"); + request.setApiPath("/bulkhead"); apiPath.clear(); matcher.setApiPath(apiPath); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); } @Test public void test_exact_api_path_match_header_match() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/bulkhead"); + request.setApiPath("/bulkhead"); request.setMethod("GET"); Map reqHeaders = new HashMap<>(); reqHeaders.put("header1", "value1"); @@ -145,13 +147,13 @@ public void test_exact_api_path_match_header_match() { header1.put("exact", "value1"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); } @Test public void test_exact_api_path_match_header_not_match() { GovernanceRequest request = new GovernanceRequest(); - request.setUri("/bulkhead"); + request.setApiPath("/bulkhead"); request.setMethod("GET"); Map reqHeaders = new HashMap<>(); reqHeaders.put("header1", "value2"); @@ -166,11 +168,11 @@ public void test_exact_api_path_match_header_not_match() { header1.put("exact", "value1"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); reqHeaders.clear(); request.setHeaders(reqHeaders); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); } @Test @@ -185,7 +187,7 @@ public void test_header_low_case() { header1.put("compare", ">10"); headers.put("HeAder", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); } @Test @@ -201,31 +203,31 @@ public void test_compare_header_match() { header1.put("compare", ">10"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", ">=10"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", "<1000"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", "<=1000"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", "=100"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertTrue(requestProcessor.match(request, matcher)); + Assertions.assertTrue(requestProcessor.match(request, matcher)); } @Test @@ -241,31 +243,31 @@ public void test_compare_header_not_match() { header1.put("compare", ">1000"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", ">=1000"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", "<10"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", "<=10"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); header1 = new RawOperator(); header1.put("compare", "=200"); headers.put("header1", header1); matcher.setHeaders(headers); - Assert.assertFalse(requestProcessor.match(request, matcher)); + Assertions.assertFalse(requestProcessor.match(request, matcher)); } @Test @@ -273,23 +275,23 @@ public void test_time_changed_to_duration() { RetryPolicy retryPolicy = new RetryPolicy(); String result; result = retryPolicy.stringOfDuration("100", Duration.ofMillis(10)); - Assert.assertEquals("PT0.1S", result); - Assert.assertEquals(100, Duration.parse(result).toMillis()); + Assertions.assertEquals("PT0.1S", result); + Assertions.assertEquals(100, Duration.parse(result).toMillis()); result = retryPolicy.stringOfDuration("3S", Duration.ofMillis(10)); - Assert.assertEquals("PT3S", result); - Assert.assertEquals(3000, Duration.parse(result).toMillis()); + Assertions.assertEquals("PT3S", result); + Assertions.assertEquals(3000, Duration.parse(result).toMillis()); result = retryPolicy.stringOfDuration("1M", Duration.ofMillis(10)); - Assert.assertEquals("PT1M", result); - Assert.assertEquals(60000, Duration.parse(result).toMillis()); + Assertions.assertEquals("PT1M", result); + Assertions.assertEquals(60000, Duration.parse(result).toMillis()); result = retryPolicy.stringOfDuration("1H", Duration.ofMillis(10)); - Assert.assertEquals("PT1H", result); - Assert.assertEquals(3600000, Duration.parse(result).toMillis()); + Assertions.assertEquals("PT1H", result); + Assertions.assertEquals(3600000, Duration.parse(result).toMillis()); result = retryPolicy.stringOfDuration("3", Duration.ofMillis(10)); - Assert.assertEquals("PT0.003S", result); - Assert.assertEquals(3, Duration.parse(result).toMillis()); + Assertions.assertEquals("PT0.003S", result); + Assertions.assertEquals(3, Duration.parse(result).toMillis()); } } diff --git a/governance/src/test/java/org/apache/servicecomb/governance/RetryHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/RetryHandlerTest.java new file mode 100644 index 00000000000..073cfc44534 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/RetryHandlerTest.java @@ -0,0 +1,85 @@ +/* + * 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.governance; + +import org.apache.servicecomb.governance.handler.Disposable; +import org.apache.servicecomb.governance.handler.RetryHandler; +import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.policy.RetryPolicy; +import org.apache.servicecomb.governance.properties.RetryProperties; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import io.github.resilience4j.retry.MaxRetriesExceededException; +import io.github.resilience4j.retry.Retry; + +public class RetryHandlerTest { + @Test + public void testNotFailAfterMaxAttemptsWhenThrow() { + AbstractRetryExtension retryExtension = Mockito.mock(AbstractRetryExtension.class); + RetryProperties retryProperties = Mockito.mock(RetryProperties.class); + GovernanceRequest governanceRequest = Mockito.mock(GovernanceRequest.class); + Mockito.when(retryExtension.isFailedResult(Mockito.any(), Mockito.any())).thenReturn(true); + + RetryPolicy retryPolicy = new RetryPolicy(); + retryPolicy.setName("test"); + retryPolicy.setFailAfterMaxAttempts(false); + RetryHandler retryHandler = new RetryHandler(retryProperties, retryExtension); + + Disposable retry = retryHandler.createProcessor(retryPolicy.getName(), governanceRequest, retryPolicy); + Assertions.assertThrows(IllegalStateException.class, () -> retry.get().executeCheckedSupplier(() -> { + throw new IllegalStateException(); + })); + } + + @Test + public void testFailAfterMaxAttemptsWhenThrow() { + AbstractRetryExtension retryExtension = Mockito.mock(AbstractRetryExtension.class); + RetryProperties retryProperties = Mockito.mock(RetryProperties.class); + GovernanceRequest governanceRequest = Mockito.mock(GovernanceRequest.class); + Mockito.when(retryExtension.isFailedResult(Mockito.any(), Mockito.any())).thenReturn(true); + + RetryPolicy retryPolicy = new RetryPolicy(); + retryPolicy.setName("test"); + retryPolicy.setFailAfterMaxAttempts(true); + RetryHandler retryHandler = new RetryHandler(retryProperties, retryExtension); + + Disposable retry = retryHandler.createProcessor(retryPolicy.getName(), governanceRequest, retryPolicy); + Assertions.assertThrows(IllegalStateException.class, () -> retry.get().executeCheckedSupplier(() -> { + throw new IllegalStateException(); + })); + } + + @Test + public void testFailAfterMaxAttemptsOnResult() { + AbstractRetryExtension retryExtension = Mockito.mock(AbstractRetryExtension.class); + RetryProperties retryProperties = Mockito.mock(RetryProperties.class); + GovernanceRequest governanceRequest = Mockito.mock(GovernanceRequest.class); + Mockito.when(retryExtension.isFailedResult(Mockito.any(), (Object) Mockito.any())).thenReturn(true); + + RetryPolicy retryPolicy = new RetryPolicy(); + retryPolicy.setName("test"); + retryPolicy.setFailAfterMaxAttempts(true); + RetryHandler retryHandler = new RetryHandler(retryProperties, retryExtension); + + Disposable retry = retryHandler.createProcessor(retryPolicy.getName(), governanceRequest, retryPolicy); + Assertions.assertThrows(MaxRetriesExceededException.class, + () -> retry.get().executeCheckedSupplier(() -> -1)); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/TimeLimiterHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/TimeLimiterHandlerTest.java new file mode 100644 index 00000000000..742c7118417 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/TimeLimiterHandlerTest.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.governance; + +import java.time.Duration; + +import org.apache.servicecomb.governance.handler.TimeLimiterHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.policy.TimeLimiterPolicy; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import io.github.resilience4j.timelimiter.TimeLimiter; + +@SpringBootTest +@ContextConfiguration(classes = {GovernanceCommonConfiguration.class, MockConfiguration.class}) +public class TimeLimiterHandlerTest { + private TimeLimiterHandler timeLimiterHandler; + + @Autowired + public void setInstanceIsolationHandler(TimeLimiterHandler timeLimiterHandler) { + this.timeLimiterHandler = timeLimiterHandler; + } + + @Test + public void testMatchPriorityPolicy() { + GovernanceRequest request = new GovernanceRequest(); + request.setApiPath("/timeLimiter"); + TimeLimiterPolicy policy = timeLimiterHandler.matchPolicy(request); + Assertions.assertEquals("demo-timeLimiter", policy.getName()); + TimeLimiter timeLimiter = timeLimiterHandler.getActuator(request); + Duration timeoutDuration = timeLimiter.getTimeLimiterConfig().getTimeoutDuration(); + Assertions.assertEquals(2000, timeoutDuration.toMillis()); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/handler/ext/RetryExtensionTest.java b/governance/src/test/java/org/apache/servicecomb/governance/handler/ext/RetryExtensionTest.java index 89b92a82914..41157a9b079 100644 --- a/governance/src/test/java/org/apache/servicecomb/governance/handler/ext/RetryExtensionTest.java +++ b/governance/src/test/java/org/apache/servicecomb/governance/handler/ext/RetryExtensionTest.java @@ -17,57 +17,140 @@ package org.apache.servicecomb.governance.handler.ext; +import java.io.IOException; +import java.net.ConnectException; +import java.net.NoRouteToHostException; +import java.net.SocketTimeoutException; import java.util.Arrays; import java.util.List; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; -@RunWith(SpringRunner.class) -@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class) +import io.vertx.core.VertxException; + +@SpringBootTest +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) public class RetryExtensionTest { @Test public void test_status_code_to_contains() { List statusList = Arrays.asList("502", "503"); boolean result = AbstractRetryExtension.statusCodeContains(statusList, "502"); - Assert.assertTrue(result); + Assertions.assertTrue(result); result = AbstractRetryExtension.statusCodeContains(statusList, "504"); - Assert.assertFalse(result); + Assertions.assertFalse(result); statusList = Arrays.asList("5xx", "4x4", "4x", "x32", "xx6"); result = AbstractRetryExtension.statusCodeContains(statusList, "502"); - Assert.assertTrue(result); + Assertions.assertTrue(result); result = AbstractRetryExtension.statusCodeContains(statusList, "504"); - Assert.assertTrue(result); + Assertions.assertTrue(result); statusList = Arrays.asList("4x4", "x32", "xx6"); result = AbstractRetryExtension.statusCodeContains(statusList, "402"); - Assert.assertFalse(result); + Assertions.assertFalse(result); result = AbstractRetryExtension.statusCodeContains(statusList, "404"); - Assert.assertTrue(result); + Assertions.assertTrue(result); result = AbstractRetryExtension.statusCodeContains(statusList, "332"); - Assert.assertTrue(result); + Assertions.assertTrue(result); result = AbstractRetryExtension.statusCodeContains(statusList, "446"); - Assert.assertTrue(result); + Assertions.assertTrue(result); statusList = Arrays.asList("4x", "x3x", "x5"); result = AbstractRetryExtension.statusCodeContains(statusList, "446"); - Assert.assertFalse(result); + Assertions.assertFalse(result); result = AbstractRetryExtension.statusCodeContains(statusList, "455"); - Assert.assertFalse(result); + Assertions.assertFalse(result); result = AbstractRetryExtension.statusCodeContains(statusList, "434"); - Assert.assertTrue(result); + Assertions.assertTrue(result); + } + + @Test + public void testRetryWithConnectionException() { + Exception target = new ConnectException("connection refused"); + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + } + + @Test + public void testRetryWithSocketTimeout() { + Exception target = new SocketTimeoutException("Read timed out"); + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + } + + @Test + public void testRetryWithIOException() { + Exception target = new IOException("Connection reset by peer"); + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + + target = new IOException("Target not exist"); + root = new Exception(target); + canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertFalse(canRetry); + } + + @Test + public void testRetryVertxException() { + Exception target = new VertxException("Connection was closed"); + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + + target = new IOException(""); + root = new Exception(target); + canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertFalse(canRetry); + } + + @Test + public void testRetryNoRouteToHostException() { + Exception target = new NoRouteToHostException("Host is unreachable"); + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + + target = new NoRouteToHostException("No route to host"); + root = new Exception(target); + canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + } + + @Test + public void testRetryEqualTen() { + Exception target = new ConnectException("connection refused"); + for (int i = 0; i < 8; i++) { + target = new Exception("Level" + i, target); + } + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertTrue(canRetry); + } + + @Test + public void testRetryOverTen() { + Exception target = new ConnectException("connection refused"); + for (int i = 0; i < 9; i++) { + target = new Exception("Level" + i, target); + } + Exception root = new Exception(target); + boolean canRetry = FailurePredictor.canRetryForException(FailurePredictor.STRICT_RETRIABLE, root); + Assertions.assertFalse(canRetry); } } diff --git a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassNotImplements.java b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassNotImplements.java new file mode 100644 index 00000000000..51336e60ed5 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassNotImplements.java @@ -0,0 +1,28 @@ +/* + * 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.governance.mockclasses; + +import org.springframework.stereotype.Component; +import org.apache.servicecomb.governance.marker.GovernanceRequest; + +@Component +public class ClassNotImplements { + public boolean matchRequest(GovernanceRequest request, String parameters) { + return true; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassWithAnnotation.java b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassWithAnnotation.java new file mode 100644 index 00000000000..263d442f40b --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/ClassWithAnnotation.java @@ -0,0 +1,39 @@ +/* + * 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.governance.mockclasses; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.mockclasses.service.MockProfileClassUserService; +import org.apache.servicecomb.governance.utils.CustomMatch; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ClassWithAnnotation implements CustomMatch { + @Autowired + MockProfileClassUserService service; + + @Override + public boolean matchRequest(GovernanceRequestExtractor requestExtractor, String parameters) { + String profileValue = service.getUser(); + return Stream.of(parameters.split(",")).collect(Collectors.toSet()).contains(profileValue); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/CustomMatchDemo.java b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/CustomMatchDemo.java new file mode 100644 index 00000000000..dba57a48dd5 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/CustomMatchDemo.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.governance.mockclasses; + +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.utils.CustomMatch; + +public class CustomMatchDemo implements CustomMatch { + + private CustomMatchDemo() { + + } + + @Override + public boolean matchRequest(GovernanceRequestExtractor requestExtractor, String parameters) { + return true; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockConfigurationForCustomMatcher.java b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockConfigurationForCustomMatcher.java new file mode 100644 index 00000000000..7668ddc8e28 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockConfigurationForCustomMatcher.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.governance.mockclasses.service; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("org.apache.servicecomb.governance.mockclasses") +public class MockConfigurationForCustomMatcher { +} diff --git a/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockProfileClassUserService.java b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockProfileClassUserService.java new file mode 100644 index 00000000000..31aa5479cef --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/governance/mockclasses/service/MockProfileClassUserService.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.governance.mockclasses.service; + +import org.springframework.stereotype.Service; + +@Service +public class MockProfileClassUserService { + public String getUser() { + return "bill"; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java b/governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java index 38f09686f97..42fdfad0367 100644 --- a/governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java +++ b/governance/src/test/java/org/apache/servicecomb/router/ExampleDistributor.java @@ -21,8 +21,8 @@ import org.springframework.stereotype.Component; @Component -public class ExampleDistributor extends AbstractRouterDistributor { +public class ExampleDistributor extends AbstractRouterDistributor { public ExampleDistributor() { - init(a -> a, ServiceIns::getVersion, ServiceIns::getServerName, ServiceIns::getTags); + init(ServiceIns::getVersion, ServiceIns::getServerName, ServiceIns::getTags); } -} \ No newline at end of file +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorDynamicConfig2Test.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorDynamicConfig2Test.java new file mode 100644 index 00000000000..cc8cc9ce96c --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorDynamicConfig2Test.java @@ -0,0 +1,279 @@ +/* + * 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.router; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; +import org.apache.servicecomb.governance.event.GovernanceEventManager; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.router.cache.RouterRuleCache; +import org.apache.servicecomb.router.distribute.RouterDistributor; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) +public class RouterDistributorDynamicConfig2Test { + private static final String TARGET_SERVICE_NAME = "test_server"; + + public static final String CONFIG_KEY = RouterRuleCache.ROUTE_RULE_PREFIX + TARGET_SERVICE_NAME; + + private static final String RULE_STRING = "" + + " - precedence: 2\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 1\n" + + " match:\n" + + " headers:\n" + + " appId:\n" + + " regex: 01\n" + + " caseInsensitive: false\n" + + " userId:\n" + + " exact: 01\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + + private Environment environment; + + private RouterFilter routerFilter; + + private RouterDistributor testDistributor; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Autowired + public void setRouterFilter(RouterFilter routerFilter) { + this.routerFilter = routerFilter; + } + + @Autowired + public void setTestDistributor(RouterDistributor testDistributor) { + this.testDistributor = testDistributor; + } + + private final Map dynamicValues = new HashMap<>(); + + @BeforeEach + public void setUp() { + ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment; + + if (configurableEnvironment.getPropertySources().contains("testDynamicChange")) { + configurableEnvironment.getPropertySources().remove("testDynamicChange"); + } + + configurableEnvironment.getPropertySources() + .addFirst(new EnumerablePropertySource>("testDynamicChange", dynamicValues) { + @Override + public Object getProperty(String s) { + return this.getSource().get(s); + } + + @Override + public String[] getPropertyNames() { + return this.getSource().keySet().toArray(new String[0]); + } + }); + + dynamicValues.put(CONFIG_KEY, RULE_STRING); + + postConfigurationChangedEvent(); + } + + private void postConfigurationChangedEvent() { + Set changedKeys = new HashSet<>(); + changedKeys.add(CONFIG_KEY); + GovernanceConfigurationChangedEvent newEvent = new GovernanceConfigurationChangedEvent(changedKeys); + GovernanceEventManager.post(newEvent); + } + + @Test + public void testMatchPrecedenceHigher() { + GovernanceRequest governanceRequest = new GovernanceRequest(); + Map headers = new HashMap<>(); + headers.put("userId", "01"); + headers.put("appId", "01"); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("2.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.setVersion("1.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(1, resultServerList.size()); + Assertions.assertEquals("01", resultServerList.get(0).getId()); + } + + @Test + public void testCaseSensitiveNotMatch() { + String rule = "" + + " - precedence: 1\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 2\n" + + " match:\n" + + " headers:\n" + + " userId:\n" + + " exact: user01\n" + + " caseInsensitive: false\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + dynamicValues.put(CONFIG_KEY, rule); + postConfigurationChangedEvent(); + + Map headers = new HashMap<>(); + headers.put("userId", "User01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("2.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.setVersion("1.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(1, resultServerList.size()); + Assertions.assertEquals("01", resultServerList.get(0).getId()); + Assertions.assertEquals("2.0", resultServerList.get(0).getVersion()); + } + + @Test + public void testNoneMatch() { + String rule = "" + + " - precedence: 1\n" + + " match:\n" + + " headers:\n" + + " userId:\n" + + " regex: user02\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 2\n" + + " match:\n" + + " headers:\n" + + " userId:\n" + + " exact: user01\n" + + " caseInsensitive: false\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + dynamicValues.put(CONFIG_KEY, rule); + postConfigurationChangedEvent(); + + Map headers = new HashMap<>(); + headers.put("userId", "User01"); + headers.put("appId", "App01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("2.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.setVersion("1.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(2, resultServerList.size()); + } + + @Test + public void testOneMatchButNoInstance() { + String rule = "" + + " - precedence: 1\n" + + " match:\n" + + " headers:\n" + + " appId:\n" + + " regex: app02\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 2\n" + + " match:\n" + + " headers:\n" + + " userId:\n" + + " exact: user01\n" + + " caseInsensitive: false\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + dynamicValues.put(CONFIG_KEY, rule); + postConfigurationChangedEvent(); + + Map headers = new HashMap<>(); + headers.put("userId", "user01"); + headers.put("appId", "app02"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("1.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.setVersion("1.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(2, resultServerList.size()); + } + + private List mainFilter(List serverList, GovernanceRequestExtractor requestExtractor) { + return routerFilter + .getFilteredListOfServers(serverList, TARGET_SERVICE_NAME, requestExtractor, + testDistributor); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorDynamicConfigTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorDynamicConfigTest.java new file mode 100644 index 00000000000..4418a30829b --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorDynamicConfigTest.java @@ -0,0 +1,224 @@ +/* + * 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.router; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; +import org.apache.servicecomb.governance.event.GovernanceEventManager; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.router.cache.RouterRuleCache; +import org.apache.servicecomb.router.distribute.RouterDistributor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) +public class RouterDistributorDynamicConfigTest { + private static final String TARGET_SERVICE_NAME = "test_server"; + + private static final String RULE_STRING = "" + + " - precedence: 2 #优先级\n" + + " match: #匹配策略\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"01\"\n" + + " route: #路由规则\n" + + " - weight: 50\n" + + " tags:\n" + + " version: 1.1\n" + + " - precedence: 1\n" + + " match:\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"02\"\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 3\n" + + " match:\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"03\"\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + + private Environment environment; + + private RouterFilter routerFilter; + + private RouterDistributor testDistributor; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Autowired + public void setRouterFilter(RouterFilter routerFilter) { + this.routerFilter = routerFilter; + } + + @Autowired + public void setTestDistributor(RouterDistributor testDistributor) { + this.testDistributor = testDistributor; + } + + public RouterDistributorDynamicConfigTest() { + } + + private final Map dynamicValues = new HashMap<>(); + + @BeforeEach + public void setUp() { + ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment; + + if (configurableEnvironment.getPropertySources().contains("testDynamicChange")) { + configurableEnvironment.getPropertySources().remove("testDynamicChange"); + } + + configurableEnvironment.getPropertySources() + .addFirst(new EnumerablePropertySource>("testDynamicChange", dynamicValues) { + @Override + public Object getProperty(String s) { + return this.getSource().get(s); + } + + @Override + public String[] getPropertyNames() { + return this.getSource().keySet().toArray(new String[0]); + } + }); + + dynamicValues.put(RouterRuleCache.ROUTE_RULE_PREFIX + TARGET_SERVICE_NAME, RULE_STRING); + + Set changedKeys = new HashSet<>(); + changedKeys.add(RouterRuleCache.ROUTE_RULE_PREFIX + TARGET_SERVICE_NAME); + GovernanceConfigurationChangedEvent newEvent = new GovernanceConfigurationChangedEvent(changedKeys); + GovernanceEventManager.post(newEvent); + } + + + @Test + public void testHeaderIsEmpty() { + List list = getMockList(); + List serverList = mainFilter(list, new GovernanceRequest()); + Assertions.assertEquals(2, serverList.size()); + } + + @Test + public void testVersionNotMatch() { + Map headerMap = new HashMap<>(); + headerMap.put("userId", "02"); + headerMap.put("appId", "01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headerMap); + List list = getMockList(); + list.remove(1); + List serverList = mainFilter(list, governanceRequest); + Assertions.assertEquals(1, serverList.size()); + Assertions.assertEquals("01", serverList.get(0).getId()); + } + + @Test + public void testVersionMatch() { + Map headers = new HashMap<>(); + headers.put("userId", "01"); + headers.put("appId", "01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + List serverList = mainFilter(getMockList(), governanceRequest); + Assertions.assertEquals(1, serverList.size()); + Assertions.assertEquals("02", serverList.get(0).getId()); + } + + @Test + public void testMatchPrecedenceLower() { + Map headers = new HashMap<>(); + headers.put("userId", "02"); + headers.put("appId", "01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + List serverList = mainFilter(getMockList(), governanceRequest); + Assertions.assertEquals(1, serverList.size()); + Assertions.assertEquals("01", serverList.get(0).getId()); + } + + @Test + public void testMatchPrecedenceHigher() { + Map headers = new HashMap<>(); + headers.put("userId", "03"); + headers.put("appId", "01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("2.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.addTags("app", "a"); + ins2.setVersion("1.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(1, resultServerList.size()); + Assertions.assertEquals("02", resultServerList.get(0).getId()); + } + + private List getMockList() { + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("2.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.addTags("app", "a"); + serverList.add(ins1); + serverList.add(ins2); + return serverList; + } + + private List mainFilter(List serverList, + GovernanceRequestExtractor governanceRequestExtractor) { + return routerFilter + .getFilteredListOfServers(serverList, TARGET_SERVICE_NAME, governanceRequestExtractor, + testDistributor); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileConfigTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileConfigTest.java new file mode 100644 index 00000000000..54ebcb05823 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileConfigTest.java @@ -0,0 +1,97 @@ +/* + * 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.router; + +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.router.distribute.RouterDistributor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +@SpringBootTest +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) +public class RouterDistributorFileConfigTest { + private static final String TARGET_SERVICE_NAME = "test_server1"; + + private RouterFilter routerFilter; + + private RouterDistributor routerDistributor; + + @Autowired + public void setRouterFilter(RouterFilter routerFilter) { + this.routerFilter = routerFilter; + } + + @Autowired + public void setRouterDistributor(RouterDistributor routerDistributor) { + this.routerDistributor = routerDistributor; + } + + @Test + public void testDistribute() { + List list = initServiceList(); + HashMap header = new HashMap<>(); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(header); + + List listOfServers = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME, governanceRequest, routerDistributor); + Assertions.assertNotNull(listOfServers); + for (ServiceIns server : listOfServers) { + Assertions.assertEquals(TARGET_SERVICE_NAME, server.getServerName()); + } + int serverNum1 = 0; + int serverNum2 = 0; + + for (int i = 0; i < 10; i++) { + List serverList = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME, governanceRequest, routerDistributor); + for (ServiceIns serviceIns : serverList) { + if ("01".equals(serviceIns.getId())) { + serverNum1++; + } else if ("02".equals(serviceIns.getId())) { + serverNum2++; + } + } + } + boolean flag = false; + if (Math.round(serverNum2 * 1.0 / serverNum1) == 4) { + flag = true; + } + Assertions.assertTrue(flag); + } + + List initServiceList() { + ServiceIns serviceIns1 = new ServiceIns("01", "test_server1"); + ServiceIns serviceIns2 = new ServiceIns("02", "test_server1"); + serviceIns1.setVersion("1.0"); + serviceIns2.setVersion("2.0"); + serviceIns1.addTags("x-group", "red"); + serviceIns2.addTags("x-group", "green"); + List list = new ArrayList<>(); + list.add(serviceIns1); + list.add(serviceIns2); + return list; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileWeightLessTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileWeightLessTest.java new file mode 100644 index 00000000000..68b04bc9cdb --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileWeightLessTest.java @@ -0,0 +1,96 @@ +/* + * 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.router; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.router.distribute.RouterDistributor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) +public class RouterDistributorFileWeightLessTest { + private static final String TARGET_SERVICE_NAME = "test_server2"; + + private RouterFilter routerFilter; + + private RouterDistributor routerDistributor; + + @Autowired + public void setRouterFilter(RouterFilter routerFilter) { + this.routerFilter = routerFilter; + } + + @Autowired + public void setRouterDistributor(RouterDistributor routerDistributor) { + this.routerDistributor = routerDistributor; + } + + @Test + public void testDistribute() { + List list = initServiceList(); + HashMap header = new HashMap<>(); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(header); + List listOfServers = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME, governanceRequest, routerDistributor); + Assertions.assertNotNull(listOfServers); + for (ServiceIns server : listOfServers) { + Assertions.assertEquals(TARGET_SERVICE_NAME, server.getServerName()); + } + int serverNum1 = 0; + int unSetTagNum = 0; + + for (int i = 0; i < 10; i++) { + List serverList = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME, governanceRequest, routerDistributor); + for (ServiceIns serviceIns : serverList) { + if ("01".equals(serviceIns.getId())) { + serverNum1++; + } else if ("02".equals(serviceIns.getId())) { + unSetTagNum++; + } + } + } + boolean flag = false; + if (Math.round(unSetTagNum * 1.0 / serverNum1) == 4) { + flag = true; + } + Assertions.assertTrue(flag); + } + + List initServiceList() { + ServiceIns serviceIns1 = new ServiceIns("01", "test_server2"); + ServiceIns serviceIns2 = new ServiceIns("02", "test_server2"); + serviceIns1.setVersion("1.0"); + serviceIns2.setVersion("2.0"); + serviceIns1.addTags("x-group", "red"); + serviceIns2.addTags("x-group", "green"); + List list = new ArrayList<>(); + list.add(serviceIns1); + list.add(serviceIns2); + return list; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileWithFallbackTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileWithFallbackTest.java new file mode 100644 index 00000000000..2d7a1064557 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorFileWithFallbackTest.java @@ -0,0 +1,162 @@ +/* + * 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.router; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.router.distribute.RouterDistributor; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) +public class RouterDistributorFileWithFallbackTest { + private static final String TARGET_SERVICE_NAME_WITHOUT_FALLBACK = "test_server3"; + + private static final String TARGET_SERVICE_NAME_WITH_FALLBACK = "test_server4"; + + private static final String TARGET_SERVICE_NAME_ROUTE_FALLBACK = "test_server5"; + + private RouterFilter routerFilter; + + private RouterDistributor routerDistributor; + + @Autowired + public void setRouterFilter(RouterFilter routerFilter) { + this.routerFilter = routerFilter; + } + + @Autowired + public void setRouterDistributor(RouterDistributor routerDistributor) { + this.routerDistributor = routerDistributor; + } + + @Test + public void testDistributeWithoutFallback() { + List list = initServiceList(TARGET_SERVICE_NAME_WITHOUT_FALLBACK); + HashMap header = new HashMap<>(); + header.put("canary", "canary"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(header); + List listOfServers = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME_WITHOUT_FALLBACK, governanceRequest, routerDistributor); + Assertions.assertNotNull(listOfServers); + for (ServiceIns server : listOfServers) { + Assertions.assertEquals(TARGET_SERVICE_NAME_WITHOUT_FALLBACK, server.getServerName()); + } + int serverNum1 = 0; + int serverNum2 = 0; + + for (int i = 0; i < 10; i++) { + List serverList = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME_WITHOUT_FALLBACK, governanceRequest, routerDistributor); + for (ServiceIns serviceIns : serverList) { + if ("01".equals(serviceIns.getId())) { + serverNum1++; + } else if ("02".equals(serviceIns.getId())) { + serverNum2++; + } + } + } + Assertions.assertTrue(serverNum2 == serverNum1); + } + + @Test + public void testDistributeWithFallback() { + List list = initServiceList(TARGET_SERVICE_NAME_WITH_FALLBACK); + HashMap header = new HashMap<>(); + header.put("canary", "canary"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(header); + List listOfServers = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME_WITH_FALLBACK, governanceRequest, routerDistributor); + Assertions.assertNotNull(listOfServers); + for (ServiceIns server : listOfServers) { + Assertions.assertEquals(TARGET_SERVICE_NAME_WITH_FALLBACK, server.getServerName()); + } + int serverNum1 = 0; + int serverNum2 = 0; + + for (int i = 0; i < 10; i++) { + List serverList = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME_WITH_FALLBACK, governanceRequest, routerDistributor); + for (ServiceIns serviceIns : serverList) { + if ("01".equals(serviceIns.getId())) { + serverNum1++; + } else if ("02".equals(serviceIns.getId())) { + serverNum2++; + } + } + } + Assertions.assertTrue((serverNum2 + serverNum1) == serverNum1); + } + + @Test + public void testDistributeRouteAndFallbackHaveSame() { + List list = initServiceList(TARGET_SERVICE_NAME_ROUTE_FALLBACK); + HashMap header = new HashMap<>(); + header.put("canary", "canary"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(header); + List listOfServers = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME_ROUTE_FALLBACK, governanceRequest, routerDistributor); + Assertions.assertNotNull(listOfServers); + for (ServiceIns server : listOfServers) { + Assertions.assertEquals(TARGET_SERVICE_NAME_ROUTE_FALLBACK, server.getServerName()); + } + int serverNum1 = 0; + int serverNum2 = 0; + + for (int i = 0; i < 20; i++) { + List serverList = routerFilter + .getFilteredListOfServers(list, TARGET_SERVICE_NAME_ROUTE_FALLBACK, governanceRequest, routerDistributor); + for (ServiceIns serviceIns : serverList) { + if ("01".equals(serviceIns.getId())) { + serverNum1++; + } else if ("02".equals(serviceIns.getId())) { + serverNum2++; + } + } + } + boolean flag = false; + if (Math.round(serverNum1 * 1.0 / serverNum2) == 3) { + flag = true; + } + Assertions.assertTrue(flag); + } + + List initServiceList(String serviceName) { + ServiceIns serviceIns1 = new ServiceIns("01", serviceName); + ServiceIns serviceIns2 = new ServiceIns("02", serviceName); + serviceIns1.setVersion("1.0"); + serviceIns2.setVersion("2.0"); + serviceIns1.addTags("x-group", "red"); + serviceIns2.addTags("x-group", "green"); + List list = new ArrayList<>(); + list.add(serviceIns1); + list.add(serviceIns2); + return list; + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorGlobalConfigTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorGlobalConfigTest.java new file mode 100644 index 00000000000..89a54d76979 --- /dev/null +++ b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorGlobalConfigTest.java @@ -0,0 +1,209 @@ +/* + * 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.router; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; +import org.apache.servicecomb.governance.event.GovernanceEventManager; +import org.apache.servicecomb.governance.marker.GovernanceRequest; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.router.cache.RouterRuleCache; +import org.apache.servicecomb.router.distribute.RouterDistributor; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.Environment; +import org.springframework.test.context.ContextConfiguration; + +@SpringBootTest +@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigDataApplicationContextInitializer.class) +public class RouterDistributorGlobalConfigTest { + private static final String TARGET_SERVICE_NAME = "test_server"; + + public static final String CONFIG_KEY = RouterRuleCache.ROUTE_RULE_PREFIX + TARGET_SERVICE_NAME; + + private static final String RULE_STRING = "" + + " - precedence: 1\n" + + " match:\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"02\"\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 2\n" + + " match:\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"03\"\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + + private Environment environment; + + private RouterFilter routerFilter; + + private RouterDistributor testDistributor; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Autowired + public void setRouterFilter(RouterFilter routerFilter) { + this.routerFilter = routerFilter; + } + + @Autowired + public void setTestDistributor(RouterDistributor testDistributor) { + this.testDistributor = testDistributor; + } + + public RouterDistributorGlobalConfigTest() { + } + + private final Map dynamicValues = new HashMap<>(); + + @BeforeEach + public void setUp() { + ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment; + + if (configurableEnvironment.getPropertySources().contains("testDynamicChange")) { + configurableEnvironment.getPropertySources().remove("testDynamicChange"); + } + + configurableEnvironment.getPropertySources() + .addFirst(new EnumerablePropertySource>("testDynamicChange", dynamicValues) { + @Override + public Object getProperty(String s) { + return this.getSource().get(s); + } + + @Override + public String[] getPropertyNames() { + return this.getSource().keySet().toArray(new String[0]); + } + }); + + dynamicValues.put(RouterRuleCache.GLOBAL_ROUTE_RULE_KEY, RULE_STRING); + postConfigurationChangedEvent(RouterRuleCache.GLOBAL_ROUTE_RULE_KEY); + } + + @Test + public void testUseGlobalRouteRule() { + Map headers = new HashMap<>(); + headers.put("userId", "03"); + headers.put("appId", "01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("1.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.addTags("app", "a"); + ins2.setVersion("2.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(1, resultServerList.size()); + Assertions.assertEquals("01", resultServerList.get(0).getId()); + } + + @Test + public void testUseProviderRouteRule() { + String rule = "" + + " - precedence: 1\n" + + " match:\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"03\"\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 2.0\n" + + " - precedence: 2\n" + + " match:\n" + + " headers: #header匹配\n" + + " appId:\n" + + " exact: \"01\"\n" + + " userId:\n" + + " exact: \"02\"\n" + + " route:\n" + + " - weight: 100\n" + + " tags:\n" + + " version: 1.0\n"; + dynamicValues.put(CONFIG_KEY, rule); + postConfigurationChangedEvent(CONFIG_KEY); + + Map headers = new HashMap<>(); + headers.put("userId", "03"); + headers.put("appId", "01"); + GovernanceRequest governanceRequest = new GovernanceRequest(); + governanceRequest.setHeaders(headers); + + List serverList = new ArrayList<>(); + ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); + ins1.setVersion("1.0"); + ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); + ins2.addTags("app", "a"); + ins2.setVersion("2.0"); + serverList.add(ins1); + serverList.add(ins2); + + List resultServerList = mainFilter(serverList, governanceRequest); + Assertions.assertEquals(1, resultServerList.size()); + Assertions.assertEquals("02", resultServerList.get(0).getId()); + } + + private List mainFilter(List serverList, + GovernanceRequestExtractor governanceRequestExtractor) { + return routerFilter + .getFilteredListOfServers(serverList, TARGET_SERVICE_NAME, governanceRequestExtractor, + testDistributor); + } + + private void postConfigurationChangedEvent(String changKey) { + Set changedKeys = new HashSet<>(); + changedKeys.add(changKey); + GovernanceConfigurationChangedEvent newEvent = new GovernanceConfigurationChangedEvent(changedKeys); + GovernanceEventManager.post(newEvent); + } +} diff --git a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java b/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java deleted file mode 100644 index 9d4d4489cfc..00000000000 --- a/governance/src/test/java/org/apache/servicecomb/router/RouterDistributorTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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.router; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.router.cache.RouterRuleCache; -import org.apache.servicecomb.router.distribute.RouterDistributor; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; -import org.springframework.core.env.ConfigurableEnvironment; -import org.springframework.core.env.EnumerablePropertySource; -import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@ContextConfiguration(locations = "classpath:META-INF/spring/*.xml", initializers = ConfigFileApplicationContextInitializer.class) -public class RouterDistributorTest { - private static final String TARGET_SERVICE_NAME = "test_server"; - - private static final String RULE_STRING = "" - + " - precedence: 2 #优先级\n" - + " match: #匹配策略\n" - + " source: xx #匹配某个服务名\n" - + " headers: #header匹配\n" - + " appId:\n" - + " regex: 01\n" - + " caseInsensitive: false # 是否区分大小写,默认为false,区分大小写\n" - + " userId:\n" - + " exact: 01\n" - + " route: #路由规则\n" - + " - weight: 50\n" - + " tags:\n" - + " version: 1.1\n" - + " - precedence: 1\n" - + " match:\n" - + " source: 1 #匹配某个服务名\n" - + " headers: #header匹配\n" - + " appId:\n" - + " regex: 01\n" - + " caseInsensitive: false # 是否区分大小写,默认为false,区分大小写\n" - + " userId:\n" - + " exact: 02\n" - + " route:\n" - + " - weight: 1\n" - + " tags:\n" - + " version: 1\n" - + " app: a"; - - @Autowired - private Environment environment; - - @Autowired - private RouterFilter routerFilter; - - @Autowired - private RouterDistributor testDistributor; - - private Map dynamicValues = new HashMap<>(); - - @Before - public void setUp() { - ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) environment; - - if (configurableEnvironment.getPropertySources().contains("testDynamicChange")) { - configurableEnvironment.getPropertySources().remove("testDynamicChange"); - } - - configurableEnvironment.getPropertySources() - .addFirst(new EnumerablePropertySource>("testDynamicChange", dynamicValues) { - @Override - public Object getProperty(String s) { - return this.getSource().get(s); - } - - @Override - public String[] getPropertyNames() { - return this.getSource().keySet().toArray(new String[0]); - } - }); - - dynamicValues.put(RouterRuleCache.ROUTE_RULE_PREFIX + TARGET_SERVICE_NAME, RULE_STRING); - } - - - @Test - public void testHeaderIsEmpty() { - List list = getMockList(); - List serverList = mainFilter(list, Collections.emptyMap()); - Assert.assertEquals(2, serverList.size()); - } - - @Test - public void testVersionNotMatch() { - Map headerMap = new HashMap<>(); - headerMap.put("userId", "01"); - headerMap.put("appId", "01"); - headerMap.put("format", "json"); - List list = getMockList(); - list.remove(1); - List serverList = mainFilter(list, headerMap); - Assert.assertEquals(1, serverList.size()); - Assert.assertEquals("01", serverList.get(0).getId()); - } - - @Test - public void testVersionMatch() { - Map headers = new HashMap<>(); - headers.put("userId", "01"); - headers.put("appId", "01"); - headers.put("format", "json"); - List serverList = mainFilter(getMockList(), headers); - Assert.assertEquals(1, serverList.size()); - Assert.assertEquals("02", serverList.get(0).getId()); - } - - private List getMockList() { - List serverList = new ArrayList<>(); - ServiceIns ins1 = new ServiceIns("01", TARGET_SERVICE_NAME); - ins1.setVersion("2.0"); - ServiceIns ins2 = new ServiceIns("02", TARGET_SERVICE_NAME); - ins2.addTags("app", "a"); - serverList.add(ins1); - serverList.add(ins2); - return serverList; - } - - private List mainFilter(List serverList, Map headers) { - return routerFilter - .getFilteredListOfServers(serverList, TARGET_SERVICE_NAME, headers, - testDistributor); - } -} diff --git a/governance/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java b/governance/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java index 46ee61ea32f..d4438a956a1 100644 --- a/governance/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java +++ b/governance/src/test/java/org/apache/servicecomb/router/VersionCompareUtilTest.java @@ -17,18 +17,18 @@ package org.apache.servicecomb.router; import org.apache.servicecomb.router.util.VersionCompareUtil; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; public class VersionCompareUtilTest { @Test public void testVersion() { - Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0") > 0); - Assert.assertEquals(0, VersionCompareUtil.compareVersion("0.0.0", "0.0.0")); - Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.0", "0.0.1") < 0); - Assert.assertEquals(0, VersionCompareUtil.compareVersion("0.0.0", "0.0.0.0")); - Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0.0") > 0); - Assert.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0.0") > 0); + Assertions.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0") > 0); + Assertions.assertEquals(0, VersionCompareUtil.compareVersion("0.0.0", "0.0.0")); + Assertions.assertTrue(VersionCompareUtil.compareVersion("0.0.0", "0.0.1") < 0); + Assertions.assertEquals(0, VersionCompareUtil.compareVersion("0.0.0", "0.0.0.0")); + Assertions.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0.0") > 0); + Assertions.assertTrue(VersionCompareUtil.compareVersion("0.0.1", "0.0.0.0") > 0); } } diff --git a/governance/src/test/resources/META-INF/spring/bean.xml b/governance/src/test/resources/META-INF/spring/bean.xml index 69f52375755..5ff6c6e05cc 100644 --- a/governance/src/test/resources/META-INF/spring/bean.xml +++ b/governance/src/test/resources/META-INF/spring/bean.xml @@ -18,10 +18,10 @@ - + + diff --git a/governance/src/test/resources/application.yaml b/governance/src/test/resources/application.yaml index d68c1af478c..ce981ac1ea2 100644 --- a/governance/src/test/resources/application.yaml +++ b/governance/src/test/resources/application.yaml @@ -17,10 +17,42 @@ servicecomb: matchGroup: + demo-timeLimiter: | + matches: + - apiPath: + prefix: "/timeLimiter" + demo-governanceCache: | + matches: + - apiPath: + prefix: "/governanceCache" + demo-loadbalance-random: | + matches: + - serviceName: "loadrandom" + demo-loadbalance-roundRobin: | + matches: + - serviceName: "loadroundRobin" + demo-fallback-returnNull: | + matches: + - serviceName: "returnNull" + demo-fallback-ThrowException: | + matches: + - serviceName: "ThrowException" + demo-faultInject-forceClosed: | + matches: + - serviceName: "forceClosed" + demo-allOperation: | + matches: + - apiPath: + prefix: "/" demo-rateLimiting: | matches: - apiPath: exact: "/hello" + demo-rateLimiting-servicename: | + matches: + - apiPath: + exact: "/helloServiceName" + serviceName: "srcService" wrong-name-inogred: | wrong: some demo-retry: | @@ -40,33 +72,85 @@ servicecomb: headers: x-token: exact: token + demo-bulkhead-priority: | + matches: + - apiPath: + exact: "/bulkhead" demo-bulkhead-other: | matches: - apiPath: exact: "/bulkhead" services: other:1.0 + demo-faultInjectDelay: | + matches: + - apiPath: + contains: "/faultInjectDelay" + demo-faultInjectAbort: | + matches: + - apiPath: + contains: "/faultInjectAbort" + demo-mapper: | + matches: + - apiPath: + prefix: "/mapper" + demo-mapper-query: | + matches: + - queries: + name: + exact: "bob" rateLimiting: demo-rateLimiting: | rate: 1 - wrongIngored: | + demo-rateLimiting-servicename: | + rate: 1 + wrongIgnored: | rate: 0 + identifierRateLimiting: + demo-rateLimiting: | + rate: 1 + identifier: test + demo-rateLimiting-servicename: | + rate: 1 + identifier: test + timeLimiter: + demo-timeLimiter: | + timeoutDuration: 2000 + cancelRunningFuture: true + demo-timeLimiter-other: | + timeoutDuration: 2000 + cancelRunningFuture: false + cache: + demo-governanceCache: | + ttl: 36000000 + maximumSize: 50000 + concurrencyLevel: 10 + demo-governanceCache-other: | + ttl: 666666 + maximumSize: 50000 + concurrencyLevel: 15 retry: demo-retry: | maxAttempts: 3 - wrongIngored: | + wrongIgnored: | maxAttempts: -1 circuitBreaker: demo-circuitBreaker: | minimumNumberOfCalls: 2 slidingWindowSize: 2 - slidingWindowType: count + slidingWindowType: COUNT_BASED services: myself:1.0,other - wrongIngored: | + wrongIgnored: | rules: match: demo-circuitBreaker.xx minimumNumberOfCalls: -1 bulkhead: demo-bulkhead: | + order: 1 + maxConcurrentCalls: 1 + maxWaitDuration: 3000 + services: myself:1.0 + demo-bulkhead-priority: | + order: 0 maxConcurrentCalls: 1 maxWaitDuration: 3000 services: myself:1.0 @@ -74,7 +158,141 @@ servicecomb: maxConcurrentCalls: 1 maxWaitDuration: 3000 services: other:1.0 - wrongIngored: | + wrongIgnored: | rules: match: demo-bulkhead.xx - maxWaitDuration: -1 \ No newline at end of file + maxWaitDuration: -1 + instanceIsolation: + demo-allOperation: | + minimumNumberOfCalls: 2 + slidingWindowSize: 2 + slidingWindowType: COUNT_BASED + waitDurationInOpenState: 1000 + instanceBulkhead: + demo-allOperation: | + maxConcurrentCalls: 2 + maxWaitDuration: 10 + faultInjection: + demo-fallback-ThrowException: | + type: abort + percentage: 100 + demo-fallback-returnNull: | + fallbackType: ReturnNull + type: abort + percentage: 100 + demo-faultInject-forceClosed: | + forceClosed: true + fallbackType: ReturnNull + demo-faultInjectDelay: | + delayTime: 2S + type: delay + percentage: 100 + demo-faultInjectAbort: | + type: abort + percentage: 50 + errorCode: 500 + wrongIgnored: | + delayTime: -1 + type: ERROR + faultInjection2: + demo-fallback-ThrowException: | + type: abort + percentage: 100 + loadbalance: + demo-loadbalance-random: | + rule: Random + demo-loadbalance-roundRobin: | + rule: RoundRobin + mapper: + demo-mapper: | + target: + host: 127.0.0.1 + port: 8080 + demo-mapper-query: | + target: + user-id: $Q{name} + mapper2: + demo-mapper: | + target: + host: 127.0.0.1 + port: 9090 + routeRule: + test_server1: | # 服务名 + - precedence: 1 # 优先级,数字越大,优先级越高。 + match: # 请求匹配规则。0..N个,不配置表示匹配。 + headers: # header 匹配 + region: # 如果配置了多个 header,那么所有的 header 规则都必须和请求匹配 + exact: 'providerRegion' + type: + regex: gray_[a-z]+ # java 正则表达式匹配 + route: # 路由规则 + - weight: 20 # 权重值 + tags: + version: 1.0.0 # 实例标记。满足标记条件的实例放到这一组。 + - weight: 80 # 权重值 + tags: + version: 2.0.0 # 实例标记。满足标记条件的实例放到这一组。 + + - precedence: 2 + route: + - weight: 20 + tags: + x-group: red + - weight: 80 + tags: + x-group: green + + test_server2: | # 服务名 + - precedence: 1 + route: + - weight: 20 + tags: + x-group: red + + test_server3: | # 服务名 + - precedence: 2 + match: + headers: + canary: + exact: 'canary' + route: + - weight: 20 + tags: + version: 1.0.0 + - weight: 80 + tags: + version: 2.0.0 + test_server4: | # 服务名 + - precedence: 2 + match: + headers: + canary: + exact: 'canary' + route: + - weight: 20 + tags: + version: 1.0.0 + - weight: 80 + tags: + version: 2.0.0 + fallback: + - weight: 100 + tags: + x-group: red + test_server5: | # 服务名 + - precedence: 2 + match: + headers: + canary: + exact: 'canary' + route: + - weight: 50 + tags: + x-group: red + fallback: + - weight: 50 + tags: + x-group: red + - weight: 50 + tags: + x-group: green diff --git a/handlers/handler-bizkeeper/pom.xml b/handlers/handler-bizkeeper/pom.xml deleted file mode 100644 index 5fc7bf5d216..00000000000 --- a/handlers/handler-bizkeeper/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - 4.0.0 - - org.apache.servicecomb - handlers - 2.6.0-SNAPSHOT - - - handler-bizkeeper - Java Chassis::Handlers::Bizkeeper - - - UTF-8 - - - - - org.apache.servicecomb - java-chassis-core - - - - com.netflix.hystrix - hystrix-core - - - - org.slf4j - slf4j-log4j12 - test - - - log4j - log4j - test - - - org.apache.servicecomb - foundation-metrics - - - - - diff --git a/handlers/handler-bizkeeper/readme.MD b/handlers/handler-bizkeeper/readme.MD deleted file mode 100644 index d5045ac07f6..00000000000 --- a/handlers/handler-bizkeeper/readme.MD +++ /dev/null @@ -1 +0,0 @@ -参考: hystrix: https://github.com/Netflix/Hystrix/wiki \ No newline at end of file diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BeansHolder.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BeansHolder.java deleted file mode 100644 index 41f5efa5694..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BeansHolder.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.bizkeeper; - -import java.util.List; - -import javax.inject.Inject; - -public class BeansHolder { - @Inject - private List policies; - - public void init() { - for (FallbackPolicy policy : this.policies) { - FallbackPolicyManager.addPolicy(policy); - } - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperCommand.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperCommand.java deleted file mode 100644 index a582041f2f2..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperCommand.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.hystrix.HystrixObservableCommand; -import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; - -import rx.Observable; - -/** - * 接管调用链的处理流程,处理完成后,将结果交给调用链。额外还提供了请求缓存的功能和容错/降级处理能力。 - * - */ -public abstract class BizkeeperCommand extends HystrixObservableCommand { - private static final Logger LOG = LoggerFactory.getLogger(BizkeeperCommand.class); - - private final Invocation invocation; - - private final String type; - - protected BizkeeperCommand(String type, Invocation invocation, HystrixObservableCommand.Setter setter) { - super(setter); - this.type = type; - this.invocation = invocation; - } - - @Override - protected String getCacheKey() { - if (HystrixRequestContext.isCurrentThreadInitialized()) { - StringBuilder sb = new StringBuilder(); - sb.append(this.getCommandGroup().name()); - sb.append("-"); - sb.append(this.getCommandKey().name()); - return sb.toString(); - } else { - return super.getCacheKey(); - } - } - - @Override - protected Observable resumeWithFallback() { - Throwable cause = getFailedExecutionException(); - Observable observable = Observable.create(f -> { - try { - f.onNext(FallbackPolicyManager.getFallbackResponse(type, cause, invocation)); - f.onCompleted(); - } catch (Exception e) { - LOG.warn("fallback failed due to:" + e.getMessage()); - throw e; - } - }); - return observable; - } - - @Override - protected Observable construct() { - Observable observable = Observable.create(f -> { - try { - invocation.next(resp -> { - if (isFailedResponse(resp)) { - // e should implements toString - LOG.warn("bizkeeper command {} failed due to {}", invocation.getInvocationQualifiedName(), - resp.getResult()); - f.onError(resp.getResult()); - FallbackPolicyManager.record(type, invocation, resp, false); - } else { - f.onNext(resp); - f.onCompleted(); - FallbackPolicyManager.record(type, invocation, resp, true); - } - }); - } catch (Exception e) { - LOG.warn("bizkeeper command {} execute failed due to {}", invocation.getInvocationQualifiedName(), - e.getClass().getName()); - f.onError(e); - } - }); - return observable; - } - - protected abstract boolean isFailedResponse(Response resp); -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperExceptionUtils.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperExceptionUtils.java deleted file mode 100644 index 5e496e9b71e..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperExceptionUtils.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.exception.CseException; -import org.apache.servicecomb.core.exception.ExceptionUtils; - -public class BizkeeperExceptionUtils extends ExceptionUtils { - private BizkeeperExceptionUtils() { - } - - public static final String SERVICECOMB_BIZKEEPER_FALLBACK = "servicecomb.bizkeeper.fallback"; - - static { - ERROR_DESC_MGR.register(SERVICECOMB_BIZKEEPER_FALLBACK, - "This is a fallback call from circuit breaker. " - + "\n You can add fallback logic by catching this exception. " + "\n info: operation=%s."); - } - - public static CseException createBizkeeperException(String code, Throwable cause, Object... args) { - String msg = String.format(ERROR_DESC_MGR.ensureFindValue(code), args); - return new CseException(code, msg, cause); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperHandler.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperHandler.java deleted file mode 100644 index a79741f0147..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperHandler.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.HystrixInvokable; -import com.netflix.hystrix.HystrixObservable; -import com.netflix.hystrix.strategy.HystrixPlugins; -import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook; - -import rx.Observable; - -/** - * 提供createBizkeeperCommand抽象接口来创建不同的处理链实例。 - * - */ -public abstract class BizkeeperHandler implements Handler { - private static final Logger LOG = LoggerFactory.getLogger(BizkeeperHandler.class); - - protected final String groupname; - - static { - try { - HystrixPlugins.getInstance().registerPropertiesStrategy(HystrixPropertiesStrategyExt.getInstance()); - } catch (IllegalStateException e) { - LOG.warn("Hystrix properties already registered. Dynamic configuration may not work.", e); - } - try { - HystrixPlugins.getInstance().registerCommandExecutionHook(new HystrixCommandExecutionHook() { - @Override - public Exception onExecutionError(HystrixInvokable commandInstance, Exception e) { - LOG.warn("bizkeeper execution error, info={}", ExceptionUtils.getExceptionMessageWithoutTrace(e)); - return e; //by default, just pass through - } - }); - } catch (IllegalStateException e) { - LOG.warn("HystrixCommandExecutionHook already registered.", e); - } - } - - private BizkeeperHandlerDelegate delegate; - - public BizkeeperHandler(String groupname) { - this.groupname = groupname; - delegate = new BizkeeperHandlerDelegate(this); - } - - protected abstract BizkeeperCommand createBizkeeperCommand(Invocation invocation); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) { - HystrixObservable command = delegate.createBizkeeperCommand(invocation); - - Observable observable = command.toObservable(); - observable.subscribe(asyncResp::complete, error -> { - LOG.warn("catch error in bizkeeper:" + error.getMessage()); - asyncResp.fail(invocation.getInvocationType(), error); - }, () -> { - - }); - } - - protected void setCommonProperties(Invocation invocation, HystrixCommandProperties.Setter setter) { - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperHandlerDelegate.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperHandlerDelegate.java deleted file mode 100644 index e3b755b5d06..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperHandlerDelegate.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -import com.netflix.hystrix.HystrixObservable; - -import rx.Observable; -import rx.Subscription; -import rx.subjects.ReplaySubject; - -public class BizkeeperHandlerDelegate { - - private BizkeeperHandler handler; - - public BizkeeperHandlerDelegate(BizkeeperHandler handler) { - this.handler = handler; - } - - protected HystrixObservable createBizkeeperCommand(Invocation invocation) { - if (Configuration.INSTANCE.isFallbackForce(handler.groupname, - invocation.getMicroserviceName(), - invocation.getOperationMeta().getMicroserviceQualifiedName())) { - return forceFallbackCommand(invocation); - } - return handler.createBizkeeperCommand(invocation); - } - - protected HystrixObservable forceFallbackCommand(Invocation invocation) { - return new HystrixObservable() { - @Override - public Observable observe() { - ReplaySubject subject = ReplaySubject.create(); - final Subscription sourceSubscription = toObservable().subscribe(subject); - return subject.doOnUnsubscribe(sourceSubscription::unsubscribe); - } - - @Override - public Observable toObservable() { - return Observable.create(f -> { - try { - f.onNext(FallbackPolicyManager.getFallbackResponse(handler.groupname, null, invocation)); - } catch (Exception e) { - f.onError(e); - } - }); - } - }; - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperRequestContext.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperRequestContext.java deleted file mode 100644 index d65229c5b20..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/BizkeeperRequestContext.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.bizkeeper; - -import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; - -/** - * 使用缓存功能的时候,需要首先使用BizkeeperRequestContext来初始化上下文 - * - */ -public final class BizkeeperRequestContext { - private HystrixRequestContext context; - - private BizkeeperRequestContext(HystrixRequestContext context) { - this.context = context; - } - - public static BizkeeperRequestContext initializeContext() { - return new BizkeeperRequestContext(HystrixRequestContext.initializeContext()); - } - - public void shutdown() { - this.context.shutdown(); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java deleted file mode 100644 index 22a2cfcdcd7..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CommandKey.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; - -import com.netflix.hystrix.HystrixCommandGroupKey; -import com.netflix.hystrix.HystrixCommandKey; - -/** - * 创建对应的Key值 - * - */ -public final class CommandKey { - private CommandKey() { - } - - public static HystrixCommandGroupKey toHystrixCommandGroupKey(String type, Invocation invocation) { - return CustomizeCommandGroupKey.asKey(type + "." + invocation.getOperationMeta().getMicroserviceQualifiedName(), - invocation); - } - - public static HystrixCommandKey toHystrixCommandKey(String type, Invocation invocation) { - return HystrixCommandKey.Factory - .asKey(type + "." + invocation.getOperationMeta().getMicroserviceQualifiedName()); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/Configuration.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/Configuration.java deleted file mode 100644 index 625bbdb46d5..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/Configuration.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * 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.bizkeeper; - -import com.netflix.config.DynamicPropertyFactory; - -public final class Configuration { - //isolation - private static final String ISOLATION = "servicecomb.isolation."; - - private static final String ISOLATION_TIMEOUT_IN_MILLISECONDS = "timeoutInMilliseconds"; - - private static final String ISOLATION_TIMEOUT_IN_MILLISECONDS_OLD = - ".businessKeeper.command.execution.isolation.thread.timeoutInMilliseconds"; - - private static final String ISOLATION_TIMEOUT_ENABLED = "timeout.enabled"; - - private static final String ISOLATION_MAX_CONCURRENT_REQUESTS = "maxConcurrentRequests"; - - //circuit breaker - private static final String CIRCUIT_BREAKER = "servicecomb.circuitBreaker."; - - private static final String CIRCUIT_BREAKER_ENABLED = "enabled"; - - private static final String CIRCUIT_BREAKER_FORCEOPEN = "forceOpen"; - - private static final String CIRCUIT_BREAKER_FORCECLOSED = "forceClosed"; - - private static final String CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS = "sleepWindowInMilliseconds"; - - private static final String CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD = "requestVolumeThreshold"; - - private static final String CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE = "errorThresholdPercentage"; - - // fallback - // following items only supports consumer - private static final String FALLBACK = "servicecomb.fallback."; - - private static final String FALLBACK_FORCE = "force"; - - private static final String FALLBACK_MAX_CONCURRENT_REQUESTS = "maxConcurrentRequests"; - - // fallbackpolicy - private static final String FALLBACKPOLICY = "servicecomb.fallbackpolicy."; - - private static final String FALLBACKPOLICY_POLICY = "policy"; - - public static final String FALLBACKPOLICY_POLICY_THROW = "throwexception"; - - public static final String FALLBACKPOLICY_POLICY_RETURN = "returnnull"; - - private static final int DEFAULT_ISOLATION_TIMEOUT = 30000; - - private static final int DEFAULT_MAX_CONCURRENT_REQUESTS = 1000; - - private static final int DEFAULT_SLEEP_WINDOW = 15000; - - private static final int DEFAULT_VOLUME_THRESHOLD = 20; - - private static final int DEFAULT_THRESHOLD_PERCENTAGE = 50; - - public static final Configuration INSTANCE = new Configuration(); - - private Configuration() { - - } - - public int getIsolationTimeoutInMilliseconds(String type, String microserviceName, - String qualifiedOperationName) { - int timeout; - String p = getProperty("30000", - ISOLATION + type + "." + qualifiedOperationName + "." + ISOLATION_TIMEOUT_IN_MILLISECONDS, - ISOLATION + type + "." + microserviceName + "." + ISOLATION_TIMEOUT_IN_MILLISECONDS, - ISOLATION + type + "." + ISOLATION_TIMEOUT_IN_MILLISECONDS, - // 2.0 compatible - type + "." + microserviceName + ISOLATION_TIMEOUT_IN_MILLISECONDS_OLD, - type + ".default" + ISOLATION_TIMEOUT_IN_MILLISECONDS_OLD); - try { - timeout = Integer.parseInt(p); - } catch (NumberFormatException e) { - return DEFAULT_ISOLATION_TIMEOUT; - } - if (timeout > 0) { - return timeout; - } - return DEFAULT_ISOLATION_TIMEOUT; - } - - public boolean getIsolationTimeoutEnabled(String type, String microserviceName, - String qualifiedOperationName) { - String p = getProperty("false", - ISOLATION + type + "." + qualifiedOperationName + "." + ISOLATION_TIMEOUT_ENABLED, - ISOLATION + type + "." + microserviceName + "." + ISOLATION_TIMEOUT_ENABLED, - ISOLATION + type + "." + ISOLATION_TIMEOUT_ENABLED); - return Boolean.parseBoolean(p); - } - - public int getIsolationMaxConcurrentRequests(String type, String microserviceName, - String qualifiedOperationName) { - int concurrentRequests; - String p = getProperty("1000", - ISOLATION + type + "." + qualifiedOperationName + "." + ISOLATION_MAX_CONCURRENT_REQUESTS, - ISOLATION + type + "." + microserviceName + "." + ISOLATION_MAX_CONCURRENT_REQUESTS, - ISOLATION + type + "." + ISOLATION_MAX_CONCURRENT_REQUESTS); - try { - concurrentRequests = Integer.parseInt(p); - } catch (NumberFormatException e) { - return DEFAULT_MAX_CONCURRENT_REQUESTS; - } - if (concurrentRequests > 0) { - return concurrentRequests; - } - return DEFAULT_MAX_CONCURRENT_REQUESTS; - } - - public boolean isCircuitBreakerEnabled(String type, String microserviceName, String qualifiedOperationName) { - String p = getProperty("true", - CIRCUIT_BREAKER + type + "." + qualifiedOperationName + "." + CIRCUIT_BREAKER_ENABLED, - CIRCUIT_BREAKER + type + "." + microserviceName + "." + CIRCUIT_BREAKER_ENABLED, - CIRCUIT_BREAKER + type + "." + CIRCUIT_BREAKER_ENABLED); - return Boolean.parseBoolean(p); - } - - public boolean isCircuitBreakerForceOpen(String type, String microserviceName, String qualifiedOperationName) { - String p = getProperty("false", - CIRCUIT_BREAKER + type + "." + qualifiedOperationName + "." + CIRCUIT_BREAKER_FORCEOPEN, - CIRCUIT_BREAKER + type + "." + microserviceName + "." + CIRCUIT_BREAKER_FORCEOPEN, - CIRCUIT_BREAKER + type + "." + CIRCUIT_BREAKER_FORCEOPEN); - return Boolean.parseBoolean(p); - } - - public boolean isCircuitBreakerForceClosed(String type, String microserviceName, String qualifiedOperationName) { - String p = getProperty("false", - CIRCUIT_BREAKER + type + "." + qualifiedOperationName + "." + CIRCUIT_BREAKER_FORCECLOSED, - CIRCUIT_BREAKER + type + "." + microserviceName + "." + CIRCUIT_BREAKER_FORCECLOSED, - CIRCUIT_BREAKER + type + "." + CIRCUIT_BREAKER_FORCECLOSED); - return Boolean.parseBoolean(p); - } - - public int getCircuitBreakerSleepWindowInMilliseconds(String type, String microserviceName, - String qualifiedOperationName) { - String p = getProperty("15000", - CIRCUIT_BREAKER + type + "." + qualifiedOperationName + "." - + CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, - CIRCUIT_BREAKER + type + "." + microserviceName + "." + CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, - CIRCUIT_BREAKER + type + "." + CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS); - try { - return Integer.parseInt(p); - } catch (NumberFormatException e) { - return DEFAULT_SLEEP_WINDOW; - } - } - - public int getCircuitBreakerRequestVolumeThreshold(String type, String microserviceName, - String qualifiedOperationName) { - String p = getProperty("20", - CIRCUIT_BREAKER + type + "." + qualifiedOperationName + "." - + CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, - CIRCUIT_BREAKER + type + "." + microserviceName + "." + CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, - CIRCUIT_BREAKER + type + "." + CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD); - try { - return Integer.parseInt(p); - } catch (NumberFormatException e) { - return DEFAULT_VOLUME_THRESHOLD; - } - } - - public int getCircuitBreakerErrorThresholdPercentage(String type, String microserviceName, - String qualifiedOperationName) { - String p = getProperty("50", - CIRCUIT_BREAKER + type + "." + qualifiedOperationName + "." - + CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, - CIRCUIT_BREAKER + type + "." + microserviceName + "." + CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, - CIRCUIT_BREAKER + type + "." + CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE); - try { - return Integer.parseInt(p); - } catch (NumberFormatException e) { - return DEFAULT_THRESHOLD_PERCENTAGE; - } - } - - public boolean isFallbackForce(String type, String microserviceName, String qualifiedOperationName) { - String p = getProperty("false", - FALLBACK + type + "." + qualifiedOperationName + "." + FALLBACK_FORCE, - FALLBACK + type + "." + microserviceName + "." + FALLBACK_FORCE, - FALLBACK + type + "." + FALLBACK_FORCE); - return Boolean.parseBoolean(p); - } - - public int getFallbackMaxConcurrentRequests(String type, String microserviceName, String qualifiedOperationName) { - String p = getProperty("10", - FALLBACK + type + "." + qualifiedOperationName + "." + FALLBACK_MAX_CONCURRENT_REQUESTS, - FALLBACK + type + "." + microserviceName + "." + FALLBACK_MAX_CONCURRENT_REQUESTS, - FALLBACK + type + "." + FALLBACK_MAX_CONCURRENT_REQUESTS); - try { - return Integer.parseInt(p); - } catch (NumberFormatException e) { - return DEFAULT_MAX_CONCURRENT_REQUESTS; - } - } - - public String getFallbackPolicyPolicy(String type, String microserviceName, String qualifiedOperationName) { - return getProperty(null, - FALLBACKPOLICY + type + "." + qualifiedOperationName + "." + FALLBACKPOLICY_POLICY, - FALLBACKPOLICY + type + "." + microserviceName + "." + FALLBACKPOLICY_POLICY, - FALLBACKPOLICY + type + "." + FALLBACKPOLICY_POLICY); - } - - private String getProperty(String defaultValue, String... keys) { - String property = null; - for (String key : keys) { - property = DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); - if (property != null) { - break; - } - } - - if (property != null) { - return property; - } else { - return defaultValue; - } - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ConsumerBizkeeperCommand.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ConsumerBizkeeperCommand.java deleted file mode 100644 index e43bfbd1e75..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ConsumerBizkeeperCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class ConsumerBizkeeperCommand extends BizkeeperCommand { - protected ConsumerBizkeeperCommand(String type, Invocation invocation, - com.netflix.hystrix.HystrixObservableCommand.Setter setter) { - super(type, invocation, setter); - } - - @Override - protected boolean isFailedResponse(Response resp) { - if (resp.isFailed()) { - if (InvocationException.class.isInstance(resp.getResult())) { - InvocationException e = (InvocationException) resp.getResult(); - return e.getStatusCode() == ExceptionFactory.CONSUMER_INNER_STATUS_CODE; - } else { - return true; - } - } else { - return false; - } - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ConsumerBizkeeperHandler.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ConsumerBizkeeperHandler.java deleted file mode 100644 index 28848d5be53..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ConsumerBizkeeperHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; - -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.HystrixObservableCommand; - -/** - * 客户端调用链处理流程 - * - */ -public class ConsumerBizkeeperHandler extends BizkeeperHandler { - private static final String COMMAND_GROUP = "Consumer"; - - public ConsumerBizkeeperHandler() { - super(COMMAND_GROUP); - } - - @Override - protected BizkeeperCommand createBizkeeperCommand(Invocation invocation) { - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - setCommonProperties(invocation, setter); - - BizkeeperCommand command = new ConsumerBizkeeperCommand(groupname, invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey(groupname, invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey(groupname, invocation)) - .andCommandPropertiesDefaults(setter)); - return command; - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CustomizeCommandGroupKey.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CustomizeCommandGroupKey.java deleted file mode 100644 index 79183b7189e..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/CustomizeCommandGroupKey.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; - -import com.netflix.hystrix.HystrixCommandGroupKey; -import com.netflix.hystrix.HystrixKey; -import com.netflix.hystrix.util.InternMap; - -/** - * 通过定制CommandGroupKey,目的是携带Invocation部分静态信息,便于CircutBreakerEvent获取 - */ -public class CustomizeCommandGroupKey extends HystrixKey.HystrixKeyDefault implements HystrixCommandGroupKey { - - private Invocation instance; - - public CustomizeCommandGroupKey(String key) { - super(key); - } - - private static final InternMap intern = - new InternMap( - new InternMap.ValueConstructor() { - @Override - public CustomizeCommandGroupKey create(String key) { - return new CustomizeCommandGroupKey(key); - } - }); - - public static HystrixCommandGroupKey asKey(String key, Invocation invocation) { - CustomizeCommandGroupKey result = intern.interned(key); - result.setInvocation(invocation); - return result; - } - - public void setInvocation(Invocation invocation) { - this.instance = invocation; - } - - public Invocation getInstance() { - return instance; - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicy.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicy.java deleted file mode 100644 index c394a35d4f4..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicy.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -public interface FallbackPolicy { - String name(); - - Response getFallbackResponse(Invocation invocation, Throwable error); - - default void record(Invocation invocation, Response response, boolean isSuccess) { - - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java deleted file mode 100644 index 03da31d3c3a..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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.bizkeeper; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -public class FallbackPolicyManager { - private static final Map POLICIES = new HashMap<>(); - - public static void addPolicy(FallbackPolicy policy) { - POLICIES.put(policy.name().toLowerCase(), policy); - } - - public static void record(String type, Invocation invocation, Response response, boolean isSuccess) { - FallbackPolicy policy = getPolicy(type, invocation); - if (policy != null) { - policy.record(invocation, response, isSuccess); - } - } - - public static Response getFallbackResponse(String type, Throwable error, Invocation invocation) { - FallbackPolicy policy = getPolicy(type, invocation); - if (policy != null) { - return policy.getFallbackResponse(invocation, error); - } else { - return Response.failResp(invocation.getInvocationType(), error); - } - } - - private static FallbackPolicy getPolicy(String type, Invocation invocation) { - String policyKey = Configuration.INSTANCE.getFallbackPolicyPolicy(type, - invocation.getMicroserviceName(), - invocation.getOperationMeta().getMicroserviceQualifiedName()); - FallbackPolicy policy = null; - if (policyKey != null) { - policy = POLICIES.get(policyKey.toLowerCase()); - } - return policy; - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FromCacheFallbackPolicy.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FromCacheFallbackPolicy.java deleted file mode 100644 index 2e6314b27e5..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FromCacheFallbackPolicy.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.bizkeeper; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; - -@Component -public class FromCacheFallbackPolicy implements FallbackPolicy { - private static final String POLICY_NAME = "fromCache"; - - private Map cachedResponse = new ConcurrentHashMap<>(); - - @Override - public String name() { - return POLICY_NAME; - } - - @Override - public Response getFallbackResponse(Invocation invocation, Throwable error) { - if (cachedResponse.get(invocation.getInvocationQualifiedName()) != null) { - return cachedResponse.get(invocation.getInvocationQualifiedName()); - } else { - return Response.succResp(null); - } - } - - @Override - public void record(Invocation invocation, Response response, boolean isSuccess) { - if (isSuccess) { - cachedResponse.put(invocation.getInvocationQualifiedName(), response); - } - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixCommandPropertiesExt.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixCommandPropertiesExt.java deleted file mode 100644 index 406ecf11181..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixCommandPropertiesExt.java +++ /dev/null @@ -1,553 +0,0 @@ -/** - * Copyright 2012 Netflix, Inc. - * - * Licensed 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. - */ - -// This file is forked from https://github.com/Netflix/Hystrix/blob/master/hystrix-core/src/main/java/com/netflix/hystrix/HystrixCommandProperties.java - -package org.apache.servicecomb.bizkeeper; - -import static com.netflix.hystrix.strategy.properties.HystrixPropertiesChainedProperty.forBoolean; -import static com.netflix.hystrix.strategy.properties.HystrixPropertiesChainedProperty.forInteger; -import static com.netflix.hystrix.strategy.properties.HystrixPropertiesChainedProperty.forString; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.strategy.properties.HystrixDynamicProperty; -import com.netflix.hystrix.strategy.properties.HystrixProperty; - -public class HystrixCommandPropertiesExt extends HystrixCommandProperties { - - private static final Logger LOGGER = LoggerFactory.getLogger(HystrixCommandProperties.class); - - /* defaults */ - /* package */ - // default => statisticalWindow: 10000 = 10 seconds (and default of 10 - // buckets so each bucket is 1 second) - static final Integer DEFAULT_METRICSROLLINGSTATISTICALWINDOW = 10000; - - // default => statisticalWindowBuckets: 10 = 10 buckets in a 10 second - // window so each bucket is 1 second - private static final Integer DEFAULT_METRICSROLLINGSTATISTICALWINDOWBUCKETS = 10; - - // default => statisticalWindowVolumeThreshold: 20 requests in 10 seconds - // must occur before statistics matter - private static final Integer DEFAULT_CIRCUITBREAKERREQUESTVOLUMETHRESHOLD = 20; - - // default => sleepWindow: 15000 = 15 seconds that we will sleep before trying - // again after tripping the circuit - private static final Integer DEFAULT_CIRCUITBREAKERSLEEPWINDOWINMILLISECONDS = 15000; - - // default => errorThresholdPercentage = 50 = if 50%+ of requests in 10 - // seconds are failures or latent then we will trip the circuit - private static final Integer DEFAULT_CIRCUITBREAKERERRORTHRESHOLDPERCENTAGE = 50; - - // default => forceCircuitOpen = false (we want to allow traffic) - private static final Boolean DEFAULT_CIRCUITBREAKERFORCEOPEN = false; - - /* package */ - // default => ignoreErrors = false - static final Boolean DEFAULT_CIRCUITBREAKERFORCECLOSED = false; - - // default => executionTimeoutInMilliseconds: 30000 = 30 second - private static final Integer DEFAULT_EXECUTIONTIMEOUTINMILLISECONDS = 30000; - - private static final Boolean DEFAULT_EXECUTIONTIMEOUTENABLED = false; - - private static final ExecutionIsolationStrategy DEFAULT_ISOLATIONSTRATEGY = ExecutionIsolationStrategy.SEMAPHORE; - - private static final Boolean DEFAULT_EXECUTIONISOLATIONTHREADINTERRUPTONTIMEOUT = true; - - private static final Boolean DEFAULT_METRICSROLLINGPERCENTILEENABLED = false; - - private static final Boolean DEFAULT_REQUESTCACHEENABLED = true; - - private static final Integer DEFAULT_FALLBACKISOLATIONSEMAPHOREMAXCONCURRENTREQUESTS = 10; - - private static final Boolean DEFAULT_FALLBACKENABLED = true; - - private static final Integer DEFAULT_EXECUTIONISOLATIONSEMAPHOREMAXCONCURRENTREQUESTS = 1000; - - private static final Boolean DEFAULT_REQUESTLOGENABLED = true; - - private static final Boolean DEFAULT_CIRCUITBREAKERENABLED = true; - - // default to 1 minute for RollingPercentile - private static final Integer DEFAULT_METRICSROLLINGPERCENTILEWINDOW = 60000; - - // default to 6 buckets (10 seconds each in 60 second window) - private static final Integer DEFAULT_METRICSROLLINGPERCENTILEWINDOWBUCKETS = 6; - - // default to 100 values max per bucket - private static final Integer DEFAULT_METRICSROLLINGPERCENTILEBUCKETSIZE = 100; - - // default to 1000ms as max frequency between allowing snapshots of health - // (error percentage etc) - private static final Integer DEFAULT_METRICSHEALTHSNAPSHOTINTERVALINMILLISECONDS = 1000; - - private static final int COMMAND_KEY_LENGTH = 3; - - @SuppressWarnings("unused") - private final HystrixCommandKey key; - - // number of requests that must be made within a statisticalWindow before - // open/close decisions are made using stats - private final HystrixProperty circuitBreakerRequestVolumeThreshold; - - // milliseconds after tripping circuit before allowing retry - private final HystrixProperty circuitBreakerSleepWindowInMilliseconds; - - // Whether circuit breaker should be enabled. - private final HystrixProperty circuitBreakerEnabled; - - // % of 'marks' that must be failed to trip the circuit - private final HystrixProperty circuitBreakerErrorThresholdPercentage; - - // a property to allow forcing the circuit open (stopping all requests) - private final HystrixProperty circuitBreakerForceOpen; - - // a property to allow ignoring errors and therefore never trip 'open' (ie. - // allow all traffic through) - private final HystrixProperty circuitBreakerForceClosed; - - // Whether a command should be executed in a separate thread or not. - private final HystrixProperty executionIsolationStrategy; - - // Timeout value in milliseconds for a command - private final HystrixProperty executionTimeoutInMilliseconds; - - // Whether timeout should be triggered - private final HystrixProperty executionTimeoutEnabled; - - // What thread-pool this command should run in (if running on a separate - // thread). - private final HystrixProperty executionIsolationThreadPoolKeyOverride; - - // Number of permits for execution semaphore - private final HystrixProperty executionIsolationSemaphoreMaxConcurrentRequests; - - // Number of permits for fallback semaphore - private final HystrixProperty fallbackIsolationSemaphoreMaxConcurrentRequests; - - // Whether fallback should be attempted. - private final HystrixProperty fallbackEnabled; - - // Whether an underlying Future/Thread (when runInSeparateThread == true) - // should be interrupted after a timeout - private final HystrixProperty executionIsolationThreadInterruptOnTimeout; - - // milliseconds back that will be tracked - private final HystrixProperty metricsRollingStatisticalWindowInMilliseconds; - - // number of buckets in the statisticalWindow - private final HystrixProperty metricsRollingStatisticalWindowBuckets; - - // Whether monitoring should be enabled (SLA and Tracers). - private final HystrixProperty metricsRollingPercentileEnabled; - - // number of milliseconds that will be tracked in RollingPercentile - private final HystrixProperty metricsRollingPercentileWindowInMilliseconds; - - // number of buckets percentileWindow will be divided into - private final HystrixProperty metricsRollingPercentileWindowBuckets; - - // how many values will be stored in each percentileWindowBucket - private final HystrixProperty metricsRollingPercentileBucketSize; - - // time between health snapshots - private final HystrixProperty metricsHealthSnapshotIntervalInMilliseconds; - - // whether command request logging is enabled. - private final HystrixProperty requestLogEnabled; - - // Whether request caching is enabled. - private final HystrixProperty requestCacheEnabled; - - protected HystrixCommandPropertiesExt(HystrixCommandKey key) { - this(key, HystrixCommandProperties.Setter(), "servicecomb"); - } - - protected HystrixCommandPropertiesExt(HystrixCommandKey key, HystrixCommandProperties.Setter builder) { - this(key, builder, "servicecomb"); - } - - protected HystrixCommandPropertiesExt(HystrixCommandKey key, HystrixCommandProperties.Setter builder, - String propertyPrefix) { - super(key, builder, propertyPrefix); - this.key = key; - this.circuitBreakerEnabled = getProperty(propertyPrefix, - "circuitBreaker", - key, - "enabled", - builder.getCircuitBreakerEnabled(), - DEFAULT_CIRCUITBREAKERENABLED); - this.circuitBreakerRequestVolumeThreshold = getProperty(propertyPrefix, - "circuitBreaker", - key, - "requestVolumeThreshold", - builder.getCircuitBreakerRequestVolumeThreshold(), - DEFAULT_CIRCUITBREAKERREQUESTVOLUMETHRESHOLD); - this.circuitBreakerSleepWindowInMilliseconds = getProperty(propertyPrefix, - "circuitBreaker", - key, - "sleepWindowInMilliseconds", - builder.getCircuitBreakerSleepWindowInMilliseconds(), - DEFAULT_CIRCUITBREAKERSLEEPWINDOWINMILLISECONDS); - this.circuitBreakerErrorThresholdPercentage = getProperty(propertyPrefix, - "circuitBreaker", - key, - "errorThresholdPercentage", - builder.getCircuitBreakerErrorThresholdPercentage(), - DEFAULT_CIRCUITBREAKERERRORTHRESHOLDPERCENTAGE); - this.circuitBreakerForceOpen = getProperty(propertyPrefix, - "circuitBreaker", - key, - "forceOpen", - builder.getCircuitBreakerForceOpen(), - DEFAULT_CIRCUITBREAKERFORCEOPEN); - this.circuitBreakerForceClosed = getProperty(propertyPrefix, - "circuitBreaker", - key, - "forceClosed", - builder.getCircuitBreakerForceClosed(), - DEFAULT_CIRCUITBREAKERFORCECLOSED); - this.executionIsolationStrategy = getProperty(propertyPrefix, - "isolation", - key, - "strategy", - builder.getExecutionIsolationStrategy(), - DEFAULT_ISOLATIONSTRATEGY); - this.executionTimeoutInMilliseconds = getProperty(propertyPrefix, - "isolation", - key, - "timeoutInMilliseconds", - builder.getExecutionTimeoutInMilliseconds(), - DEFAULT_EXECUTIONTIMEOUTINMILLISECONDS); - this.executionTimeoutEnabled = getProperty(propertyPrefix, - "isolation", - key, - "timeout.enabled", - builder.getExecutionTimeoutEnabled(), - DEFAULT_EXECUTIONTIMEOUTENABLED); - this.executionIsolationThreadInterruptOnTimeout = getProperty(propertyPrefix, - "isolation", - key, - "interruptOnTimeout", - builder.getExecutionIsolationThreadInterruptOnTimeout(), - DEFAULT_EXECUTIONISOLATIONTHREADINTERRUPTONTIMEOUT); - this.executionIsolationSemaphoreMaxConcurrentRequests = getProperty(propertyPrefix, - "isolation", - key, - "maxConcurrentRequests", - builder.getExecutionIsolationSemaphoreMaxConcurrentRequests(), - DEFAULT_EXECUTIONISOLATIONSEMAPHOREMAXCONCURRENTREQUESTS); - this.fallbackIsolationSemaphoreMaxConcurrentRequests = getProperty(propertyPrefix, - "fallback", - key, - "maxConcurrentRequests", - builder.getFallbackIsolationSemaphoreMaxConcurrentRequests(), - DEFAULT_FALLBACKISOLATIONSEMAPHOREMAXCONCURRENTREQUESTS); - this.fallbackEnabled = getProperty(propertyPrefix, - "fallback", - key, - "enabled", - builder.getFallbackEnabled(), - DEFAULT_FALLBACKENABLED); - this.metricsRollingStatisticalWindowInMilliseconds = getProperty(propertyPrefix, - "metrics", - key, - "rollingStats.timeInMilliseconds", - builder.getMetricsRollingStatisticalWindowInMilliseconds(), - DEFAULT_METRICSROLLINGSTATISTICALWINDOW); - this.metricsRollingStatisticalWindowBuckets = getProperty(propertyPrefix, - "metrics", - key, - "rollingStats.numBuckets", - builder.getMetricsRollingStatisticalWindowBuckets(), - DEFAULT_METRICSROLLINGSTATISTICALWINDOWBUCKETS); - this.metricsRollingPercentileEnabled = getProperty(propertyPrefix, - "metrics", - key, - "rollingPercentile.enabled", - builder.getMetricsRollingPercentileEnabled(), - DEFAULT_METRICSROLLINGPERCENTILEENABLED); - this.metricsRollingPercentileWindowInMilliseconds = getProperty(propertyPrefix, - "metrics", - key, - "rollingPercentile.timeInMilliseconds", - builder.getMetricsRollingPercentileWindowInMilliseconds(), - DEFAULT_METRICSROLLINGPERCENTILEWINDOW); - this.metricsRollingPercentileWindowBuckets = getProperty(propertyPrefix, - "metrics", - key, - "rollingPercentile.numBuckets", - builder.getMetricsRollingPercentileWindowBuckets(), - DEFAULT_METRICSROLLINGPERCENTILEWINDOWBUCKETS); - this.metricsRollingPercentileBucketSize = getProperty(propertyPrefix, - "metrics", - key, - "rollingPercentile.bucketSize", - builder.getMetricsRollingPercentileBucketSize(), - DEFAULT_METRICSROLLINGPERCENTILEBUCKETSIZE); - this.metricsHealthSnapshotIntervalInMilliseconds = getProperty(propertyPrefix, - "metrics", - key, - "healthSnapshot.intervalInMilliseconds", - builder.getMetricsHealthSnapshotIntervalInMilliseconds(), - DEFAULT_METRICSHEALTHSNAPSHOTINTERVALINMILLISECONDS); - this.requestCacheEnabled = getProperty(propertyPrefix, - "requestCache", - key, - "enabled", - builder.getRequestCacheEnabled(), - DEFAULT_REQUESTCACHEENABLED); - this.requestLogEnabled = getProperty(propertyPrefix, - "requestLog", - key, - "enabled", - builder.getRequestLogEnabled(), - DEFAULT_REQUESTLOGENABLED); - - // threadpool doesn't have a global override, only instance level makes - // sense - this.executionIsolationThreadPoolKeyOverride = forString() - .add(propertyPrefix + ".command." + key.name() + ".threadPoolKeyOverride", null) - .build(); - } - - @Override - public HystrixProperty circuitBreakerEnabled() { - return circuitBreakerEnabled; - } - - @Override - public HystrixProperty circuitBreakerErrorThresholdPercentage() { - return circuitBreakerErrorThresholdPercentage; - } - - @Override - public HystrixProperty circuitBreakerForceClosed() { - return circuitBreakerForceClosed; - } - - @Override - public HystrixProperty circuitBreakerForceOpen() { - return circuitBreakerForceOpen; - } - - @Override - public HystrixProperty circuitBreakerRequestVolumeThreshold() { - return circuitBreakerRequestVolumeThreshold; - } - - @Override - public HystrixProperty circuitBreakerSleepWindowInMilliseconds() { - return circuitBreakerSleepWindowInMilliseconds; - } - - @Override - public HystrixProperty executionIsolationSemaphoreMaxConcurrentRequests() { - return executionIsolationSemaphoreMaxConcurrentRequests; - } - - @Override - public HystrixProperty executionIsolationStrategy() { - return executionIsolationStrategy; - } - - @Override - public HystrixProperty executionIsolationThreadInterruptOnTimeout() { - return executionIsolationThreadInterruptOnTimeout; - } - - @Override - public HystrixProperty executionIsolationThreadPoolKeyOverride() { - return executionIsolationThreadPoolKeyOverride; - } - - @Override - @Deprecated // prefer {@link #executionTimeoutInMilliseconds} - public HystrixProperty executionIsolationThreadTimeoutInMilliseconds() { - return executionTimeoutInMilliseconds; - } - - @Override - public HystrixProperty executionTimeoutInMilliseconds() { - return executionIsolationThreadTimeoutInMilliseconds(); - } - - @Override - public HystrixProperty executionTimeoutEnabled() { - return executionTimeoutEnabled; - } - - @Override - public HystrixProperty fallbackIsolationSemaphoreMaxConcurrentRequests() { - return fallbackIsolationSemaphoreMaxConcurrentRequests; - } - - @Override - public HystrixProperty fallbackEnabled() { - return fallbackEnabled; - } - - @Override - public HystrixProperty metricsHealthSnapshotIntervalInMilliseconds() { - return metricsHealthSnapshotIntervalInMilliseconds; - } - - @Override - public HystrixProperty metricsRollingPercentileBucketSize() { - return metricsRollingPercentileBucketSize; - } - - @Override - public HystrixProperty metricsRollingPercentileEnabled() { - return metricsRollingPercentileEnabled; - } - - @Override - @Deprecated - public HystrixProperty metricsRollingPercentileWindow() { - return metricsRollingPercentileWindowInMilliseconds; - } - - @Override - public HystrixProperty metricsRollingPercentileWindowInMilliseconds() { - return metricsRollingPercentileWindowInMilliseconds; - } - - @Override - public HystrixProperty metricsRollingPercentileWindowBuckets() { - return metricsRollingPercentileWindowBuckets; - } - - @Override - public HystrixProperty metricsRollingStatisticalWindowInMilliseconds() { - return metricsRollingStatisticalWindowInMilliseconds; - } - - @Override - public HystrixProperty metricsRollingStatisticalWindowBuckets() { - return metricsRollingStatisticalWindowBuckets; - } - - @Override - public HystrixProperty requestCacheEnabled() { - return requestCacheEnabled; - } - - @Override - public HystrixProperty requestLogEnabled() { - return requestLogEnabled; - } - - private HystrixProperty getProperty(String propertyPrefix, String command, - HystrixCommandKey key, String instanceProperty, ExecutionIsolationStrategy builderOverrideValue, - ExecutionIsolationStrategy defaultValue) { - return new ExecutionIsolationStrategyHystrixProperty(builderOverrideValue, key, propertyPrefix, command, - defaultValue, instanceProperty); - } - - private static final class ExecutionIsolationStrategyHystrixProperty - implements HystrixProperty { - private final HystrixDynamicProperty property; - - private volatile ExecutionIsolationStrategy value; - - private final ExecutionIsolationStrategy defaultValue; - - private ExecutionIsolationStrategyHystrixProperty(ExecutionIsolationStrategy builderOverrideValue, - HystrixCommandKey key, String propertyPrefix, String command, ExecutionIsolationStrategy defaultValue, - String instanceProperty) { - this.defaultValue = defaultValue; - String overrideValue = null; - if (builderOverrideValue != null) { - overrideValue = builderOverrideValue.name(); - } - property = forString() - .add(propertyPrefix + "." + command + "." + key.name() + "." + instanceProperty, null) - .add(propertyPrefix + "." + command + "." + serviceKey(key.name()) + "." + instanceProperty, - overrideValue) - .add(propertyPrefix + "." + command + "." + typeKey(key.name()) + "." + instanceProperty, - defaultValue.name()) - .build(); - - // initialize the enum value from the property - parseProperty(); - - // use a callback to handle changes so we only handle the parse cost - // on updates rather than every fetch - // when the property value changes we'll update the value - property.addCallback(this::parseProperty); - } - - @Override - public ExecutionIsolationStrategy get() { - return value; - } - - private void parseProperty() { - try { - value = ExecutionIsolationStrategy.valueOf(property.get()); - } catch (Exception e) { - LOGGER.error("Unable to derive ExecutionIsolationStrategy from property value: " + property.get(), e); - // use the default value - value = defaultValue; - } - } - } - - private static String serviceKey(String key) { - String[] keyparts = key.split("\\.", COMMAND_KEY_LENGTH); - if (keyparts.length == COMMAND_KEY_LENGTH) { - return keyparts[0] + "." + keyparts[1]; - } - return key; - } - - private static String typeKey(String key) { - int index = key.indexOf("."); - if (index > 0) { - return key.substring(0, index); - } - return key; - } - - private HystrixProperty getProperty(String propertyPrefix, String command, HystrixCommandKey key, - String instanceProperty, Integer builderOverrideValue, - Integer defaultValue) { - return forInteger() - .add(propertyPrefix + "." + command + "." + key.name() + "." + instanceProperty, null) - .add(propertyPrefix + "." + command + "." + serviceKey(key.name()) + "." + instanceProperty, - null) - .add(propertyPrefix + "." + command + "." + typeKey(key.name()) + "." + instanceProperty, - builderOverrideValue == null ? defaultValue : builderOverrideValue) - .build(); - } - - private HystrixProperty getProperty(String propertyPrefix, String command, HystrixCommandKey key, - String instanceProperty, Boolean builderOverrideValue, Boolean defaultValue) { - return forBoolean() - .add(propertyPrefix + "." + command + "." + key.name() + "." + instanceProperty, null) - .add(propertyPrefix + "." + command + "." + serviceKey(key.name()) + "." + instanceProperty, - null) - .add(propertyPrefix + "." + command + "." + typeKey(key.name()) + "." + instanceProperty, - builderOverrideValue == null ? defaultValue : builderOverrideValue) - .build(); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixPropertiesStrategyExt.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixPropertiesStrategyExt.java deleted file mode 100644 index c862d119548..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/HystrixPropertiesStrategyExt.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.bizkeeper; - -import java.util.Map; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; - -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.HystrixCommandProperties.Setter; -import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy; - -/** - * 定制HystrixPropertiesStrategy。 配置需要支持动态生效和调整, 默认的hystrix实现会根据CommonKey进行缓存。 - * CircuitBreake需要统计并记录请求数据,需要缓存并保证每个commandKey对应一个Breaker;单纯清理CommandKey无法动态生效。 - * 参考:HystrixCircuitBreaker.Factory.getInstance(commandKey, groupKey, - * properties, metrics) - * - */ -public final class HystrixPropertiesStrategyExt extends HystrixPropertiesStrategy { - - private static final HystrixPropertiesStrategyExt INSTANCE = new HystrixPropertiesStrategyExt(); - - private final Map commandPropertiesMap = new ConcurrentHashMapEx<>(); - - private HystrixPropertiesStrategyExt() { - } - - public static HystrixPropertiesStrategyExt getInstance() { - return INSTANCE; - } - - @Override - public HystrixCommandProperties getCommandProperties(HystrixCommandKey commandKey, Setter builder) { - return commandPropertiesMap.computeIfAbsent(commandKey.name(), - key -> new HystrixCommandPropertiesExt(commandKey, builder)); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ProviderBizkeeperCommand.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ProviderBizkeeperCommand.java deleted file mode 100644 index 4ef5a629e3c..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ProviderBizkeeperCommand.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class ProviderBizkeeperCommand extends BizkeeperCommand { - protected ProviderBizkeeperCommand(String type, Invocation invocation, - com.netflix.hystrix.HystrixObservableCommand.Setter setter) { - super(type, invocation, setter); - } - - @Override - protected boolean isFailedResponse(Response resp) { - if (resp.isFailed()) { - if (InvocationException.class.isInstance(resp.getResult())) { - InvocationException e = (InvocationException) resp.getResult(); - return e.getStatusCode() == ExceptionFactory.PRODUCER_INNER_STATUS_CODE; - } else { - return true; - } - } else { - return false; - } - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ProviderBizkeeperHanlder.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ProviderBizkeeperHanlder.java deleted file mode 100644 index 8f688a48aa4..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ProviderBizkeeperHanlder.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; - -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.HystrixObservableCommand; - -/** - * 服务端调用链处理流程 - * - */ -public class ProviderBizkeeperHanlder extends BizkeeperHandler { - private static final String COMMAND_GROUP = "Provider"; - - public ProviderBizkeeperHanlder() { - super(COMMAND_GROUP); - } - - @Override - protected BizkeeperCommand createBizkeeperCommand(Invocation invocation) { - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(false) - .withRequestLogEnabled(false); - setCommonProperties(invocation, setter); - - BizkeeperCommand command = new ProviderBizkeeperCommand(groupname, invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey(groupname, invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey(groupname, invocation)) - .andCommandPropertiesDefaults(setter)); - return command; - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ReturnNullFallbackPolicy.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ReturnNullFallbackPolicy.java deleted file mode 100644 index 1b4d6e0f430..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ReturnNullFallbackPolicy.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; - -@Component -public class ReturnNullFallbackPolicy implements FallbackPolicy { - private static final String POLICY_NAME = "returnNull"; - - @Override - public String name() { - return POLICY_NAME; - } - - @Override - public Response getFallbackResponse(Invocation invocation, Throwable error) { - return Response.succResp(null); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ThrowExceptionFallbackPolicy.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ThrowExceptionFallbackPolicy.java deleted file mode 100644 index 1c74e4a4dba..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/ThrowExceptionFallbackPolicy.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.springframework.stereotype.Component; - -@Component -public class ThrowExceptionFallbackPolicy implements FallbackPolicy { - private static final String POLICY_NAME = "throwException"; - - @Override - public String name() { - return POLICY_NAME; - } - - @Override - public Response getFallbackResponse(Invocation invocation, Throwable error) { - return Response.failResp(invocation.getInvocationType(), - BizkeeperExceptionUtils - .createBizkeeperException(BizkeeperExceptionUtils.SERVICECOMB_BIZKEEPER_FALLBACK, - error, - invocation.getOperationMeta().getMicroserviceQualifiedName())); - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEvent.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEvent.java deleted file mode 100644 index c9f7a8ed898..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEvent.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.bizkeeper.event; - - -import org.apache.servicecomb.bizkeeper.CustomizeCommandGroupKey; -import org.apache.servicecomb.foundation.common.event.AlarmEvent; - -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixCommandMetrics; - -public class CircutBreakerEvent extends AlarmEvent { - - private String role; - - private String microservice; - - private String schema; - - private String operation; - - //当前总请求数 - private long currentTotalRequest; - - //当前请求出错计数 - private long currentErrorCount; - - //当前请求出错百分比 - private long currentErrorPercentage; - - private int requestVolumeThreshold; - - private int sleepWindowInMilliseconds; - - private int errorThresholdPercentage; - - public CircutBreakerEvent(HystrixCommandKey commandKey, Type type) { - super(type); - HystrixCommandMetrics hystrixCommandMetrics = HystrixCommandMetrics.getInstance(commandKey); - if (hystrixCommandMetrics != null) { - if (hystrixCommandMetrics.getCommandGroup() instanceof CustomizeCommandGroupKey) { - CustomizeCommandGroupKey customCommandGroupKey = - (CustomizeCommandGroupKey) hystrixCommandMetrics.getCommandGroup(); - this.microservice = customCommandGroupKey.getInstance().getMicroserviceName(); - this.role = customCommandGroupKey.getInstance().getInvocationType().name(); - this.schema = customCommandGroupKey.getInstance().getSchemaId(); - this.operation = customCommandGroupKey.getInstance().getOperationName(); - } - this.currentTotalRequest = hystrixCommandMetrics.getHealthCounts().getTotalRequests(); - this.currentErrorPercentage = hystrixCommandMetrics.getHealthCounts().getErrorCount(); - this.currentErrorCount = hystrixCommandMetrics.getHealthCounts().getErrorPercentage(); - this.requestVolumeThreshold = hystrixCommandMetrics.getProperties().circuitBreakerRequestVolumeThreshold().get(); - this.sleepWindowInMilliseconds = - hystrixCommandMetrics.getProperties().circuitBreakerSleepWindowInMilliseconds().get(); - this.errorThresholdPercentage = - hystrixCommandMetrics.getProperties().circuitBreakerErrorThresholdPercentage().get(); - } - } - - public String getRole() { - return role; - } - - public String getMicroservice() { - return microservice; - } - - public String getSchema() { - return schema; - } - - public String getOperation() { - return operation; - } - - public long getCurrentTotalRequest() { - return currentTotalRequest; - } - - public long getCurrentErrorCount() { - return currentErrorCount; - } - - public long getCurrentErrorPercentage() { - return currentErrorPercentage; - } - - public int getRequestVolumeThreshold() { - return requestVolumeThreshold; - } - - public int getSleepWindowInMilliseconds() { - return sleepWindowInMilliseconds; - } - - public int getErrorThresholdPercentage() { - return errorThresholdPercentage; - } -} diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEventNotifier.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEventNotifier.java deleted file mode 100644 index 3b47b5f204d..00000000000 --- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/event/CircutBreakerEventNotifier.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.bizkeeper.event; - -import java.util.concurrent.atomic.AtomicBoolean; - -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.event.AlarmEvent.Type; - -import com.google.common.eventbus.EventBus; -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixEventType; -import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier; - -public class CircutBreakerEventNotifier extends HystrixEventNotifier { - - /** - * 使用circuitFlag来记录被熔断的接口 - */ - private ConcurrentHashMapEx circuitFlag = new ConcurrentHashMapEx<>(); - - EventBus eventBus = EventManager.getEventBus(); - - @Override - public void markEvent(HystrixEventType eventType, HystrixCommandKey key) { - String keyName = key.name(); - AtomicBoolean flag = circuitFlag.computeIfAbsent(keyName, k -> new AtomicBoolean()); - switch (eventType) { - case SHORT_CIRCUITED: - if (flag.compareAndSet(false, true)) { - eventBus.post(new CircutBreakerEvent(key, Type.OPEN)); - } - break; - - case SUCCESS: - if (flag.compareAndSet(true, false)) { - eventBus.post(new CircutBreakerEvent(key, Type.CLOSE)); - } - break; - - default: - break; - } - } -} diff --git a/handlers/handler-bizkeeper/src/main/resources/META-INF/spring/cse.bean.xml b/handlers/handler-bizkeeper/src/main/resources/META-INF/spring/cse.bean.xml deleted file mode 100644 index a362a92fb5e..00000000000 --- a/handlers/handler-bizkeeper/src/main/resources/META-INF/spring/cse.bean.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - diff --git a/handlers/handler-bizkeeper/src/main/resources/config/cse.handler.xml b/handlers/handler-bizkeeper/src/main/resources/config/cse.handler.xml deleted file mode 100644 index 4253c44d825..00000000000 --- a/handlers/handler-bizkeeper/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/handlers/handler-bizkeeper/src/main/resources/hystrix-plugins.properties b/handlers/handler-bizkeeper/src/main/resources/hystrix-plugins.properties deleted file mode 100644 index 74eb50f74e7..00000000000 --- a/handlers/handler-bizkeeper/src/main/resources/hystrix-plugins.properties +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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. -# -hystrix.plugin.HystrixEventNotifier.implementation=org.apache.servicecomb.bizkeeper.event.CircutBreakerEventNotifier diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java deleted file mode 100644 index 9629d32c799..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperCommand.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.HystrixObservableCommand; -import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; - -import rx.Observable; - -public class TestBizkeeperCommand { - - @Test - public void testGetCacheKeyProvider() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ProviderBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - String str = bizkeeperCommand.getCacheKey(); - Assert.assertNull(str); - - Response resp = Mockito.mock(Response.class); - Mockito.when(resp.isFailed()).thenReturn(false); - Assert.assertEquals(false, bizkeeperCommand.isFailedResponse(resp)); - Mockito.when(resp.isFailed()).thenReturn(true); - InvocationException excp = Mockito.mock(InvocationException.class); - Mockito.when(resp.getResult()).thenReturn(excp); - Mockito.when(excp.getStatusCode()).thenReturn(400); - Assert.assertEquals(false, bizkeeperCommand.isFailedResponse(resp)); - Mockito.when(resp.getResult()).thenReturn(excp); - Mockito.when(excp.getStatusCode()).thenReturn(590); - Assert.assertEquals(true, bizkeeperCommand.isFailedResponse(resp)); - } - - @Test - public void testResumeWithFallbackProvider() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ProviderBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - Observable observe = bizkeeperCommand.resumeWithFallback(); - Assert.assertNotNull(observe); - } - - @Test - public void testConstructProvider() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ProviderBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - Observable response = bizkeeperCommand.construct(); - Assert.assertNotNull(response); - } - - @Test - public void testGetCacheKeyWithContextInitializedProvider() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ProviderBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - HystrixRequestContext.initializeContext(); - String cacheKey = bizkeeperCommand.getCacheKey(); - Assert.assertNotNull(cacheKey); - } - - @Test - public void testGetCacheKeyConsumer() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ConsumerBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - String str = bizkeeperCommand.getCacheKey(); - Assert.assertNull(str); - - Response resp = Mockito.mock(Response.class); - Mockito.when(resp.isFailed()).thenReturn(false); - Assert.assertEquals(false, bizkeeperCommand.isFailedResponse(resp)); - Mockito.when(resp.isFailed()).thenReturn(true); - InvocationException excp = Mockito.mock(InvocationException.class); - Mockito.when(resp.getResult()).thenReturn(excp); - Mockito.when(excp.getStatusCode()).thenReturn(400); - Assert.assertEquals(false, bizkeeperCommand.isFailedResponse(resp)); - Mockito.when(resp.getResult()).thenReturn(excp); - Mockito.when(excp.getStatusCode()).thenReturn(490); - Assert.assertEquals(true, bizkeeperCommand.isFailedResponse(resp)); - } - - @Test - public void testResumeWithFallbackConsumer() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ConsumerBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - Observable observe = bizkeeperCommand.resumeWithFallback(); - Assert.assertNotNull(observe); - } - - @Test - public void testConstructConsumer() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ConsumerBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - Observable response = bizkeeperCommand.construct(); - Assert.assertNotNull(response); - } - - @Test - public void testGetCacheKeyWithContextInitializedConsumer() { - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ConsumerBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - - HystrixRequestContext.initializeContext(); - String cacheKey = bizkeeperCommand.getCacheKey(); - Assert.assertNotNull(cacheKey); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperExceptionUtils.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperExceptionUtils.java deleted file mode 100644 index 294b33d47d1..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperExceptionUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.exception.CseException; -import org.junit.Assert; -import org.junit.Test; - -public class TestBizkeeperExceptionUtils { - - @Test - public void testCreateBizkeeperException() { - Assert.assertEquals("servicecomb.bizkeeper.fallback", BizkeeperExceptionUtils.SERVICECOMB_BIZKEEPER_FALLBACK); - CseException cseException = BizkeeperExceptionUtils.createBizkeeperException("servicecomb.bizkeeper.fallback", - new Throwable(), - "ARGS"); - Assert.assertNotNull(cseException); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperHandler.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperHandler.java deleted file mode 100644 index 9f96eaba12b..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperHandler.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.InvocationType; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import com.netflix.hystrix.HystrixCommandProperties; -import com.netflix.hystrix.HystrixObservableCommand; -import com.netflix.hystrix.strategy.HystrixPlugins; - -public class TestBizkeeperHandler extends BizkeeperHandler { - - BizkeeperHandler bizkeeperHandler = null; - - private static final String GROUP_NAME = "Group_Name"; - - Invocation invocation = null; - - AsyncResponse asyncResp = null; - - public TestBizkeeperHandler() { - super(GROUP_NAME); - } - - @Before - public void setUp() throws Exception { - bizkeeperHandler = new TestBizkeeperHandler(); - invocation = Mockito.mock(Invocation.class); - asyncResp = Mockito.mock(AsyncResponse.class); - - FallbackPolicyManager.addPolicy(new ReturnNullFallbackPolicy()); - FallbackPolicyManager.addPolicy(new ThrowExceptionFallbackPolicy()); - FallbackPolicyManager.addPolicy(new FromCacheFallbackPolicy()); - } - - @After - public void tearDown() throws Exception { - bizkeeperHandler = null; - invocation = null; - asyncResp = null; - } - - @Test - public void testHandleWithException() { - boolean validAssert; - HystrixPlugins.reset(); - try { - validAssert = true; - bizkeeperHandler.handle(invocation, asyncResp); - } catch (Exception e) { - validAssert = false; - } - Assert.assertFalse(validAssert); - } - - @Test - public void testHandle() { - boolean validAssert; - - try { - Assert.assertNotNull(bizkeeperHandler); - Mockito.when(invocation.getMicroserviceName()).thenReturn("test1"); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - validAssert = true; - - bizkeeperHandler.handle(invocation, asyncResp); - } catch (Exception exce) { - validAssert = false; - } - Assert.assertTrue(validAssert); - } - - @Test - public void testSetCommonProperties() { - boolean validAssert; - try { - validAssert = true; - HystrixPlugins.reset(); - HystrixCommandProperties.Setter setter = Mockito.mock(HystrixCommandProperties.Setter.class); - bizkeeperHandler.setCommonProperties(invocation, setter); - } catch (Exception e) { - validAssert = false; - } - Assert.assertTrue(validAssert); - } - - @Override - protected BizkeeperCommand createBizkeeperCommand(Invocation invocation) { - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false); - - BizkeeperCommand bizkeeperCommand = new ConsumerBizkeeperCommand("groupname", invocation, - HystrixObservableCommand.Setter - .withGroupKey(CommandKey.toHystrixCommandGroupKey("groupname", invocation)) - .andCommandKey(CommandKey.toHystrixCommandKey("groupname", invocation)) - .andCommandPropertiesDefaults(setter)); - return bizkeeperCommand; - } - - @Test - public void testHandleForceThrowException() throws Exception { - Mockito.when(invocation.getMicroserviceName()).thenReturn("testHandleForceThrowException"); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()) - .thenReturn("testHandleForceThrowException"); - System.setProperty("servicecomb.fallback.Group_Name.testHandleForceThrowException.force", "true"); - System.setProperty("servicecomb.fallbackpolicy.Group_Name.testHandleForceThrowException.policy", "throwexception"); - bizkeeperHandler.handle(invocation, f -> { - Assert.assertTrue(f.isFailed()); - }); - } - - @Test - public void testHandleForceReturnnull() throws Exception { - Mockito.when(invocation.getMicroserviceName()).thenReturn("testHandleForceReturnnull"); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()) - .thenReturn("testHandleForceReturnnull"); - System.setProperty("servicecomb.fallback.Group_Name.testHandleForceReturnnull.force", "true"); - System.setProperty("servicecomb.fallbackpolicy.Group_Name.testHandleForceReturnnull.policy", "returnnull"); - bizkeeperHandler.handle(invocation, f -> { - Assert.assertTrue(f.isSucceed()); - Assert.assertNull(f.getResult()); - }); - } - - @Test - public void testHandleInError() throws Exception { - Mockito.when(invocation.getMicroserviceName()).thenReturn("testHandleInError"); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()) - .thenReturn("testHandleInError"); - FallbackPolicy policy = Mockito.mock(FallbackPolicy.class); - Mockito.when(policy.name()).thenReturn("throwException"); - Mockito.when(policy.getFallbackResponse(Mockito.any(Invocation.class), Mockito.any(null))) - .thenThrow(new RuntimeException()); - FallbackPolicyManager.addPolicy(policy); - System.setProperty("servicecomb.fallbackpolicy.groupname.testHandleInError.policy", "throwException"); - Mockito.doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) { - AsyncResponse asyncRsp = invocation.getArgumentAt(0, AsyncResponse.class); - asyncRsp.fail(InvocationType.CONSUMER, new Exception("testHandleInError")); - return null; - } - }).when(invocation).next(Mockito.any(AsyncResponse.class)); - bizkeeperHandler.handle(invocation, f -> { - Assert.assertTrue(f.isFailed()); - }); - } - - @Test - public void testHandlNextException() throws Exception { - Mockito.when(invocation.getMicroserviceName()).thenReturn("testHandlNextException"); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()) - .thenReturn("testHandlNextException"); - Mockito.doThrow(new Exception("testHandlNextException")).when(invocation).next(Mockito.any(AsyncResponse.class)); - bizkeeperHandler.handle(invocation, f -> { - Assert.assertTrue(f.isFailed()); - }); - } - - @Test - public void testHandleSuccess() throws Exception { - Mockito.when(invocation.getMicroserviceName()).thenReturn("testHandleSuccess"); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()) - .thenReturn("testHandleSuccess"); - Mockito.doAnswer(new Answer() { - @Override - public Void answer(InvocationOnMock invocation) { - AsyncResponse asyncRsp = invocation.getArgumentAt(0, AsyncResponse.class); - asyncRsp.success(""); - return null; - } - }).when(invocation).next(Mockito.any(AsyncResponse.class)); - bizkeeperHandler.handle(invocation, f -> { - Assert.assertTrue(f.isSucceed()); - }); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperRequestContext.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperRequestContext.java deleted file mode 100644 index d0fc7a92f81..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestBizkeeperRequestContext.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.bizkeeper; - -import org.junit.Assert; -import org.junit.Test; - -/** - * - * - */ -public class TestBizkeeperRequestContext { - - @Test - public void testInitializeContext() { - - BizkeeperRequestContext bizkeeperRequestContext = BizkeeperRequestContext.initializeContext(); - Assert.assertNotNull(bizkeeperRequestContext); - } - - @Test - public void testShutdown() { - BizkeeperRequestContext bizkeeperRequestContext = BizkeeperRequestContext.initializeContext(); - boolean validAssert; - - try { - bizkeeperRequestContext.shutdown(); - validAssert = true; - } catch (Exception e) { - validAssert = false; - } - - Assert.assertTrue(validAssert); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCommandKey.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCommandKey.java deleted file mode 100644 index 29c03caa98d..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCommandKey.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.hystrix.HystrixCommandGroupKey; -import com.netflix.hystrix.HystrixCommandKey; - -/** - * - * - */ -public class TestCommandKey { - - @Test - public void testToHystrixCommandGroupKey() { - Invocation invocation = Mockito.mock(Invocation.class); - - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - Assert.assertNotNull(invocation); - HystrixCommandGroupKey hystrixCommandGroupKey = CommandKey.toHystrixCommandGroupKey("groupname", invocation); - Assert.assertNotNull(hystrixCommandGroupKey); - } - - @Test - public void testToHystrixCommandKey() { - - Invocation invocation = Mockito.mock(Invocation.class); - - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - Assert.assertNotNull(invocation); - HystrixCommandKey hystrixCommandGroupKey = CommandKey.toHystrixCommandKey("groupname", invocation); - Assert.assertNotNull(hystrixCommandGroupKey); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestConfiguration.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestConfiguration.java deleted file mode 100644 index c892227932e..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestConfiguration.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.bizkeeper; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.junit.Test; -import org.mockito.Mockito; - -public class TestConfiguration { - @Test - public void testConfiguration() { - - assertNotNull(Configuration.INSTANCE); - assertEquals("returnnull", Configuration.FALLBACKPOLICY_POLICY_RETURN); - assertEquals("throwexception", Configuration.FALLBACKPOLICY_POLICY_THROW); - - Configuration c = Configuration.INSTANCE; - Invocation invocation = Mockito.mock(Invocation.class); - String test2 = invocation.getMicroserviceName(); - - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceName()).thenReturn("testqualify"); - - int res = c.getIsolationTimeoutInMilliseconds("groupname", test2, "testqualify"); - assertEquals(30000, res); - boolean b1 = c.getIsolationTimeoutEnabled("groupname", test2, "testqualify"); - assertFalse(b1); - int res1 = c.getIsolationMaxConcurrentRequests("groupname", test2, "testqualify"); - assertEquals(1000, res1); - boolean b2 = c.isCircuitBreakerEnabled("groupname", test2, "testqualify"); - assertTrue(b2); - String str = c.getFallbackPolicyPolicy("groupname", test2, "testqualify"); - // no need to give default value now - assertEquals(null, str); - - assertFalse(c.isCircuitBreakerForceOpen("groupname", test2, "testqualify")); - assertFalse(c.isCircuitBreakerForceClosed("groupname", test2, "testqualify")); - assertEquals(15000, c.getCircuitBreakerSleepWindowInMilliseconds("groupname", test2, "testqualify")); - assertEquals(20, c.getCircuitBreakerRequestVolumeThreshold("groupname", test2, "testqualify")); - assertEquals(50, c.getCircuitBreakerErrorThresholdPercentage("groupname", test2, "testqualify")); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestConsumerBizkeeperHandler.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestConsumerBizkeeperHandler.java deleted file mode 100644 index b50a5d0e8a3..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestConsumerBizkeeperHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.hystrix.strategy.HystrixPlugins; - -/** - * - * - */ -public class TestConsumerBizkeeperHandler { - - @Test - public void testCreateBizkeeperCommand() { - HystrixPlugins.reset(); - ConsumerBizkeeperHandler consumerBizkeeperHandler = new ConsumerBizkeeperHandler(); - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - - CommandKey.toHystrixCommandGroupKey("groupname", invocation); - CommandKey.toHystrixCommandKey("groupname", invocation); - BizkeeperCommand command = consumerBizkeeperHandler.createBizkeeperCommand(invocation); - Assert.assertNotNull(command); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCustomCommandGroupKey.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCustomCommandGroupKey.java deleted file mode 100644 index 9bcf64eaa4b..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestCustomCommandGroupKey.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -public class TestCustomCommandGroupKey { - @Test - public void testToHystrixCommandGroupKey() { - Invocation invocation = Mockito.mock(Invocation.class); - CustomizeCommandGroupKey customizeCommandGroupKey = - (CustomizeCommandGroupKey) CustomizeCommandGroupKey.asKey("key", invocation); - Assert.assertEquals(invocation, customizeCommandGroupKey.getInstance()); - } - - @Test - public void testOOM() { - Invocation invocation1 = Mockito.mock(Invocation.class); - Invocation invocation2 = Mockito.mock(Invocation.class); - CustomizeCommandGroupKey customizeCommandGroupKey1 = - (CustomizeCommandGroupKey) CustomizeCommandGroupKey.asKey("key", invocation1); - CustomizeCommandGroupKey customizeCommandGroupKey2 = - (CustomizeCommandGroupKey) CustomizeCommandGroupKey.asKey("key", invocation2); - Assert.assertEquals(customizeCommandGroupKey1, customizeCommandGroupKey2); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java deleted file mode 100644 index a9c0f701bcd..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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.bizkeeper; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.core.exception.CseException; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Mocked; - -public class TestFallbackPolicyManager { - @Test - public void testFallbackPolicyManager(final @Mocked Configuration config, final @Mocked Invocation invocation, - final @Mocked OperationMeta operation) { - FallbackPolicyManager.addPolicy(new ReturnNullFallbackPolicy()); - FallbackPolicyManager.addPolicy(new ThrowExceptionFallbackPolicy()); - FallbackPolicyManager.addPolicy(new FromCacheFallbackPolicy()); - FallbackPolicyManager.addPolicy(new FallbackPolicy() { - private static final String CUSTOM = "custom"; - - @Override - public String name() { - return CUSTOM; - } - - @Override - public Response getFallbackResponse(Invocation invocation, Throwable error) { - if (error instanceof InvocationException) { - return Response.succResp("test"); - } - if (error instanceof RuntimeException) { - return Response.succResp("runtime"); - } - return null; - } - }); - - new Expectations() { - { - invocation.getMicroserviceName(); - result = "testservice"; - invocation.getOperationMeta(); - result = operation; - operation.getMicroserviceQualifiedName(); - result = "testservice.schema.custom"; - config.getFallbackPolicyPolicy("Consumer", "testservice", "testservice.schema.custom"); - result = "custom"; - } - }; - - Assert.assertEquals("runtime", - FallbackPolicyManager.getFallbackResponse("Consumer", new RuntimeException(), invocation) - .getResult()); - - new Expectations() { - { - invocation.getMicroserviceName(); - result = "testservice"; - invocation.getOperationMeta(); - result = operation; - operation.getMicroserviceQualifiedName(); - result = "testservice.schema.returnnull"; - config.getFallbackPolicyPolicy("Consumer", "testservice", "testservice.schema.returnnull"); - result = "returnnull"; - } - }; - - Assert.assertEquals((String) null, - FallbackPolicyManager.getFallbackResponse("Consumer", null, invocation).getResult()); - - new Expectations() { - { - invocation.getMicroserviceName(); - result = "testservice"; - invocation.getOperationMeta(); - result = operation; - operation.getMicroserviceQualifiedName(); - result = "testservice.schema.throwexception"; - config.getFallbackPolicyPolicy("Consumer", "testservice", "testservice.schema.throwexception"); - result = "throwexception"; - } - }; - Assert.assertEquals(CseException.class, - ((Exception) FallbackPolicyManager.getFallbackResponse("Consumer", null, invocation).getResult()).getCause() - .getClass()); - - new Expectations() { - { - invocation.getMicroserviceName(); - result = "testservice"; - invocation.getOperationMeta(); - result = operation; - operation.getMicroserviceQualifiedName(); - result = "testservice.schema.fromcache"; - config.getFallbackPolicyPolicy("Consumer", "testservice", "testservice.schema.fromcache"); - result = "fromcache"; - invocation.getInvocationQualifiedName(); - result = "testservice.schema.fromcache"; - } - }; - FallbackPolicyManager.record("Consumer", invocation, Response.succResp("mockedsuccess"), true); - FallbackPolicyManager.record("Consumer", invocation, Response.succResp("mockedfailure"), false); - Assert.assertEquals("mockedsuccess", - FallbackPolicyManager.getFallbackResponse("Consumer", null, invocation).getResult()); - - new Expectations() { - { - invocation.getMicroserviceName(); - result = "testservice"; - invocation.getOperationMeta(); - result = operation; - operation.getMicroserviceQualifiedName(); - result = "testservice.schema.unknown"; - config.getFallbackPolicyPolicy("Consumer", "testservice", "testservice.schema.unknown"); - result = "unknown"; - } - }; - Assert.assertEquals(InvocationException.class, - ((Exception) FallbackPolicyManager.getFallbackResponse("Consumer", new InvocationException( - Status.TOO_MANY_REQUESTS, ""), invocation).getResult()).getClass()); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestHystrixPropertiesStrategyExt.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestHystrixPropertiesStrategyExt.java deleted file mode 100644 index 3c563aded37..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestHystrixPropertiesStrategyExt.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.bizkeeper; - -import static org.junit.Assert.assertNotNull; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixCommandProperties; - -/** - * - */ -public class TestHystrixPropertiesStrategyExt { - - @Test - public void testGetCommandPropertiesCacheKey() { - - assertNotNull(HystrixPropertiesStrategyExt.getInstance()); - - HystrixPropertiesStrategyExt hps = HystrixPropertiesStrategyExt.getInstance(); - HystrixCommandKey commandKey = Mockito.mock(HystrixCommandKey.class); - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceName()).thenReturn("testqualify"); - - HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter() - .withRequestCacheEnabled(true) - .withRequestLogEnabled(false) - .withFallbackIsolationSemaphoreMaxConcurrentRequests( - Configuration.INSTANCE.getFallbackMaxConcurrentRequests("groupname", - "testing", - invocation.getOperationMeta().getMicroserviceQualifiedName())); - - String str1 = hps.getCommandPropertiesCacheKey(commandKey, setter); - Assert.assertNull(str1); - } - - @Test - public void testgetCommandProperties() { - HystrixCommandKey commandKey = Mockito.mock(HystrixCommandKey.class); - Mockito.when(commandKey.name()) - .thenReturn("provider.HystrixPropertiesStrategyExtTest.testgetCommandProperties"); - HystrixCommandProperties commandPro = HystrixPropertiesStrategyExt.getInstance() - .getCommandProperties(commandKey, HystrixCommandProperties.Setter()); - Assert.assertTrue(commandPro.circuitBreakerEnabled().get()); - Assert.assertEquals(Integer.valueOf(50), commandPro.circuitBreakerErrorThresholdPercentage().get()); - Assert.assertFalse(commandPro.circuitBreakerForceClosed().get()); - Assert.assertFalse(commandPro.circuitBreakerForceOpen().get()); - Assert.assertEquals(Integer.valueOf(20), commandPro.circuitBreakerRequestVolumeThreshold().get()); - Assert.assertEquals(Integer.valueOf(15000), commandPro.circuitBreakerSleepWindowInMilliseconds().get()); - Assert.assertEquals(Integer.valueOf(1000), commandPro.executionIsolationSemaphoreMaxConcurrentRequests().get()); - Assert.assertTrue(commandPro.executionIsolationThreadInterruptOnTimeout().get()); - Assert.assertEquals(null, commandPro.executionIsolationThreadPoolKeyOverride().get()); - Assert.assertEquals(Integer.valueOf(30000), commandPro.executionTimeoutInMilliseconds().get()); - Assert.assertFalse(commandPro.executionTimeoutEnabled().get()); - Assert.assertEquals(Integer.valueOf(10), commandPro.fallbackIsolationSemaphoreMaxConcurrentRequests().get()); - Assert.assertTrue(commandPro.fallbackEnabled().get()); - Assert.assertEquals(Integer.valueOf(100), commandPro.metricsRollingPercentileBucketSize().get()); - Assert.assertFalse(commandPro.metricsRollingPercentileEnabled().get()); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestProviderBizkeeperHandler.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestProviderBizkeeperHandler.java deleted file mode 100644 index 467993aad0e..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestProviderBizkeeperHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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.bizkeeper; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.hystrix.strategy.HystrixPlugins; - -/** - * - * - */ -public class TestProviderBizkeeperHandler { - - @Test - public void testCreateBizkeeperCommand() { - HystrixPlugins.reset(); - ProviderBizkeeperHanlder providerBizkeeperHanlder = new ProviderBizkeeperHanlder(); - - Invocation invocation = Mockito.mock(Invocation.class); - Mockito.when(invocation.getOperationMeta()).thenReturn(Mockito.mock(OperationMeta.class)); - Mockito.when(invocation.getOperationMeta().getMicroserviceQualifiedName()).thenReturn("test1"); - - CommandKey.toHystrixCommandGroupKey("groupname", invocation); - CommandKey.toHystrixCommandKey("groupname", invocation); - BizkeeperCommand command = providerBizkeeperHanlder.createBizkeeperCommand(invocation); - Assert.assertNotNull(command); - } -} diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/event/TestCircutBreakerEventNotifier.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/event/TestCircutBreakerEventNotifier.java deleted file mode 100644 index 9bcb4a819f6..00000000000 --- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/event/TestCircutBreakerEventNotifier.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.bizkeeper.event; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.servicecomb.foundation.common.event.AlarmEvent; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.google.common.eventbus.Subscribe; -import com.netflix.hystrix.HystrixCommandKey; -import com.netflix.hystrix.HystrixCommandMetrics; -import com.netflix.hystrix.HystrixEventType; - -import mockit.Expectations; - -public class TestCircutBreakerEventNotifier { - private List taskList = null; - - CircutBreakerEventNotifier circutBreakerEventNotifier; - - HystrixCommandKey commandKey = null; - - Object receiveEvent = null; - - public static class EventSubscriber { - List taskList; - - public EventSubscriber(List taskList) { - this.taskList = taskList; - } - - @Subscribe - public void onEvent(AlarmEvent circutBreakerEvent) { - taskList.add(circutBreakerEvent); - } - } - - @Before - public void setUp() throws Exception { - taskList = new ArrayList<>(); - circutBreakerEventNotifier = new CircutBreakerEventNotifier(); - commandKey = Mockito.mock(HystrixCommandKey.class); - receiveEvent = new EventSubscriber(taskList); - circutBreakerEventNotifier.eventBus.register(receiveEvent); - } - - @After - public void tearDown() throws Exception { - circutBreakerEventNotifier.eventBus.unregister(receiveEvent); - } - - @Test - public void testMarkEvent() { - Mockito.when(commandKey.name()).thenReturn("Consumer.springmvc.springmvcHello.sayHi"); - new Expectations(HystrixCommandMetrics.class) { - { - HystrixCommandMetrics.getInstance(commandKey); - result = null; - } - }; - circutBreakerEventNotifier.markEvent(HystrixEventType.SHORT_CIRCUITED, commandKey); - Assert.assertEquals(1, taskList.size()); - circutBreakerEventNotifier.markEvent(HystrixEventType.SUCCESS, commandKey); - Assert.assertEquals(2, taskList.size()); - } -} diff --git a/handlers/handler-bizkeeper/src/test/resources/log4j.properties b/handlers/handler-bizkeeper/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/handlers/handler-bizkeeper/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/handlers/handler-fault-injection/pom.xml b/handlers/handler-fault-injection/pom.xml index e5d581be976..825c63c2270 100755 --- a/handlers/handler-fault-injection/pom.xml +++ b/handlers/handler-fault-injection/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb handlers - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT handler-fault-injection Java Chassis::Handlers::Fault Injection @@ -38,13 +38,13 @@ - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/AbortFault.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/AbortFault.java deleted file mode 100644 index 26044606d42..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/AbortFault.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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.faultinjection; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AbortFault extends AbstractFault { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbortFault.class); - - public static final String ABORTED_ERROR_MSG = "aborted by fault inject"; - - @Override - public void injectFault(Invocation invocation, FaultParam faultParam, AsyncResponse asyncResponse) { - if (!shouldAbort(invocation, faultParam)) { - asyncResponse.success(SUCCESS_RESPONSE); - return; - } - - // get the config values related to abort percentage. - int errorCode = FaultInjectionUtil.getFaultInjectionConfig(invocation, "abort.httpStatus"); - if (errorCode == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { - LOGGER.debug("Fault injection: Abort error code is not configured"); - asyncResponse.success(SUCCESS_RESPONSE); - return; - } - - // if request need to be abort then return failure with given error code - CommonExceptionData errorData = new CommonExceptionData(ABORTED_ERROR_MSG); - asyncResponse.consumerFail(new InvocationException(errorCode, ABORTED_ERROR_MSG, errorData)); - } - - private boolean shouldAbort(Invocation invocation, FaultParam faultParam) { - // get the config values related to abort. - int abortPercent = FaultInjectionUtil.getFaultInjectionConfig(invocation, "abort.percent"); - if (abortPercent == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { - LOGGER.debug("Fault injection: Abort percentage is not configured"); - return false; - } - - // check fault abort condition. - return FaultInjectionUtil.isFaultNeedToInject(faultParam.getReqCount(), abortPercent); - } - - @Override - public int getOrder() { - return 200; - } -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/AbstractFault.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/AbstractFault.java deleted file mode 100644 index e92a68ef560..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/AbstractFault.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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.faultinjection; - -public abstract class AbstractFault implements Fault { - -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/ConsumerAbortFaultFilter.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/ConsumerAbortFaultFilter.java new file mode 100644 index 00000000000..e4eef91ef2f --- /dev/null +++ b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/ConsumerAbortFaultFilter.java @@ -0,0 +1,79 @@ +/* + * 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.faultinjection; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ConsumerAbortFaultFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerAbortFaultFilter.class); + + private static final String SUCCESS_RESPONSE = "success"; + + public static final String ABORTED_ERROR_MSG = "aborted by fault inject"; + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1020; + } + + @Override + public String getName() { + return "consumer-abort-fault"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (!shouldAbort(invocation)) { + return nextNode.onFilter(invocation); + } + + // get the config values related to abort percentage. + int errorCode = FaultInjectionUtil.getFaultInjectionConfig(invocation, "abort.httpStatus"); + if (errorCode == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: Abort error code is not configured"); + return CompletableFuture.completedFuture(Response.succResp(SUCCESS_RESPONSE)); + } + + // if request need to be abort then return failure with given error code + CommonExceptionData errorData = new CommonExceptionData(ABORTED_ERROR_MSG); + return CompletableFuture.failedFuture(new InvocationException(errorCode, ABORTED_ERROR_MSG, errorData)); + } + + private boolean shouldAbort(Invocation invocation) { + // get the config values related to abort. + int abortPercent = FaultInjectionUtil.getFaultInjectionConfig(invocation, "abort.percent"); + if (abortPercent == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: Abort percentage is not configured"); + return false; + } + + // check fault abort condition. + return FaultInjectionUtil.isFaultNeedToInject(abortPercent); + } +} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/ConsumerDelayFaultFilter.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/ConsumerDelayFaultFilter.java new file mode 100644 index 00000000000..e8c0f6ffd67 --- /dev/null +++ b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/ConsumerDelayFaultFilter.java @@ -0,0 +1,99 @@ +/* + * 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.faultinjection; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.swagger.invocation.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.vertx.core.Context; +import io.vertx.core.Vertx; + +public class ConsumerDelayFaultFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerDelayFaultFilter.class); + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1030; + } + + @Override + public String getName() { + return "consumer-delay-fault"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (!shouldDelay(invocation)) { + return nextNode.onFilter(invocation); + } + + LOGGER.debug("Fault injection: delay is added for the request by fault inject handler"); + long delay = FaultInjectionUtil.getFaultInjectionConfig(invocation, + "delay.fixedDelay"); + if (delay == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: delay is not configured"); + return nextNode.onFilter(invocation); + } + + return executeDelay(invocation, nextNode, delay); + } + + private CompletableFuture executeDelay(Invocation invocation, FilterNode nextNode, + long delay) { + Context currentContext = Vertx.currentContext(); + if (currentContext != null && currentContext.isEventLoopContext()) { + CompletableFuture result = new CompletableFuture<>(); + currentContext.owner().setTimer(delay, timeID -> nextNode.onFilter(invocation).whenComplete((r, e) -> { + if (e == null) { + result.complete(r); + } else { + result.completeExceptionally(e); + } + } + )); + return result; + } + + try { + Thread.sleep(delay); + } catch (InterruptedException e) { + LOGGER.info("Interrupted exception is received"); + } + return nextNode.onFilter(invocation); + } + + private boolean shouldDelay(Invocation invocation) { + int delayPercent = FaultInjectionUtil.getFaultInjectionConfig(invocation, + "delay.percent"); + if (delayPercent == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { + LOGGER.debug("Fault injection: delay percentage is not configured"); + return false; + } + + // check fault delay condition. + return FaultInjectionUtil.isFaultNeedToInject(delayPercent); + } +} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/DelayFault.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/DelayFault.java deleted file mode 100644 index 38318d2deb5..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/DelayFault.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.faultinjection; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.vertx.core.Vertx; - -public class DelayFault extends AbstractFault { - private static final Logger LOGGER = LoggerFactory.getLogger(DelayFault.class); - - @Override - public int getOrder() { - return 100; - } - - @Override - public void injectFault(Invocation invocation, FaultParam faultParam, AsyncResponse asynResponse) { - if (!shouldDelay(invocation, faultParam, asynResponse)) { - asynResponse.success(SUCCESS_RESPONSE); - return; - } - - LOGGER.debug("Fault injection: delay is added for the request by fault inject handler"); - long delay = FaultInjectionUtil.getFaultInjectionConfig(invocation, - "delay.fixedDelay"); - if (delay == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { - LOGGER.debug("Fault injection: delay is not configured"); - asynResponse.success(SUCCESS_RESPONSE); - return; - } - - executeDelay(faultParam, asynResponse, delay); - } - - private void executeDelay(FaultParam faultParam, AsyncResponse asynResponse, long delay) { - Vertx vertx = faultParam.getVertx(); - if (vertx != null) { - vertx.setTimer(delay, timeID -> asynResponse.success(SUCCESS_RESPONSE)); - return; - } - - try { - Thread.sleep(delay); - } catch (InterruptedException e) { - LOGGER.info("Interrupted exception is received"); - } - asynResponse.success(SUCCESS_RESPONSE); - } - - private boolean shouldDelay(Invocation invocation, FaultParam faultParam, AsyncResponse asynResponse) { - int delayPercent = FaultInjectionUtil.getFaultInjectionConfig(invocation, - "delay.percent"); - if (delayPercent == FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE) { - LOGGER.debug("Fault injection: delay percentage is not configured"); - return false; - } - - // check fault delay condition. - return FaultInjectionUtil.isFaultNeedToInject(faultParam.getReqCount(), delayPercent); - } -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/Fault.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/Fault.java deleted file mode 100644 index a3f254537cf..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/Fault.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.faultinjection; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; - -public interface Fault { - - String SUCCESS_RESPONSE = "success"; - - int getOrder(); - - void injectFault(Invocation invocation, FaultParam faultAttributes, AsyncResponse asynResponse); -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultExecutor.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultExecutor.java deleted file mode 100644 index 9a20f64c949..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultExecutor.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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.faultinjection; - -import java.util.List; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; - - -/** - * Implements the fault feature execution one after other. - */ -public class FaultExecutor { - private List faultInjectList; - - private int handlerIndex = 0; - - private Invocation invocation; - - private FaultParam param; - - public FaultExecutor(List faultInjectList, Invocation invocation, FaultParam param) { - this.faultInjectList = faultInjectList; - this.invocation = invocation; - this.param = param; - } - - public void execute(AsyncResponse asyncResponse) { - this.next(asyncResponse); - } - - private void next(AsyncResponse asyncResponse) { - if (handlerIndex >= faultInjectList.size()) { - asyncResponse.complete(Response.succResp("success")); - return; - } - - int runIndex = handlerIndex; - handlerIndex++; - faultInjectList.get(runIndex).injectFault(invocation, param, response -> { - if (response.isFailed()) { - asyncResponse.complete(response); - } else { - FaultExecutor.this.next(asyncResponse); - } - }); - } -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionConfig.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionConfig.java deleted file mode 100755 index d43eb2f385a..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.faultinjection; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicIntProperty; -import com.netflix.config.DynamicPropertyFactory; - -/** - * Handles the fault injection configuration read from micro service file/config - * center. - */ -public final class FaultInjectionConfig { - - private static final Logger LOGGER = LoggerFactory.getLogger(FaultInjectionConfig.class); - - // key is configuration parameter. - private static Map cfgCallback = new ConcurrentHashMapEx<>(); - - public static int getConfigVal(String config, int defaultValue) { - DynamicIntProperty dynamicIntProperty = DynamicPropertyFactory.getInstance().getIntProperty(config, - defaultValue); - - cfgCallback.computeIfAbsent(config, key -> { - dynamicIntProperty.addCallback(() -> { - int newValue = dynamicIntProperty.get(); - String cfgName = dynamicIntProperty.getName(); - - //store the value in config center map and check for next requests. - FaultInjectionUtil.setConfigCenterValue(cfgName, new AtomicInteger(newValue)); - LOGGER.info("{} changed to {}", cfgName, newValue); - }); - return config; - }); - - return dynamicIntProperty.get(); - } -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionConfiguration.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionConfiguration.java new file mode 100644 index 00000000000..600ed5dc9f6 --- /dev/null +++ b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionConfiguration.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.faultinjection; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(value = FaultInjectionConfiguration.FAULT_INJECTION_ENABLED, + havingValue = "true") +public class FaultInjectionConfiguration { + public static final String FAULT_INJECTION_PREFIX = "servicecomb.faultInjection"; + + public static final String FAULT_INJECTION_ENABLED = FAULT_INJECTION_PREFIX + ".enabled"; + + @Bean + public ConsumerAbortFaultFilter scbConsumerAbortFaultFilter() { + return new ConsumerAbortFaultFilter(); + } + + @Bean + public ConsumerDelayFaultFilter scbConsumerDelayFaultFilter() { + return new ConsumerDelayFaultFilter(); + } +} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionHandler.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionHandler.java deleted file mode 100755 index 8c292461346..00000000000 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionHandler.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.faultinjection; - -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; - -import io.vertx.core.Context; -import io.vertx.core.Vertx; - -/** - * Fault injection handler which injects the delay/abort for requests based on - * the percentage configured in service file. - * - */ - -public class FaultInjectionHandler implements Handler { - - private List faultInjectionFeatureList = SPIServiceUtils.getSortedService(Fault.class); - - //added only for unit testing - public void setFaultFeature(List faultFeature) { - faultInjectionFeatureList = faultFeature; - } - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - - // prepare the key and lookup for request count. - String key = invocation.getTransport().getName() + invocation.getMicroserviceQualifiedName(); - AtomicLong reqCount = FaultInjectionUtil.getOperMetTotalReq(key); - // increment the request count here after checking the delay/abort condition. - long reqCountCurrent = reqCount.getAndIncrement(); - - FaultParam param = new FaultParam(reqCountCurrent); - Context currentContext = Vertx.currentContext(); - if (currentContext != null && currentContext.isEventLoopContext()) { - param.setVertx(currentContext.owner()); - } - - FaultExecutor executor = new FaultExecutor(faultInjectionFeatureList, invocation, param); - executor.execute(response -> { - try { - if (response.isFailed()) { - asyncResp.complete(response); - } else { - invocation.next(asyncResp); - } - } catch (Exception e) { - asyncResp.consumerFail(e); - } - }); - } -} diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionUtil.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionUtil.java index cca451997a1..67c3ab86939 100755 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionUtil.java +++ b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultInjectionUtil.java @@ -23,12 +23,15 @@ import static org.apache.servicecomb.faultinjection.FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE; import java.util.Map; +import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import com.google.common.annotations.VisibleForTesting; + /** * Handles the count for all request based key[transport + microservice qualified name]. */ @@ -36,22 +39,8 @@ public class FaultInjectionUtil { private FaultInjectionUtil() { } - // key is transport+operQualifiedName - private static Map requestCount = new ConcurrentHashMapEx<>(); - - // key is config paramter - private static Map configCenterValue = new ConcurrentHashMapEx<>(); - - /** - * Returns total requests per provider for operational level. - * - * @param key - * transport+operational name - * @return long total requests - */ - public static AtomicLong getOperMetTotalReq(String key) { - return requestCount.computeIfAbsent(key, p -> new AtomicLong(1)); - } + // key is config parameter + private static final Map configCenterValue = new ConcurrentHashMapEx<>(); /** * Returns the map of config parameter key and values. @@ -132,34 +121,24 @@ private static int getConfigValue(String config) { return cfgMap.get(config).get(); } - value = FaultInjectionConfig.getConfigVal(config, FAULT_INJECTION_DEFAULT_VALUE); + value = LegacyPropertyFactory.getIntProperty(config, FAULT_INJECTION_DEFAULT_VALUE); return value; } /** - * It will check the delay/abort condition based on request count and percentage - * received. + * It will check the delay/abort condition based on percentage. * - * @param reqCount - * @param percentage * @return true: delay/abort is needed. false: delay/abort is not needed. */ - public static boolean isFaultNeedToInject(long reqCount, int percentage) { - /* - * Example: delay/abort percentage configured is 10% and Get the count(suppose - * if it is 10th request) from map and calculate resultNew(10th request) and - * requestOld(9th request). Like this for every request it will calculate - * current request count and previous count. if both not matched need to add - * delay/abort otherwise no need to add. - */ - - // calculate the value with current request count. - long resultNew = (reqCount * percentage) / 100; - - // calculate the value with previous count value. - long resultOld = ((reqCount - 1) * percentage) / 100; - - // if both are not matching then delay/abort should be added. - return (resultNew != resultOld); + public static boolean isFaultNeedToInject(int percentage) { + if (percentage > 0) { + return ThreadLocalRandom.current().nextInt(100) < percentage; + } + return false; + } + + @VisibleForTesting + static Map getConfigCenterValue() { + return configCenterValue; } } diff --git a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultParam.java b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultParam.java index 92f0e84ebeb..23530f13f58 100644 --- a/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultParam.java +++ b/handlers/handler-fault-injection/src/main/java/org/apache/servicecomb/faultinjection/FaultParam.java @@ -23,20 +23,10 @@ * Fault injection parameters which decides the fault injection condition. */ public class FaultParam { - private long reqCount; - private Vertx vertx; - public long getReqCount() { - return reqCount; - } - - public void setReqCount(long reqCount) { - this.reqCount = reqCount; - } + FaultParam() { - FaultParam(long reqCount) { - this.reqCount = reqCount; } public Vertx getVertx() { diff --git a/handlers/handler-fault-injection/src/main/resources/META-INF/services/org.apache.servicecomb.faultinjection.Fault b/handlers/handler-fault-injection/src/main/resources/META-INF/services/org.apache.servicecomb.faultinjection.Fault deleted file mode 100644 index 1da13d5db6a..00000000000 --- a/handlers/handler-fault-injection/src/main/resources/META-INF/services/org.apache.servicecomb.faultinjection.Fault +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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.servicecomb.faultinjection.DelayFault -org.apache.servicecomb.faultinjection.AbortFault diff --git a/handlers/handler-fault-injection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-fault-injection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..b58acc214f3 --- /dev/null +++ b/handlers/handler-fault-injection/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.servicecomb.faultinjection.FaultInjectionConfiguration diff --git a/handlers/handler-fault-injection/src/main/resources/config/cse.handler.xml b/handlers/handler-fault-injection/src/main/resources/config/cse.handler.xml deleted file mode 100755 index 3ceed7a6714..00000000000 --- a/handlers/handler-fault-injection/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/AbortFaultTest.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/AbortFaultTest.java deleted file mode 100644 index 4e51e9d0606..00000000000 --- a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/AbortFaultTest.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * 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.faultinjection; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.vertx.VertxUtils; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.config.DynamicProperty; - -import io.vertx.core.Vertx; -import mockit.Deencapsulation; - -public class AbortFaultTest { - private Invocation invocation; - - @SuppressWarnings("unchecked") - @Before - public void before() { - ArchaiusUtils.resetConfig(); - ((Map) Deencapsulation.getField(FaultInjectionConfig.class, "cfgCallback")).clear(); - ((Map) Deencapsulation.getField(FaultInjectionUtil.class, "requestCount")).clear(); - ((Map) Deencapsulation.getField(FaultInjectionUtil.class, "configCenterValue")).clear(); - - invocation = Mockito.mock(Invocation.class); - Transport transport = Mockito.mock(Transport.class); - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName12"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts6"); - } - - @After - public void after() { - ArchaiusUtils.resetConfig(); - } - - @AfterClass - public static void classTeardown() { - VertxUtils.blockCloseVertxByName("faultinjectionTest"); - } - - @Test - public void injectFaultError() { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus", "421"); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent", "100"); - - assertEquals("421", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus") - .getString()); - assertEquals("100", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent") - .getString()); - - AbortFault abortFault = new AbortFault(); - FaultParam faultParam = new FaultParam(1); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - abortFault.injectFault(invocation, faultParam, response -> resultHolder.value = response.getResult()); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals(421, resultHolder.value.getStatusCode()); - assertEquals("aborted by fault inject", resultHolder.value.getReasonPhrase()); - assertEquals("CommonExceptionData [message=aborted by fault inject]", resultHolder.value.getErrorData().toString()); - } - - @Test - public void injectFaultNoError() { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus", "421"); - ArchaiusUtils.setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent", "0"); - - assertEquals("421", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus") - .getString()); - assertEquals("0", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent") - .getString()); - - AbortFault abortFault = new AbortFault(); - FaultParam faultParam = new FaultParam(1); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - abortFault.injectFault(invocation, faultParam, response -> resultHolder.value = response.getResult()); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } - - @Test - public void injectFaultNoPercentageConfig() { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent", null); - - assertNull(DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent") - .getString()); - - AbortFault abortFault = new AbortFault(); - FaultParam faultParam = new FaultParam(1); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - abortFault.injectFault(invocation, faultParam, response -> resultHolder.value = response.getResult()); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } - - @Test - public void injectFaultNoErrorCodeConfig() { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent", "10"); - - assertEquals("10", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent") - .getString()); - - AbortFault abortFault = new AbortFault(); - FaultParam faultParam = new FaultParam(10); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - abortFault.injectFault(invocation, faultParam, response -> resultHolder.value = response.getResult()); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } -} diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/DelayFaultTest.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/DelayFaultTest.java deleted file mode 100644 index 62b96569193..00000000000 --- a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/DelayFaultTest.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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.faultinjection; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.vertx.VertxUtils; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.config.DynamicProperty; - -import io.vertx.core.Vertx; -import mockit.Deencapsulation; - -public class DelayFaultTest { - private Invocation invocation; - - @SuppressWarnings("unchecked") - @Before - public void before() { - ArchaiusUtils.resetConfig(); - ((Map) Deencapsulation.getField(FaultInjectionConfig.class, "cfgCallback")).clear(); - ((Map) Deencapsulation.getField(FaultInjectionUtil.class, "requestCount")).clear(); - ((Map) Deencapsulation.getField(FaultInjectionUtil.class, "configCenterValue")).clear(); - - invocation = Mockito.mock(Invocation.class); - Transport transport = Mockito.mock(Transport.class); - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName12"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts6"); - } - - @After - public void after() { - ArchaiusUtils.resetConfig(); - } - - @AfterClass - public static void classTeardown() { - VertxUtils.blockCloseVertxByName("faultinjectionTest"); - } - - @Test - public void injectFaultVertxDelay() throws InterruptedException { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", "10"); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", "100"); - - assertEquals("10", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay") - .getString()); - assertEquals("100", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent") - .getString()); - - DelayFault delayFault = new DelayFault(); - FaultParam faultParam = new FaultParam(1); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - CountDownLatch latch = new CountDownLatch(1); - delayFault.injectFault(invocation, faultParam, response -> { - resultHolder.value = response.getResult(); - latch.countDown(); - }); - - latch.await(10, TimeUnit.SECONDS); - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } - - @Test - public void injectFaultSystemDelay() throws InterruptedException { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", "10"); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", "100"); - - assertEquals("10", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay") - .getString()); - assertEquals("100", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent") - .getString()); - - DelayFault delayFault = new DelayFault(); - FaultParam faultParam = new FaultParam(1); - - Holder resultHolder = new Holder<>(); - CountDownLatch latch = new CountDownLatch(1); - delayFault.injectFault(invocation, faultParam, response -> { - resultHolder.value = response.getResult(); - latch.countDown(); - }); - - latch.await(10, TimeUnit.SECONDS); - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } - - @Test - public void injectFaultNotDelay() throws InterruptedException { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", "10"); - ArchaiusUtils.setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", "0"); - - assertEquals("10", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay") - .getString()); - assertEquals("0", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent") - .getString()); - - DelayFault delayFault = new DelayFault(); - FaultParam faultParam = new FaultParam(1); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - CountDownLatch latch = new CountDownLatch(1); - delayFault.injectFault(invocation, faultParam, response -> { - resultHolder.value = response.getResult(); - latch.countDown(); - }); - - latch.await(3, TimeUnit.SECONDS); - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } - - @Test - public void injectFaultNoPercentageConfig() { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", null); - - assertNull(DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent") - .getString()); - - DelayFault delayFault = new DelayFault(); - FaultParam faultParam = new FaultParam(1); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - delayFault.injectFault(invocation, faultParam, response -> resultHolder.value = response.getResult()); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } - - @Test - public void injectFaultNoDelayMsConfig() { - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", "10"); - - assertEquals("10", DynamicProperty - .getInstance("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent") - .getString()); - - DelayFault delayFault = new DelayFault(); - FaultParam faultParam = new FaultParam(10); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - Holder resultHolder = new Holder<>(); - delayFault.injectFault(invocation, faultParam, response -> resultHolder.value = response.getResult()); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - assertEquals("success", resultHolder.value); - } -} diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestConsumerAbortFaultFilter.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestConsumerAbortFaultFilter.java new file mode 100644 index 00000000000..d44fd849b2f --- /dev/null +++ b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestConsumerAbortFaultFilter.java @@ -0,0 +1,167 @@ +/* + * 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.faultinjection; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.foundation.common.Holder; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.vertx.VertxUtils; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +public class TestConsumerAbortFaultFilter { + private Invocation invocation; + + private Environment environment; + + @BeforeEach + public void before() { + environment = Mockito.mock(Environment.class); + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4.operations.sayBye4" + + ".policy.fault.protocols.rest.abort.percent", + int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4.operations.sayBye4" + + ".policy.fault.protocols.rest.abort.httpStatus", + int.class, -1)).thenReturn(-1); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4" + + ".policy.fault.protocols.rest.abort.percent", + int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4" + + ".policy.fault.protocols.rest.abort.httpStatus", + int.class, -1)).thenReturn(-1); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6" + + ".policy.fault.protocols.rest.abort.percent", + int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6" + + ".policy.fault.protocols.rest.abort.httpStatus", + int.class, -1)).thenReturn(-1); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.abort.percent", + int.class, -1)) + .thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.abort.httpStatus", + int.class, -1)) + .thenReturn(-1); + + FaultInjectionUtil.getConfigCenterValue().clear(); + + invocation = Mockito.mock(Invocation.class); + Transport transport = Mockito.mock(Transport.class); + Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName12"); + Mockito.when(invocation.getTransport()).thenReturn(transport); + Mockito.when(transport.getName()).thenReturn("rest"); + Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); + Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); + Mockito.when(invocation.getMicroserviceName()).thenReturn("carts6"); + } + + @AfterEach + public void after() { + } + + @AfterAll + public static void classTeardown() { + VertxUtils.blockCloseVertxByName("faultinjectionTest"); + } + + @Test + public void injectFaultError() { + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.abort.httpStatus", + int.class, -1)) + .thenReturn(421); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.abort.percent", + int.class, -1)) + .thenReturn(100); + + ConsumerAbortFaultFilter abortFault = new ConsumerAbortFaultFilter(); + + FilterNode filterNode = Mockito.mock(FilterNode.class); + + Holder resultHolder = new Holder<>(); + CompletableFuture result = abortFault.onFilter(invocation, filterNode); + result.whenComplete((r, e) -> { + if (e != null) { + resultHolder.value = (InvocationException) e; + } + }); + Assertions.assertThrows(ExecutionException.class, () -> result.get()); + Assertions.assertEquals(421, resultHolder.value.getStatusCode()); + Assertions.assertEquals("aborted by fault inject", resultHolder.value.getReasonPhrase()); + Assertions.assertEquals("CommonExceptionData [message=aborted by fault inject]", + resultHolder.value.getErrorData().toString()); + } + + @Test + public void injectFaultNoError() throws Exception { + ConsumerAbortFaultFilter abortFault = new ConsumerAbortFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = abortFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } + + @Test + public void injectFaultNoPercentageConfig() throws Exception { + ConsumerAbortFaultFilter abortFault = new ConsumerAbortFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = abortFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } + + @Test + public void injectFaultNoErrorCodeConfig() throws Exception { + ConsumerAbortFaultFilter abortFault = new ConsumerAbortFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = abortFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } +} diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestConsumerDelayFaultFilter.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestConsumerDelayFaultFilter.java new file mode 100644 index 00000000000..381d3d01447 --- /dev/null +++ b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestConsumerDelayFaultFilter.java @@ -0,0 +1,187 @@ +/* + * 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.faultinjection; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.vertx.VertxUtils; +import org.apache.servicecomb.swagger.invocation.Response; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +public class TestConsumerDelayFaultFilter { + private Invocation invocation; + + private Environment environment; + + @BeforeEach + public void before() { + environment = Mockito.mock(Environment.class); + LegacyPropertyFactory.setEnvironment(environment); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4.operations.sayBye4" + + ".policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4.operations.sayBye4" + + ".policy.fault.protocols.rest.delay.percent", + int.class, -1)).thenReturn(-1); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4" + + ".policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6.schemas.testSchema4" + + ".policy.fault.protocols.rest.delay.percent", + int.class, -1)).thenReturn(-1); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6" + + ".policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)).thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer.carts6" + + ".policy.fault.protocols.rest.delay.percent", + int.class, -1)).thenReturn(-1); + + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)) + .thenReturn(-1); + Mockito.when(environment.getProperty( + "servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.delay.percent", + int.class, -1)) + .thenReturn(-1); + + FaultInjectionUtil.getConfigCenterValue().clear(); + + invocation = Mockito.mock(Invocation.class); + Transport transport = Mockito.mock(Transport.class); + Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName12"); + Mockito.when(invocation.getTransport()).thenReturn(transport); + Mockito.when(transport.getName()).thenReturn("rest"); + Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); + Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); + Mockito.when(invocation.getMicroserviceName()).thenReturn("carts6"); + } + + @AfterEach + public void after() { + } + + @AfterAll + public static void classTeardown() { + VertxUtils.blockCloseVertxByName("faultinjectionTest"); + } + + @Test + public void injectFaultVertxDelay() throws Exception { + Mockito.when(environment.getProperty("servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)) + .thenReturn(10); + Mockito.when( + environment.getProperty("servicecomb.governance.Consumer._global" + + ".policy.fault.protocols.rest.delay.percent", + int.class, -1)) + .thenReturn(100); + + ConsumerDelayFaultFilter delayFault = new ConsumerDelayFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = delayFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } + + @Test + public void injectFaultSystemDelay() throws Exception { + Mockito.when( + environment.getProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)) + .thenReturn(10); + Mockito.when( + environment.getProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", + int.class, -1)) + .thenReturn(100); + + ConsumerDelayFaultFilter delayFault = new ConsumerDelayFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = delayFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } + + @Test + public void injectFaultNotDelay() throws Exception { + Mockito.when( + environment.getProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", + int.class, -1)) + .thenReturn(10); + Mockito.when( + environment.getProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", + int.class, -1)) + .thenReturn(0); + + ConsumerDelayFaultFilter delayFault = new ConsumerDelayFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = delayFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } + + @Test + public void injectFaultNoPercentageConfig() throws Exception { + ConsumerDelayFaultFilter delayFault = new ConsumerDelayFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = delayFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } + + @Test + public void injectFaultNoDelayMsConfig() throws Exception { + Mockito.when( + environment.getProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", + int.class, -1)) + .thenReturn(10); + + ConsumerDelayFaultFilter delayFault = new ConsumerDelayFaultFilter(); + FilterNode filterNode = Mockito.mock(FilterNode.class); + Mockito.when(filterNode.onFilter(invocation)) + .thenReturn(CompletableFuture.completedFuture(Response.succResp("success"))); + CompletableFuture result = delayFault.onFilter(invocation, filterNode); + Assertions.assertEquals("success", result.get().getResult()); + } +} diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectConfig.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectConfig.java deleted file mode 100644 index 50da42b60cf..00000000000 --- a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectConfig.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.faultinjection; - -import static org.junit.Assert.assertEquals; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Tests the fault injection configuration. - */ -public class TestFaultInjectConfig { - FaultInjectionConfig faultCfg; - - FaultInjectionConst faultConst; - - FaultParam faultParam; - - AbortFault abortFault; - - DelayFault delayFault; - - @Before - public void setUp() throws Exception { - faultCfg = new FaultInjectionConfig(); - faultConst = new FaultInjectionConst(); - faultParam = new FaultParam(10); - abortFault = new AbortFault(); - delayFault = new DelayFault(); - } - - @After - public void tearDown() throws Exception { - faultCfg = null; - faultConst = null; - faultParam = null; - } - - @Test - public void testFaultInjectConfig() throws Exception { - int val = FaultInjectionConfig.getConfigVal("servicecomb.servicecomb.handler.consumer.faultinject.config", 0); - Assert.assertEquals(0, val); - } - - @Test - public void testConstants() { - assertEquals("servicecomb.governance.Consumer.", FaultInjectionConst.CONSUMER_FAULTINJECTION); - assertEquals("policy.fault.protocols.", FaultInjectionConst.CONSUMER_FAULTINJECTION_POLICY_PROTOCOLS); - assertEquals(-1, FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE); - assertEquals("servicecomb.governance.Consumer._global.", FaultInjectionConst.CONSUMER_FAULTINJECTION_GLOBAL); - assertEquals(-1, FaultInjectionConst.FAULT_INJECTION_ERROR); - } - - @Test - public void testFaultParam() { - faultParam.setReqCount(100); - faultParam.setVertx(null); - assertEquals(100, faultParam.getReqCount()); - assertEquals(null, faultParam.getVertx()); - } - - @Test - public void testFaultPriority() { - assertEquals(200, abortFault.getOrder()); - assertEquals(100, delayFault.getOrder()); - } -} diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectHandler.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectHandler.java deleted file mode 100644 index b8ef3747a8a..00000000000 --- a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectHandler.java +++ /dev/null @@ -1,702 +0,0 @@ -/* - * 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.faultinjection; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.vertx.VertxUtils; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.InjectMocks; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import io.vertx.core.Vertx; - -/** - * Tests the fault injection handler functionality. - */ -public class TestFaultInjectHandler { - FaultInjectionHandler handler; - - Invocation invocation; - - AsyncResponse asyncResp; - - OperationMeta operationMeta; - - private Transport transport; - - Response response; - - boolean isDelay; - - boolean isAbort; - - @InjectMocks - AbortFault abortFault; - - @InjectMocks - DelayFault delayFault; - - AsyncResponse ar = new AsyncResponse() { - @Override - public void handle(Response resp) { - response = resp; - } - }; - - @Before - public void setUp() { - ArchaiusUtils.resetConfig(); - handler = new FaultInjectionHandler(); - invocation = Mockito.mock(Invocation.class); - asyncResp = Mockito.mock(AsyncResponse.class); - operationMeta = Mockito.mock(OperationMeta.class); - transport = Mockito.mock(Transport.class); - MockitoAnnotations.initMocks(this); - } - - @After - public void tearDown() { - handler = null; - invocation = null; - asyncResp = null; - operationMeta = null; - transport = null; - ArchaiusUtils.resetConfig(); - } - - @AfterClass - public static void classTeardown() { - VertxUtils.blockCloseVertxByName("faultinjectionTest"); - } - - /** - * Tests the fault injection handler functionality with default values for - * highway transport. - */ - @Test - public void testFaultInjectHandlerHighwayWithDefaultCfg() throws Exception { - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName1"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("highway"); - Mockito.when(invocation.getOperationName()).thenReturn("sayHello"); - Mockito.when(invocation.getSchemaId()).thenReturn("sayHelloSchema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("hello"); - - List faultInjectionFeatureList = Arrays.asList(abortFault, delayFault); - handler.setFaultFeature(faultInjectionFeatureList); - - handler.handle(invocation, asyncResp); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("highwayMicroserviceQualifiedName1"); - assertEquals(2, count.get()); - } - - /** - * Tests the fault injection handler functionality with default values for rest - * transport. - */ - @Test - public void testFaultInjectHandlerRestWithDefaultCfg() throws Exception { - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName2"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayHello"); - Mockito.when(invocation.getSchemaId()).thenReturn("sayHelloSchema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("hello"); - - List faultInjectionFeatureList = Arrays.asList(delayFault, abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - handler.handle(invocation, asyncResp); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName2"); - assertEquals(2, count.get()); - } - - /** - * Tests the fault injection handler functionality with global configuration - * with delay/abort condition. - */ - @Test - public void testFaultInjectHandlerConfigChangeGlobal() throws Exception { - - System.setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", "5"); - System.setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", "10"); - System.setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent", "10"); - System.setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus", "421"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName3"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayHello"); - Mockito.when(invocation.getSchemaId()).thenReturn("sayHelloSchema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("hello"); - - List faultInjectionFeatureList = Arrays.asList(abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - handler.handle(invocation, ar -> { - //this case no delay/no abort so reponse is null, it should not enter this in this block. - isDelay = true; - isAbort = true; - }); - Assert.assertFalse(isDelay); - Assert.assertFalse(isAbort); - - System.getProperties() - .remove("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties().remove("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent"); - System.getProperties().remove("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName3"); - assertEquals(2, count.get()); - } - - /** - * Tests the fault injection handler functionality with service level configuration - * with delay/abort condition. - */ - @Test - public void testFaultInjectHandlerServiceCfgSuccess() throws Exception { - - System.setProperty("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.delay.fixedDelay", "1"); - System.setProperty("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.delay.percent", "10"); - System.setProperty("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.abort.percent", "10"); - System.setProperty("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.abort.httpStatus", "421"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName4"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayHello"); - Mockito.when(invocation.getSchemaId()).thenReturn("sayHelloSchema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts"); - - List faultInjectionFeatureList = Arrays.asList(abortFault, delayFault); - handler.setFaultFeature(faultInjectionFeatureList); - - handler.handle(invocation, ar -> { - //this case no delay/no abort so reponse is null, it should not enter this in this block. - isDelay = true; - isAbort = true; - }); - Assert.assertFalse(isDelay); - Assert.assertFalse(isAbort); - - System.getProperties().remove("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties().remove("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.delay.percent"); - System.getProperties().remove("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.abort.percent"); - System.getProperties().remove("servicecomb.governance.Consumer.carts.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName4"); - assertEquals(2, count.get()); - } - - /** - * Tests the fault injection handler functionality with schema level configuration - * with delay/abort condition. - */ - @Test - public void testFaultInjectHandlerSchemaCfgSuccess() throws Exception { - - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.delay.fixedDelay", - "1"); - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.delay.percent", - "10"); - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.abort.percent", - "10"); - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.abort.httpStatus", - "421"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName5"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayHello"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts"); - - List faultInjectionFeatureList = Arrays.asList(abortFault, delayFault); - handler.setFaultFeature(faultInjectionFeatureList); - - handler.handle(invocation, ar -> { - //this case no delay/no abort so reponse is null, it should not enter this in this block. - isDelay = true; - isAbort = true; - }); - Assert.assertFalse(isDelay); - Assert.assertFalse(isAbort); - - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts.schemas.testSchema.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName5"); - assertEquals(2, count.get()); - } - - /** - * Tests the fault injection handler functionality with operation level configuration - * with delay/abort condition. - */ - @Test - public void testFaultInjectHandlerOperationCfgSuccess() throws Exception { - - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.delay.fixedDelay", - "1"); - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.delay.percent", - "10"); - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.abort.percent", - "10"); - System.setProperty( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.abort.httpStatus", - "421"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName6"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayHi"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts"); - - List faultInjectionFeatureList = Arrays.asList(abortFault, delayFault); - handler.setFaultFeature(faultInjectionFeatureList); - - handler.handle(invocation, ar -> { - //this case no delay/no abort so reponse is null, it should not enter this in this block. - isDelay = true; - isAbort = true; - }); - - Assert.assertFalse(isDelay); - Assert.assertFalse(isAbort); - - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts.schemas.testSchema.operations.sayHi.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName6"); - assertEquals(2, count.get()); - } - - /** - * Tests the fault injection handler functionality with configuration change event for global level config. - */ - @Test - public void testFaultInjectHandlerConfigChangeEvent1() throws Exception { - - System.setProperty( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", - "1"); - System.setProperty( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus", - "420"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName7"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye1"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema1"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts1"); - boolean validAssert; - - List faultInjectionFeatureList = Arrays.asList(delayFault, abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - try { - validAssert = true; - handler.handle(invocation, ar); - } catch (Exception e) { - validAssert = false; - } - Assert.assertTrue(validAssert); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay", 500); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus", 421); - - Holder isAsserted = new Holder<>(false); - handler.handle(invocation, ar -> { - isAsserted.value = true; - assertTrue(response.isFailed()); - }); - Assert.assertTrue(isAsserted.value); - - System.getProperties() - .remove( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer._global.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName7"); - assertEquals(3, count.get()); - } - - /** - * Tests the fault injection handler functionality with configuration change event for operation level config. - */ - @Test - public void testFaultInjectHandlerConfigChangeEvent2() throws Exception { - System.setProperty( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.delay.fixedDelay", - "1"); - System.setProperty( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.delay.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.abort.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.abort.httpStatus", - "420"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName8"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye2"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema2"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts2"); - boolean validAssert; - long timeOld = System.currentTimeMillis(); - - List faultInjectionFeatureList = Arrays.asList(delayFault, abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - try { - validAssert = true; - handler.handle(invocation, ar); - } catch (Exception e) { - validAssert = false; - } - Assert.assertTrue(validAssert); - ArchaiusUtils.setProperty( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.delay.fixedDelay", - 500); - - Holder isAsserted = new Holder<>(false); - handler.handle(invocation, ar -> { - //check whether error code return - isAsserted.value = true; - assertEquals(420, response.getStatusCode()); - assertTrue(response.isFailed()); - long timeNow = System.currentTimeMillis(); - //if really time delay is added it should be greater than 5s. - Assert.assertTrue((timeNow - timeOld) >= 500); - }); - Assert.assertTrue(isAsserted.value); - - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts2.schemas.testSchema2.operations.sayBye2.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName8"); - assertEquals(3, count.get()); - } - - /** - * Tests the fault injection handler functionality with configuration change event for schema level config. - */ - @Test - public void testFaultInjectHandlerConfigChangeEvent3() throws Exception { - - System.setProperty( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.delay.fixedDelay", - "1"); - System.setProperty( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.delay.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.abort.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.abort.httpStatus", - "421"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName9"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye3"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema3"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts3"); - boolean validAssert; - long timeOld = System.currentTimeMillis(); - - List faultInjectionFeatureList = Arrays.asList(delayFault, abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - try { - validAssert = true; - handler.handle(invocation, ar); - } catch (Exception e) { - validAssert = false; - } - Assert.assertTrue(validAssert); - ArchaiusUtils.setProperty( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.delay.fixedDelay", - 500); - - Holder isAsserted = new Holder<>(false); - handler.handle(invocation, ar -> { - //check whether error code return, defaut is 421. - isAsserted.value = true; - assertEquals(421, response.getStatusCode()); - assertTrue(response.isFailed()); - long timeNow = System.currentTimeMillis(); - //if really time delay is added it should be greater than 5s. - Assert.assertTrue((timeNow - timeOld) >= 500); - }); - Assert.assertTrue(isAsserted.value); - - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove( - "servicecomb.governance.Consumer.carts3.schemas.testSchema3.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName9"); - assertEquals(3, count.get()); - } - - /** - * Tests the fault injection handler functionality with configuration change event for service level config. - */ - @Test - public void testFaultInjectHandlerConfigChangeEvent4() throws Exception { - System.setProperty("servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.delay.fixedDelay", "1"); - - System.setProperty( - "servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.delay.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.abort.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.abort.httpStatus", - "421"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName10"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts4"); - boolean validAssert; - long timeOld = System.currentTimeMillis(); - - List faultInjectionFeatureList = Arrays.asList(delayFault, abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - try { - validAssert = true; - handler.handle(invocation, ar); - } catch (Exception e) { - validAssert = false; - } - Assert.assertTrue(validAssert); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.delay.fixedDelay", 500); - - Holder isAsserted = new Holder<>(false); - handler.handle(invocation, ar -> { - //check whether error code return, - isAsserted.value = true; - assertEquals(421, response.getStatusCode()); - assertTrue(response.isFailed()); - long timeNow = System.currentTimeMillis(); - //if really time delay is added it should be greater than 5s. - Assert.assertTrue((timeNow - timeOld) >= 500); - }); - Assert.assertTrue(isAsserted.value); - - System.getProperties() - .remove("servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts4.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName10"); - assertEquals(3, count.get()); - } - - /** - * Tests the fault injection handler functionality with configuration change event for service level config. - */ - @Test - public void testFaultInjectHandlerConfigChangeEvent5() throws Exception { - System.setProperty( - "servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.delay.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.delay.fixedDelay", - "10"); - System.setProperty( - "servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.abort.percent", - "100"); - System.setProperty( - "servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.abort.httpStatus", - "500"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName11"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts5"); - boolean validAssert; - - List faultInjectionFeatureList = Arrays.asList(delayFault, abortFault); - handler.setFaultFeature(faultInjectionFeatureList); - - try { - validAssert = true; - handler.handle(invocation, ar); - } catch (Exception e) { - validAssert = false; - } - Assert.assertTrue(validAssert); - ArchaiusUtils - .setProperty("servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.abort.httpStatus", "420"); - - Holder isAsserted = new Holder<>(false); - handler.handle(invocation, ar -> { - isAsserted.value = true; - assertTrue(response.isFailed()); - assertEquals(500, response.getStatusCode()); - assertEquals(420, ar.getStatusCode()); - }); - Assert.assertTrue(isAsserted.value); - - System.getProperties() - .remove("servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.delay.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.abort.percent"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts5.policy.fault.protocols.rest.abort.httpStatus"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName11"); - assertEquals(3, count.get()); - } - - /** - * Tests the fault injection handler functionality with configuration change event for service level config. - */ - @Test - public void testFaultInjectHandlerConfigChangeEvent6() { - System.setProperty("servicecomb.governance.Consumer.carts6.policy.fault.protocols.rest.delay.fixedDelay", "1000"); - - System.setProperty( - "servicecomb.governance.Consumer.carts6.policy.fault.protocols.rest.delay.percent", - "100"); - - Mockito.when(invocation.getMicroserviceQualifiedName()).thenReturn("MicroserviceQualifiedName12"); - Mockito.when(invocation.getTransport()).thenReturn(transport); - Mockito.when(transport.getName()).thenReturn("rest"); - Mockito.when(invocation.getOperationName()).thenReturn("sayBye4"); - Mockito.when(invocation.getSchemaId()).thenReturn("testSchema4"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("carts6"); - - DelayFault delayFault = new DelayFault(); - FaultParam faultParam = new FaultParam(3); - Vertx vertx = VertxUtils.getOrCreateVertxByName("faultinjectionTest", null); - faultParam.setVertx(vertx); - - delayFault.injectFault(invocation, faultParam, ar); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts6.policy.fault.protocols.rest.delay.fixedDelay"); - System.getProperties() - .remove("servicecomb.governance.Consumer.carts6.policy.fault.protocols.rest.delay.percent"); - - AtomicLong count = FaultInjectionUtil.getOperMetTotalReq("restMicroserviceQualifiedName12"); - assertEquals(1, count.get()); - } -} diff --git a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectUtil.java b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectUtil.java index d8c80058597..451d7205eca 100644 --- a/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectUtil.java +++ b/handlers/handler-fault-injection/src/test/java/org/apache/servicecomb/faultinjection/TestFaultInjectUtil.java @@ -18,10 +18,9 @@ package org.apache.servicecomb.faultinjection; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /** * Tests the fault inject util functionality. @@ -29,13 +28,8 @@ public class TestFaultInjectUtil { @Test public void testFaultInjectUtil() { - AtomicLong count1 = FaultInjectionUtil.getOperMetTotalReq("test"); - Assert.assertEquals(1, count1.get()); - count1.incrementAndGet(); - AtomicLong count2 = FaultInjectionUtil.getOperMetTotalReq("test"); - Assert.assertEquals(2, count2.get()); FaultInjectionUtil.setConfigCenterValue("sayHi", new AtomicInteger(123)); int value = FaultInjectionUtil.getConfigCenterMap().get("sayHi").get(); - Assert.assertEquals(123, value); + Assertions.assertEquals(123, value); } } diff --git a/handlers/handler-flowcontrol-qps/pom.xml b/handlers/handler-flowcontrol-qps/pom.xml index d986c897027..eb5d63a0993 100644 --- a/handlers/handler-flowcontrol-qps/pom.xml +++ b/handlers/handler-flowcontrol-qps/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb handlers - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT handler-flowcontrol-qps Java Chassis::Handlers::Flow Control QPS @@ -31,13 +31,13 @@ java-chassis-core - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java index 807842850d2..8325352d726 100644 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/Config.java @@ -17,14 +17,10 @@ package org.apache.servicecomb.qps; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicBooleanProperty; -import com.netflix.config.DynamicPropertyFactory; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; public final class Config { - private static final Logger LOGGER = LoggerFactory.getLogger(Config.class); + public static final String CONFIG_PREFIX = "servicecomb.flowcontrol."; public static final String STRATEGY_KEY = "servicecomb.flowcontrol.strategy"; @@ -56,29 +52,15 @@ public final class Config { public static Config INSTANCE = new Config(); - private final DynamicBooleanProperty consumerEnabled = - DynamicPropertyFactory.getInstance().getBooleanProperty(CONSUMER_ENABLED, true); - - private final DynamicBooleanProperty providerEnabled = - DynamicPropertyFactory.getInstance().getBooleanProperty(PROVIDER_ENABLED, true); - public Config() { - consumerEnabled.addCallback(() -> { - boolean newValue = consumerEnabled.get(); - LOGGER.info("{} changed from {} to {}", CONSUMER_ENABLED, consumerEnabled, newValue); - }); - - providerEnabled.addCallback(() -> { - boolean newValue = providerEnabled.get(); - LOGGER.info("{} changed from {} to {}", PROVIDER_ENABLED, providerEnabled, newValue); - }); + } public boolean isConsumerEnabled() { - return consumerEnabled.get(); + return LegacyPropertyFactory.getBooleanProperty(CONSUMER_ENABLED, true); } public boolean isProviderEnabled() { - return providerEnabled.get(); + return LegacyPropertyFactory.getBooleanProperty(PROVIDER_ENABLED, true); } } diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerFlowControlFilter.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerFlowControlFilter.java new file mode 100644 index 00000000000..72828b35ccf --- /dev/null +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerFlowControlFilter.java @@ -0,0 +1,72 @@ +/* + * 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.qps; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.core.env.Environment; + +import com.google.common.annotations.VisibleForTesting; + +public class ConsumerFlowControlFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private final QpsControllerManager qpsControllerMgr; + + public ConsumerFlowControlFilter(Environment environment) { + qpsControllerMgr = new QpsControllerManager(false, environment); + } + + @VisibleForTesting + public QpsControllerManager getQpsControllerMgr() { + return qpsControllerMgr; + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1990; + } + + @Override + public String getName() { + return "consumer-flow-control"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (!Config.INSTANCE.isConsumerEnabled()) { + return nextNode.onFilter(invocation); + } + + QpsStrategy qpsStrategy = qpsControllerMgr.getOrCreate(invocation.getMicroserviceName(), invocation); + if (qpsStrategy.isLimitNewRequest()) { + CommonExceptionData errorData = new CommonExceptionData( + "consumer request rejected by flow control."); + return CompletableFuture.failedFuture(new InvocationException(QpsConst.TOO_MANY_REQUESTS_STATUS, errorData)); + } + + return nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java deleted file mode 100644 index 1d8131115bf..00000000000 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ConsumerQpsFlowControlHandler.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.qps; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -/** - * For qps flow control on consumer side. - * Support 3 levels of microservice/schema/operation. - */ -public class ConsumerQpsFlowControlHandler implements Handler { - private final QpsControllerManager qpsControllerMgr = new QpsControllerManager(false); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - if (!Config.INSTANCE.isConsumerEnabled()) { - invocation.next(asyncResp); - return; - } - - QpsStrategy qpsStrategy = qpsControllerMgr.getOrCreate(invocation.getMicroserviceName(), invocation); - if (qpsStrategy.isLimitNewRequest()) { - // return http status 429 - CommonExceptionData errorData = new CommonExceptionData("rejected by qps flowcontrol"); - asyncResp.consumerFail( - new InvocationException(QpsConst.TOO_MANY_REQUESTS_STATUS, errorData)); - return; - } - - invocation.next(asyncResp); - } -} diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/FlowControlQpsConfiguration.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/FlowControlQpsConfiguration.java new file mode 100644 index 00000000000..d5fd7702cd1 --- /dev/null +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/FlowControlQpsConfiguration.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.qps; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +@ConditionalOnProperty(value = FlowControlQpsConfiguration.FLOW_CONTROL_ENABLED, + havingValue = "true") +public class FlowControlQpsConfiguration { + public static final String FLOW_CONTROL_PREFIX = "servicecomb.flowcontrol"; + + public static final String FLOW_CONTROL_ENABLED = FLOW_CONTROL_PREFIX + ".enabled"; + + @Bean + public ProviderFlowControlFilter scbProviderFlowControlFilter(Environment environment) { + return new ProviderFlowControlFilter(environment); + } + + @Bean + public ConsumerFlowControlFilter scbConsumerFlowControlFilter(Environment environment) { + return new ConsumerFlowControlFilter(environment); + } +} diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderFlowControlFilter.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderFlowControlFilter.java new file mode 100644 index 00000000000..00f78f126f1 --- /dev/null +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderFlowControlFilter.java @@ -0,0 +1,72 @@ +/* + * 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.qps; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.core.env.Environment; + +import com.google.common.annotations.VisibleForTesting; + +public class ProviderFlowControlFilter extends AbstractFilter implements ProviderFilter { + private final QpsControllerManager qpsControllerMgr; + + public ProviderFlowControlFilter(Environment environment) { + qpsControllerMgr = new QpsControllerManager(true, environment); + } + + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 1990; + } + + @Override + public String getName() { + return "provider-flow-control"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (!Config.INSTANCE.isProviderEnabled()) { + return nextNode.onFilter(invocation); + } + + String microserviceName = invocation.getContext(CoreConst.SRC_MICROSERVICE); + QpsStrategy qpsStrategy = qpsControllerMgr.getOrCreate(microserviceName, invocation); + if (qpsStrategy.isLimitNewRequest()) { + CommonExceptionData errorData = new CommonExceptionData( + "provider request rejected by flow control."); + return CompletableFuture.failedFuture(new InvocationException(QpsConst.TOO_MANY_REQUESTS_STATUS, errorData)); + } + return nextNode.onFilter(invocation); + } + + @VisibleForTesting + public QpsControllerManager getQpsControllerMgr() { + return qpsControllerMgr; + } +} diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java deleted file mode 100644 index 0abdd47a7a9..00000000000 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/ProviderQpsFlowControlHandler.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.qps; - -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class ProviderQpsFlowControlHandler implements Handler { - private final QpsControllerManager qpsControllerMgr = new QpsControllerManager(true); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - if (invocation.getHandlerIndex() > 0) { - // handlerIndex > 0, which means this handler is executed in handler chain. - // As this flow control logic has been executed in advance, this time it should be ignored. - invocation.next(asyncResp); - return; - } - - // The real executing position of this handler is no longer in handler chain, but in AbstractRestInvocation. - // Therefore, the Invocation#next() method should not be called below. - if (!Config.INSTANCE.isProviderEnabled()) { - return; - } - - String microserviceName = invocation.getContext(Const.SRC_MICROSERVICE); - QpsStrategy qpsStrategy = qpsControllerMgr.getOrCreate(microserviceName, invocation); - isLimitNewRequest(qpsStrategy, asyncResp); - } - - private boolean isLimitNewRequest(QpsStrategy qpsStrategy, AsyncResponse asyncResp) { - if (qpsStrategy.isLimitNewRequest()) { - CommonExceptionData errorData = new CommonExceptionData("rejected by qps flowcontrol"); - asyncResp.producerFail(new InvocationException(QpsConst.TOO_MANY_REQUESTS_STATUS, errorData)); - return true; - } else { - return false; - } - } -} diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsConst.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsConst.java index 6dae2f4133d..ab1713ec497 100644 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsConst.java +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsConst.java @@ -16,7 +16,7 @@ */ package org.apache.servicecomb.qps; -import javax.ws.rs.core.Response.StatusType; +import jakarta.ws.rs.core.Response.StatusType; import org.apache.servicecomb.swagger.invocation.context.HttpStatus; diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java index 1e954a65ddb..e4cf5e18457 100644 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/QpsControllerManager.java @@ -17,24 +17,26 @@ package org.apache.servicecomb.qps; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.ConfigurationChangedEvent; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.event.EventManager; import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.qps.strategy.AbstractQpsStrategy; import org.apache.servicecomb.qps.strategy.IStrategyFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; -import com.netflix.config.DynamicProperty; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.eventbus.Subscribe; -public class QpsControllerManager { +public final class QpsControllerManager { private static final Logger LOGGER = LoggerFactory.getLogger(QpsControllerManager.class); public static final String SEPARATOR = "."; @@ -59,7 +61,10 @@ public class QpsControllerManager { private final String globalBucketKey; - public QpsControllerManager(boolean isProvider) { + private final Environment environment; + + public QpsControllerManager(boolean isProvider, Environment environment) { + this.environment = environment; if (isProvider) { limitKeyPrefix = Config.PROVIDER_LIMIT_KEY_PREFIX; bucketKeyPrefix = Config.PROVIDER_BUCKET_KEY_PREFIX; @@ -73,6 +78,24 @@ public QpsControllerManager(boolean isProvider) { } initGlobalQpsController(); + EventManager.register(this); + } + + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + for (String changed : event.getChanged()) { + if (changed.startsWith(Config.CONFIG_PREFIX)) { + configQpsControllerMap.clear(); + qualifiedNameControllerMap.clear(); + initGlobalQpsController(); + break; + } + } + } + + @VisibleForTesting + public Map getQualifiedNameControllerMap() { + return qualifiedNameControllerMap; } public QpsStrategy getOrCreate(String microserviceName, Invocation invocation) { @@ -95,7 +118,8 @@ private String validatedName(String microserviceName) { * Create relevant qpsLimit dynamicProperty and watch the configuration change. * Search and return a valid qpsController. */ - private AbstractQpsStrategy create(String qualifiedNameKey, String microserviceName, + @VisibleForTesting + AbstractQpsStrategy create(String qualifiedNameKey, String microserviceName, Invocation invocation) { createForService(qualifiedNameKey, microserviceName, invocation); String qualifiedAnyServiceName = Config.ANY_SERVICE + qualifiedNameKey.substring(microserviceName.length()); @@ -155,11 +179,6 @@ private AbstractQpsStrategy searchQpsController(String qualifiedNameKey) { return null; } - private boolean keyMatch(String configKey, Entry controllerEntry) { - return controllerEntry.getKey().equals(configKey) - || controllerEntry.getKey().startsWith(configKey + SEPARATOR); - } - private boolean isValidQpsController(AbstractQpsStrategy qpsStrategy) { return null != qpsStrategy && null != qpsStrategy.getQpsLimit(); } @@ -170,74 +189,19 @@ private void createQpsControllerIfNotExist(String configKey) { } LOGGER.info("Create qpsController, configKey = [{}]", configKey); - DynamicProperty limitProperty = DynamicProperty.getInstance(limitKeyPrefix + configKey); - DynamicProperty bucketProperty = DynamicProperty.getInstance(bucketKeyPrefix + configKey); - DynamicProperty strategyProperty = DynamicProperty.getInstance(Config.STRATEGY_KEY); - AbstractQpsStrategy qpsStrategy = chooseStrategy(configKey, limitProperty.getLong(), - bucketProperty.getLong(), strategyProperty.getString()); - - strategyProperty.addCallback(() -> { - AbstractQpsStrategy innerQpsStrategy = chooseStrategy(configKey, limitProperty.getLong(), - bucketProperty.getLong(), strategyProperty.getString()); - configQpsControllerMap.put(configKey, innerQpsStrategy); - LOGGER.info("Global flow control strategy update, value = [{}]", - strategyProperty.getString()); - updateObjMap(configKey); - }); - limitProperty.addCallback(() -> { - qpsStrategy.setQpsLimit(limitProperty.getLong()); - LOGGER.info("Qps limit updated, configKey = [{}], value = [{}]", configKey, - limitProperty.getString()); - updateObjMap(configKey); - }); - bucketProperty.addCallback(() -> { - qpsStrategy.setBucketLimit(bucketProperty.getLong()); - LOGGER.info("bucket limit updated, configKey = [{}], value = [{}]", configKey, - bucketProperty.getString()); - updateObjMap(configKey); - }); + AbstractQpsStrategy qpsStrategy = chooseStrategy(configKey, + environment.getProperty(limitKeyPrefix + configKey, Long.class), + environment.getProperty(bucketKeyPrefix + configKey, Long.class), + environment.getProperty(Config.STRATEGY_KEY)); configQpsControllerMap.put(configKey, qpsStrategy); } - protected void updateObjMap(String configKey) { - Iterator> it = qualifiedNameControllerMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (keyMatch(configKey, entry)) { - AbstractQpsStrategy qpsStrategy = searchQpsController(entry.getKey()); - if (qpsStrategy != null) { - entry.setValue(qpsStrategy); - LOGGER.info("QpsController updated, operationId = [{}], configKey = [{}], qpsLimit = [{}]", - entry.getKey(), qpsStrategy.getKey(), qpsStrategy.getQpsLimit()); - } else { - it.remove(); - } - } - } - } - private void initGlobalQpsController() { - DynamicProperty globalLimitProperty = DynamicProperty.getInstance(globalLimitKey); - DynamicProperty globalBucketProperty = DynamicProperty.getInstance(globalBucketKey); - DynamicProperty globalStrategyProperty = DynamicProperty - .getInstance(Config.STRATEGY_KEY); - globalQpsStrategy = chooseStrategy(globalLimitKey, globalLimitProperty.getLong((long) Integer.MAX_VALUE), - globalBucketProperty.getLong(), globalStrategyProperty.getString()); - globalStrategyProperty.addCallback(() -> { - globalQpsStrategy = chooseStrategy(globalLimitKey, globalLimitProperty.getLong((long) Integer.MAX_VALUE), - globalBucketProperty.getLong(), globalStrategyProperty.getString()); - LOGGER.info("Global flow control strategy update, value = [{}]", - globalStrategyProperty.getString()); - }); - globalLimitProperty.addCallback(() -> { - globalQpsStrategy.setQpsLimit(globalLimitProperty.getLong((long) Integer.MAX_VALUE)); - LOGGER.info("Global qps limit update, value = [{}]", globalLimitProperty.getLong()); - }); - globalBucketProperty.addCallback(() -> { - globalQpsStrategy.setBucketLimit(globalBucketProperty.getLong()); - LOGGER.info("Global bucket limit update, value = [{}]", globalBucketProperty.getLong()); - }); + globalQpsStrategy = chooseStrategy(globalLimitKey, + environment.getProperty(globalLimitKey, Long.class, (long) Integer.MAX_VALUE), + environment.getProperty(globalBucketKey, Long.class), + environment.getProperty(Config.STRATEGY_KEY)); } private AbstractQpsStrategy chooseStrategy(String configKey, Long limit, Long bucket, diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java index f91f87f256e..c95c1ab2cba 100644 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/FixedWindowStrategy.java @@ -18,13 +18,18 @@ import java.util.concurrent.atomic.AtomicLong; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class FixedWindowStrategy extends AbstractQpsStrategy { + private static final Logger LOGGER = LoggerFactory.getLogger(FixedWindowStrategy.class); + // Interval begin time private volatile long msCycleBegin; // Request count between Interval begin and now in one interval - private AtomicLong requestCount = new AtomicLong(); + private final AtomicLong requestCount = new AtomicLong(); // request count before an interval private volatile long lastRequestCount = 1; @@ -47,9 +52,13 @@ public boolean isLimitNewRequest() { msCycleBegin = msNow; } - // Configuration update and use is at the situation of multi-threaded concurrency + // Configuration update and use is at the situation of multi-thread concurrency // It is possible that operation level updated to null,but schema level or microservice level does not updated - return newCount - lastRequestCount >= this.getQpsLimit(); + boolean isLimitRequest = newCount - lastRequestCount >= this.getQpsLimit(); + if (isLimitRequest){ + LOGGER.warn("qps flowcontrol open, qpsLimit is {} and tps is {}", this.getQpsLimit(), newCount - lastRequestCount + 1); + } + return isLimitRequest; } @Override diff --git a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java index d65d43b6df4..b8bf65c5e7e 100644 --- a/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java +++ b/handlers/handler-flowcontrol-qps/src/main/java/org/apache/servicecomb/qps/strategy/LeakyBucketStrategy.java @@ -19,6 +19,9 @@ import java.util.concurrent.atomic.AtomicLong; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * leaky bucket algorithm include 2 implementation : * 1. as a meter : it's same as the token bucket. @@ -27,8 +30,10 @@ **/ public class LeakyBucketStrategy extends AbstractQpsStrategy { + private static final Logger LOGGER = LoggerFactory.getLogger(LeakyBucketStrategy.class); + // Request count between Interval begin and now in one interval - private volatile AtomicLong requestCount = new AtomicLong(); + private final AtomicLong requestCount = new AtomicLong(); private volatile long lastTime; @@ -42,7 +47,7 @@ public boolean isLimitNewRequest() { throw new IllegalStateException("should not happen"); } if (this.getBucketLimit() == null) { - this.setBucketLimit(Math.max(2 * this.getQpsLimit(), Integer.MAX_VALUE)); + this.setBucketLimit(Math.min(2 * this.getQpsLimit(), Integer.MAX_VALUE)); } long nowTime = System.currentTimeMillis(); //get the num of te period time @@ -60,6 +65,7 @@ public boolean isLimitNewRequest() { requestCount.incrementAndGet(); return false; } + LOGGER.warn("qps flowcontrol open, qpsLimit is {} and tps is {}", this.getQpsLimit(), requestCount.longValue() + 1); return true; } diff --git a/handlers/handler-flowcontrol-qps/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-flowcontrol-qps/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..731cf581a05 --- /dev/null +++ b/handlers/handler-flowcontrol-qps/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.servicecomb.qps.FlowControlQpsConfiguration diff --git a/handlers/handler-flowcontrol-qps/src/main/resources/config/cse.handler.xml b/handlers/handler-flowcontrol-qps/src/main/resources/config/cse.handler.xml deleted file mode 100644 index c8f3ebb0370..00000000000 --- a/handlers/handler-flowcontrol-qps/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java index 824fc49d293..e2b5f79fa69 100644 --- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java +++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/QpsControllerManagerTest.java @@ -17,268 +17,203 @@ package org.apache.servicecomb.qps; +import java.util.HashMap; + +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.config.InMemoryDynamicPropertiesSource; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.OperationMeta; import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.foundation.common.event.EventManager; import org.apache.servicecomb.qps.strategy.AbstractQpsStrategy; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; - -import mockit.Expectations; -import mockit.Mocked; +import org.springframework.core.env.Environment; public class QpsControllerManagerTest { + static Environment environment = Mockito.mock(Environment.class); - @Before + @BeforeEach public void beforeTest() { - ArchaiusUtils.resetConfig(); + Mockito.when(environment.getProperty(Config.PROVIDER_LIMIT_KEY_GLOBAL, Long.class, (long) Integer.MAX_VALUE)) + .thenReturn((long) Integer.MAX_VALUE); + Mockito.when(environment.getProperty(Config.CONSUMER_LIMIT_KEY_GLOBAL, Long.class, (long) Integer.MAX_VALUE)) + .thenReturn((long) Integer.MAX_VALUE); } - @After + @AfterEach public void afterTest() { - ArchaiusUtils.resetConfig(); + } @Test - public void testGetOrCreate(@Mocked Invocation invocation, @Mocked OperationMeta operationMeta) { - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; - QpsControllerManager testQpsControllerManager = new QpsControllerManager(false); + public void testGetOrCreate() { + Invocation invocation = Mockito.mock(Invocation.class); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); + + QpsControllerManager testQpsControllerManager = new QpsControllerManager(false, environment); initTestQpsControllerManager(false, testQpsControllerManager, invocation, operationMeta); // pojo setConfigWithDefaultPrefix(false, "pojo", 100); QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(100, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation); - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation); - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + + Mockito.when(environment.getProperty("servicecomb.flowcontrol.Consumer.qps.limit.poj.server", + Long.class)).thenReturn(Long.valueOf(10000)); + HashMap updated = new HashMap<>(); + updated.put("servicecomb.flowcontrol.Consumer.qps.limit.poj.server", Long.valueOf(10000)); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); - ArchaiusUtils.setProperty("servicecomb.flowcontrol.Consumer.qps.limit.poj.server", 10000); qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation); - Assert.assertEquals("poj.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(((AbstractQpsStrategy) qpsStrategy).getQpsLimit(), (Long) 10000L); + Assertions.assertEquals("poj.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(((AbstractQpsStrategy) qpsStrategy).getQpsLimit(), (Long) 10000L); + + InMemoryDynamicPropertiesSource.update("servicecomb.flowcontrol.Consumer.qps.limit.poj.server.test", 20000); + Mockito.when(environment.getProperty("servicecomb.flowcontrol.Consumer.qps.limit.poj.server.test", + Long.class)).thenReturn(Long.valueOf(20000)); + updated = new HashMap<>(); + updated.put("servicecomb.flowcontrol.Consumer.qps.limit.poj.server.test", Long.valueOf(20000)); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); - ArchaiusUtils.setProperty("servicecomb.flowcontrol.Consumer.qps.limit.poj.server.test", 20000); qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation); - Assert.assertEquals("poj.server.test", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(((AbstractQpsStrategy) qpsStrategy).getQpsLimit(), (Long) 20000L); + Assertions.assertEquals("poj.server.test", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(((AbstractQpsStrategy) qpsStrategy).getQpsLimit(), (Long) 20000L); testGetOrCreateCommon(false, testQpsControllerManager, invocation, operationMeta); } @Test - public void testGetOrCreateWithGlobalConfig(@Mocked Invocation invocation, @Mocked OperationMeta operationMeta) { - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; - - QpsControllerManager testQpsControllerManager = new QpsControllerManager(true); + public void testGetOrCreateWithGlobalConfig() { + Invocation invocation = Mockito.mock(Invocation.class); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); + + QpsControllerManager testQpsControllerManager = new QpsControllerManager(true, environment); // global - setConfig(Config.PROVIDER_LIMIT_KEY_GLOBAL, 50); + Mockito.when(environment.getProperty(Config.PROVIDER_LIMIT_KEY_GLOBAL, Long.class, + (long) Integer.MAX_VALUE)).thenReturn(50L); + HashMap updated = new HashMap<>(); + updated.put(Config.PROVIDER_LIMIT_KEY_GLOBAL, 50L); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); + QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(50, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation); - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(50, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation); - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(50, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); // pojo setConfigWithDefaultPrefix(true, "pojo", 100); qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(100, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation); - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(50, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation); - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(50 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(50, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); testGetOrCreateCommon(true, testQpsControllerManager, invocation, operationMeta); } @Test - public void testQualifiedNameKey(@Mocked Invocation invocation, @Mocked OperationMeta operationMeta) { - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "schema"; - operationMeta.getSchemaQualifiedName(); - result = "schema.opr"; - } - }; - QpsControllerManager qpsControllerManager = new QpsControllerManager(true); + public void testQualifiedNameKey() { + Invocation invocation = Mockito.mock(Invocation.class); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(invocation.getSchemaId()).thenReturn("schema"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.opr"); + QpsControllerManager qpsControllerManager = new QpsControllerManager(true, environment); QpsStrategy qpsStrategy = qpsControllerManager.getOrCreate("service", invocation); - Assert.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", + Assertions.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); - - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "test_schema"; - operationMeta.getSchemaQualifiedName(); - result = "test_schema.test_opr"; - } - }; + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + + Mockito.when(invocation.getSchemaId()).thenReturn("test_schema"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("test_schema.test_opr"); qpsStrategy = qpsControllerManager.getOrCreate("test_service", invocation); - Assert.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", + Assertions.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); - - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "test_schema"; - operationMeta.getSchemaQualifiedName(); - result = "test-schema.test-opr"; - } - }; + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + + Mockito.when(invocation.getSchemaId()).thenReturn("test_schema"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("test-schema.test-opr"); qpsStrategy = qpsControllerManager.getOrCreate("test-service", invocation); - Assert.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", + Assertions.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); - - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "schema"; - operationMeta.getSchemaQualifiedName(); - result = "schema.opr.tail"; - } - }; + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + + Mockito.when(invocation.getSchemaId()).thenReturn("schema"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.opr.tail"); qpsStrategy = qpsControllerManager.getOrCreate("svc", invocation); - Assert.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", + Assertions.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); - - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "schema.opr2"; - operationMeta.getSchemaQualifiedName(); - result = "schema.opr2.tail"; - } - }; + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + + Mockito.when(invocation.getSchemaId()).thenReturn("schema.opr2"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.opr2.tail"); qpsStrategy = qpsControllerManager.getOrCreate("svc", invocation); - Assert.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", + Assertions.assertEquals("servicecomb.flowcontrol.Provider.qps.global.limit", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); } private void testGetOrCreateCommon(boolean isProvider, QpsControllerManager testQpsControllerManager, Invocation invocation, OperationMeta operationMeta) { - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); + setConfigWithDefaultPrefix(isProvider, "pojo.server", 200); QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(200 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - operationMeta.getSchemaQualifiedName(); - result = "server2.test"; - } - }; + Assertions.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(200, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server2.test"); qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - operationMeta.getSchemaQualifiedName(); - result = "serve.test"; - } - }; + Assertions.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(100, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("serve.test"); qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(100 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals("pojo", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(100, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); // pojo.server.test - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); setConfigWithDefaultPrefix(isProvider, "pojo.server.test", 300); qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo.server.test", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(300 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - operationMeta.getSchemaQualifiedName(); - result = "server.test2"; - } - }; + Assertions.assertEquals("pojo.server.test", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(300, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test2"); qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(200 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - - operationMeta.getSchemaQualifiedName(); - result = "server.tes"; - } - }; + Assertions.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(200, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.tes"); qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); - Assert.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); - Assert.assertTrue(200 == ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); + Assertions.assertEquals("pojo.server", ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(200, (long) ((AbstractQpsStrategy) qpsStrategy).getQpsLimit()); } /** @@ -288,137 +223,82 @@ private void initTestQpsControllerManager(boolean isProvider, QpsControllerManag Invocation invocation, OperationMeta operationMeta) { // pojo.server.test - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); QpsStrategy qpsStrategy = testQpsControllerManager.getOrCreate("pojo", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); // pojo.server.test2 - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.test2"; - } - }; + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test2"); testQpsControllerManager.getOrCreate("pojo", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); // pojo.server.tes - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.tes"; - } - }; + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.tes"); testQpsControllerManager.getOrCreate("pojo", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); // pojo.server2.test - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server2"; - operationMeta.getSchemaQualifiedName(); - result = "server2.test"; - } - }; + Mockito.when(invocation.getSchemaId()).thenReturn("server2"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server2.test"); testQpsControllerManager.getOrCreate("pojo", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); // pojo.serve.test - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "serve"; - operationMeta.getSchemaQualifiedName(); - result = "serve.test"; - } - }; + Mockito.when(invocation.getSchemaId()).thenReturn("serve"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("serve.test"); testQpsControllerManager.getOrCreate("pojo", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); // pojo2.server.test - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); qpsStrategy = testQpsControllerManager.getOrCreate("pojo2", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); // poj.server.test - new Expectations() { - { - invocation.getOperationMeta(); - result = operationMeta; - invocation.getSchemaId(); - result = "server"; - operationMeta.getSchemaQualifiedName(); - result = "server.test"; - } - }; + Mockito.when(invocation.getSchemaId()).thenReturn("server"); + Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("server.test"); qpsStrategy = testQpsControllerManager.getOrCreate("poj", invocation); if (isProvider) { - Assert.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.PROVIDER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } else { - Assert.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); + Assertions.assertEquals(Config.CONSUMER_LIMIT_KEY_GLOBAL, ((AbstractQpsStrategy) qpsStrategy).getKey()); } - Assert.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); + Assertions.assertEquals(Integer.MAX_VALUE, ((AbstractQpsStrategy) qpsStrategy).getQpsLimit().intValue()); } @Test @@ -427,10 +307,10 @@ public void testMock() { OperationMeta operationMeta = invocation.getOperationMeta(); SchemaMeta schemaMeta = operationMeta.getSchemaMeta(); - Assert.assertEquals("service", operationMeta.getMicroserviceName()); - Assert.assertEquals("service.schema.oper", operationMeta.getMicroserviceQualifiedName()); - Assert.assertEquals("schema.oper", operationMeta.getSchemaQualifiedName()); - Assert.assertEquals("schema", schemaMeta.getSchemaId()); + Assertions.assertEquals("service", operationMeta.getMicroserviceName()); + Assertions.assertEquals("service.schema.oper", operationMeta.getMicroserviceQualifiedName()); + Assertions.assertEquals("schema.oper", operationMeta.getSchemaQualifiedName()); + Assertions.assertEquals("schema", schemaMeta.getSchemaId()); } public static Invocation getMockInvocation(String microserviceName, String schemaId, String operationId) { @@ -460,17 +340,16 @@ public static OperationMeta getMockOperationMeta(String microserviceName, String return operationMeta; } - public static void setConfig(String key, int value) { - ArchaiusUtils.setProperty(key, value); - } - private static void setConfigWithDefaultPrefix(boolean isProvider, String key, int value) { String configKey = Config.CONSUMER_LIMIT_KEY_PREFIX + key; if (isProvider) { configKey = Config.PROVIDER_LIMIT_KEY_PREFIX + key; } - ArchaiusUtils.setProperty(configKey, value); + Mockito.when(environment.getProperty(configKey, Long.class)).thenReturn(Long.valueOf(value)); + HashMap updated = new HashMap<>(); + updated.put(configKey, value); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); } private static void deleteConfigWithDefaultPrefix(boolean isProvider, String key) { @@ -479,29 +358,34 @@ private static void deleteConfigWithDefaultPrefix(boolean isProvider, String key configKey = Config.PROVIDER_LIMIT_KEY_PREFIX + key; } - ArchaiusUtils.setProperty(configKey, null); + Mockito.when(environment.getProperty(configKey, Long.class)).thenReturn(null); + HashMap updated = new HashMap<>(); + updated.put(configKey, null); + EventManager.post(ConfigurationChangedEvent.createIncremental(updated)); } @Test public void testDeleteQpsController() { - final String MICROSERVICE_NAME = "springmvcClient"; - final String SCHEMA_ID = "controller"; - final String OPERATION_ID = "add"; - final String CONFIG_KEY = "springmvcClient.controller.add"; + final String microserviceName = "springmvcClient"; + final String schemaId = "controller"; + final String operationId = "add"; + final String configKey = "springmvcClient.controller.add"; - QpsControllerManager testManager = new QpsControllerManager(true); - Invocation testInvocation = getMockInvocation(MICROSERVICE_NAME, SCHEMA_ID, OPERATION_ID); - Mockito.when(testInvocation.getSchemaId()).thenReturn(SCHEMA_ID); + QpsControllerManager testManager = new QpsControllerManager(true, environment); + Invocation testInvocation = getMockInvocation(microserviceName, schemaId, operationId); + Mockito.when(testInvocation.getSchemaId()).thenReturn(schemaId); - QpsStrategy strategy1 = testManager.getOrCreate(MICROSERVICE_NAME, testInvocation); + QpsStrategy strategy1 = testManager.getOrCreate(microserviceName, testInvocation); - setConfigWithDefaultPrefix(true, CONFIG_KEY, 1); + setConfigWithDefaultPrefix(true, configKey, 1); - deleteConfigWithDefaultPrefix(true, CONFIG_KEY); + deleteConfigWithDefaultPrefix(true, configKey); - QpsStrategy strategy2 = testManager.getOrCreate(MICROSERVICE_NAME, testInvocation); + QpsStrategy strategy2 = testManager.getOrCreate(microserviceName, testInvocation); - Assert.assertEquals(strategy1, strategy2); + Assertions.assertEquals(((AbstractQpsStrategy) strategy1).getQpsLimit(), + ((AbstractQpsStrategy) strategy2).getQpsLimit()); + Assertions.assertEquals(((AbstractQpsStrategy) strategy1).getQpsLimit(), Long.valueOf(Integer.MAX_VALUE)); } } diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java deleted file mode 100644 index 9035ba5d406..00000000000 --- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConfig.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.qps; - -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestConfig { - @BeforeClass - public static void classSetup() { - ArchaiusUtils.resetConfig(); - } - - @AfterClass - public static void classTeardown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testEnabled() { - Config.INSTANCE = new Config(); - - Assert.assertEquals(true, Config.INSTANCE.isProviderEnabled()); - ArchaiusUtils.setProperty(Config.PROVIDER_ENABLED, false); - Assert.assertEquals(false, Config.INSTANCE.isProviderEnabled()); - - ArchaiusUtils.setProperty(Config.PROVIDER_ENABLED, null); - Assert.assertEquals(true, Config.INSTANCE.isProviderEnabled()); - - Assert.assertEquals(true, Config.INSTANCE.isConsumerEnabled()); - ArchaiusUtils.setProperty(Config.CONSUMER_ENABLED, false); - Assert.assertEquals(false, Config.INSTANCE.isConsumerEnabled()); - - ArchaiusUtils.setProperty(Config.CONSUMER_ENABLED, null); - Assert.assertEquals(true, Config.INSTANCE.isConsumerEnabled()); - } -} diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java deleted file mode 100644 index 5aef2ddcf1b..00000000000 --- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestConsumerQpsFlowControlHandler.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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.qps; - -import static org.junit.Assert.assertEquals; - -import java.util.concurrent.ConcurrentHashMap; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.qps.strategy.AbstractQpsStrategy; -import org.apache.servicecomb.qps.strategy.FixedWindowStrategy; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import mockit.Deencapsulation; -import mockit.Mock; -import mockit.MockUp; - -public class TestConsumerQpsFlowControlHandler { - - ConsumerQpsFlowControlHandler handler; - - Invocation invocation = Mockito.mock(Invocation.class); - - AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class); - - OperationMeta operationMeta = Mockito.mock(OperationMeta.class); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setUP() { - ArchaiusUtils.resetConfig(); - handler = new ConsumerQpsFlowControlHandler(); - } - - - @After - public void afterTest() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testQpsController() { - AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy(); - qpsStrategy.setKey("abc"); - qpsStrategy.setQpsLimit(100L); - Assert.assertEquals(false, qpsStrategy.isLimitNewRequest()); - - qpsStrategy.setQpsLimit(1L); - Assert.assertEquals(true, qpsStrategy.isLimitNewRequest()); - } - - @Test - public void testHandle() throws Exception { - String key = "svc.schema.opr"; - AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy(); - qpsStrategy.setKey("key"); - qpsStrategy.setQpsLimit(12L); - Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); - Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.opr"); - Mockito.when(invocation.getSchemaId()).thenReturn("schema"); - Mockito.when(invocation.getMicroserviceName()).thenReturn("svc"); - setQpsController(key, qpsStrategy); - new MockUp() { - @Mock - public boolean isLimitNewRequest() { - return true; - } - }; - - new MockUp() { - @Mock - protected QpsStrategy create(String qualifiedNameKey) { - return qpsStrategy; - } - }; - - handler.handle(invocation, asyncResp); - - ArgumentCaptor captor = ArgumentCaptor.forClass(InvocationException.class); - Mockito.verify(asyncResp).consumerFail(captor.capture()); - InvocationException invocationException = captor.getValue(); - assertEquals(QpsConst.TOO_MANY_REQUESTS_STATUS, invocationException.getStatus()); - assertEquals("rejected by qps flowcontrol", - ((CommonExceptionData) invocationException.getErrorData()).getMessage()); - } - - @Test - public void testHandleIsLimitNewRequestAsFalse() throws Exception { - String key = "service.schema.id"; - AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy(); - qpsStrategy.setKey("service"); - qpsStrategy.setQpsLimit(12L); - Mockito.when(invocation.getMicroserviceName()).thenReturn("service"); - Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); - - Mockito.when(operationMeta.getSchemaQualifiedName()).thenReturn("schema.id"); - setQpsController(key, qpsStrategy); - - new MockUp() { - @Mock - public boolean isLimitNewRequest() { - return false; - } - }; - - new MockUp() { - - @Mock - protected QpsStrategy create(String qualifiedNameKey) { - return qpsStrategy; - } - }; - handler.handle(invocation, asyncResp); - - Mockito.verify(invocation).next(asyncResp); - } - - private void setQpsController(String key, QpsStrategy qpsStrategy) { - QpsControllerManager qpsControllerManager = Deencapsulation.getField(handler, "qpsControllerMgr"); - ConcurrentHashMap objMap = Deencapsulation - .getField(qpsControllerManager, "qualifiedNameControllerMap"); - objMap.put(key, qpsStrategy); - } -} diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java deleted file mode 100644 index dfbecfd495c..00000000000 --- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestProviderQpsFlowControlHandler.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * 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.qps; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.times; - -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.qps.strategy.AbstractQpsStrategy; -import org.apache.servicecomb.qps.strategy.FixedWindowStrategy; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mock; -import mockit.MockUp; - -public class TestProviderQpsFlowControlHandler { - ProviderQpsFlowControlHandler handler; - - Invocation invocation = Mockito.mock(Invocation.class); - - AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setUP() { - ArchaiusUtils.resetConfig(); - handler = new ProviderQpsFlowControlHandler(); - ArchaiusUtils.setProperty(Config.PROVIDER_LIMIT_KEY_PREFIX + "test", 1); - } - - @After - public void afterTest() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testGlobalQpsControl(final @Injectable Invocation invocation, - final @Injectable AsyncResponse asyncResp) throws Exception { - new Expectations() { - { - invocation.getHandlerIndex(); - result = 0; - invocation.getContext(Const.SRC_MICROSERVICE); - result = "test"; - invocation.getOperationMeta(); - result = QpsControllerManagerTest.getMockOperationMeta("pojo", "server", "opr"); - invocation.getSchemaId(); - result = "server"; - asyncResp.producerFail((Throwable) any); - result = new RuntimeException("test error"); - } - }; - - ProviderQpsFlowControlHandler gHandler = new ProviderQpsFlowControlHandler(); - gHandler.handle(invocation, asyncResp); - - ArchaiusUtils.setProperty(Config.PROVIDER_LIMIT_KEY_GLOBAL, 3); - - expectedException.expect(RuntimeException.class); - expectedException.expectMessage("test error"); - - gHandler.handle(invocation, asyncResp); - gHandler.handle(invocation, asyncResp); - } - - @Test - public void testQpsController() { - AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy(); - qpsStrategy.setKey("abc"); - qpsStrategy.setQpsLimit(100L); - assertFalse(qpsStrategy.isLimitNewRequest()); - - qpsStrategy.setQpsLimit(1L); - assertTrue(qpsStrategy.isLimitNewRequest()); - } - - @Test - public void testHandleOnSourceMicroserviceNameIsNull() throws Exception { - Mockito.when(invocation.getContext(Const.SRC_MICROSERVICE)).thenReturn(null); - OperationMeta operationMeta = QpsControllerManagerTest.getMockOperationMeta("pojo", "server", "opr"); - Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); - Mockito.when(invocation.getSchemaId()).thenReturn("server"); - // only when handler index <= 0, the qps logic works - Mockito.when(invocation.getHandlerIndex()).thenReturn(0); - ArchaiusUtils.setProperty("servicecomb.flowcontrol.Provider.qps.global.limit", 1); - - handler.handle(invocation, asyncResp); - handler.handle(invocation, asyncResp); - - // Invocation#getContext(String) is only invoked when the qps logic works - Mockito.verify(invocation, times(2)).getContext(Const.SRC_MICROSERVICE); - Mockito.verify(asyncResp, times(1)).producerFail(Mockito.any(Exception.class)); - } - - @Test - public void testHandleOnSourceOnHandlerIndexIsGreaterThan0() throws Exception { - Mockito.when(invocation.getContext(Const.SRC_MICROSERVICE)).thenReturn(null); - - Mockito.when(invocation.getHandlerIndex()).thenReturn(1); - handler.handle(invocation, asyncResp); - handler.handle(invocation, asyncResp); - - Mockito.verify(invocation, times(0)).getContext(Mockito.anyString()); - } - - @Test - public void testHandle() throws Exception { - Mockito.when(invocation.getContext(Const.SRC_MICROSERVICE)).thenReturn("test"); - OperationMeta mockOperationMeta = QpsControllerManagerTest.getMockOperationMeta("pojo", "server", "opr"); - Mockito.when(invocation.getOperationMeta()).thenReturn(mockOperationMeta); - Mockito.when(invocation.getSchemaId()).thenReturn("server"); - - new MockUp() { - @Mock - protected QpsStrategy create(String qualifiedNameKey) { - AbstractQpsStrategy strategy = new FixedWindowStrategy(); - strategy.setKey(qualifiedNameKey); - strategy.setQpsLimit(1L); - return strategy; - } - }; - - handler.handle(invocation, asyncResp); - handler.handle(invocation, asyncResp); - - ArgumentCaptor captor = ArgumentCaptor.forClass(InvocationException.class); - Mockito.verify(asyncResp, times(1)).producerFail(captor.capture()); - - InvocationException invocationException = captor.getValue(); - assertEquals(QpsConst.TOO_MANY_REQUESTS_STATUS, invocationException.getStatus()); - assertEquals("rejected by qps flowcontrol", - ((CommonExceptionData) invocationException.getErrorData()).getMessage()); - } - - @Test - public void testHandleIsLimitNewRequestAsFalse() throws Exception { - Mockito.when(invocation.getContext(Const.SRC_MICROSERVICE)).thenReturn("test"); - OperationMeta mockOperationMeta = QpsControllerManagerTest - .getMockOperationMeta("pojo", "server", "opr"); - Mockito.when(invocation.getOperationMeta()).thenReturn(mockOperationMeta); - Mockito.when(invocation.getSchemaId()).thenReturn("server"); - - new MockUp() { - @Mock - protected QpsStrategy create(String qualifiedNameKey) { - AbstractQpsStrategy strategy = new FixedWindowStrategy(); - strategy.setKey(qualifiedNameKey); - strategy.setQpsLimit(1L); - return strategy; - } - }; - handler.handle(invocation, asyncResp); - - Mockito.verify(invocation, times(0)).next(asyncResp); - Mockito.verify(asyncResp, times(0)).producerFail(Mockito.any(Exception.class)); - } -} diff --git a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java index 04c6f028646..f34b6c5a261 100644 --- a/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java +++ b/handlers/handler-flowcontrol-qps/src/test/java/org/apache/servicecomb/qps/TestQpsStrategy.java @@ -20,12 +20,12 @@ import org.apache.servicecomb.qps.strategy.AbstractQpsStrategy; import org.apache.servicecomb.qps.strategy.FixedWindowStrategy; import org.apache.servicecomb.qps.strategy.LeakyBucketStrategy; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /** - * @Author GuoYl123 - * @Date 2020/7/16 + * @author GuoYl123 + * @since 2020/7/16 **/ public class TestQpsStrategy { @@ -34,10 +34,10 @@ public void testFixedWindowStrategy() { AbstractQpsStrategy qpsStrategy = new FixedWindowStrategy(); qpsStrategy.setKey("abc"); qpsStrategy.setQpsLimit(100L); - Assert.assertEquals(false, qpsStrategy.isLimitNewRequest()); + Assertions.assertFalse(qpsStrategy.isLimitNewRequest()); qpsStrategy.setQpsLimit(1L); - Assert.assertEquals(true, qpsStrategy.isLimitNewRequest()); + Assertions.assertTrue(qpsStrategy.isLimitNewRequest()); } @@ -46,11 +46,11 @@ public void testLeakyBucketStrategy() { LeakyBucketStrategy qpsStrategy = new LeakyBucketStrategy(); qpsStrategy.setKey("abc"); qpsStrategy.setQpsLimit(100L); - Assert.assertEquals(false, qpsStrategy.isLimitNewRequest()); + Assertions.assertFalse(qpsStrategy.isLimitNewRequest()); qpsStrategy.setQpsLimit(1L); qpsStrategy.setBucketLimit(1L); - Assert.assertEquals(true, qpsStrategy.isLimitNewRequest()); + Assertions.assertTrue(qpsStrategy.isLimitNewRequest()); } } diff --git a/handlers/handler-flowcontrol-qps/src/test/resources/log4j.properties b/handlers/handler-flowcontrol-qps/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/handlers/handler-flowcontrol-qps/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/handlers/handler-governance/README.md b/handlers/handler-governance/README.md index 3a9db2ff26a..b6a237f6510 100644 --- a/handlers/handler-governance/README.md +++ b/handlers/handler-governance/README.md @@ -1,3 +1,3 @@ -Enable governance features by handler. +Enable governance features by handler. -Governance can be enabled in any different process layer, enable it in handler is most portable way. \ No newline at end of file +Governance can be enabled in any different process layer, enable it in handler is most portable way. diff --git a/handlers/handler-governance/pom.xml b/handlers/handler-governance/pom.xml index 4b0c7f85817..7db533e562e 100644 --- a/handlers/handler-governance/pom.xml +++ b/handlers/handler-governance/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb handlers - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT handler-governance @@ -51,13 +51,13 @@ test - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerGovernanceHandler.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerGovernanceHandler.java deleted file mode 100644 index e52e4d21744..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerGovernanceHandler.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * 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.handler.governance; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Supplier; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.provider.consumer.SyncResponseExecutor; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.governance.handler.RetryHandler; -import org.apache.servicecomb.governance.marker.GovernanceRequest; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.github.resilience4j.decorators.Decorators; -import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; -import io.github.resilience4j.retry.Retry; - -public class ConsumerGovernanceHandler implements Handler { - private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerGovernanceHandler.class); - - private RetryHandler retryHandler = BeanUtils.getBean(RetryHandler.class); - - private static final ScheduledExecutorService RETRY_POOL = Executors.newScheduledThreadPool(2, new ThreadFactory() { - private AtomicInteger count = new AtomicInteger(0); - - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r, "governance-retry-pool-thread-" + count.getAndIncrement()); - // avoid block shutdown - thread.setDaemon(true); - return thread; - } - }); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - Supplier> next = createBusinessCompletionStageSupplier(invocation); - DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); - GovernanceRequest request = MatchType.createGovHttpRequest(invocation); - - try { - ServiceCombInvocationContext.setInvocationContext(invocation); - addRetry(dcs, request); - } finally { - ServiceCombInvocationContext.removeInvocationContext(); - } - - final SyncResponseExecutor originalExecutor; - final Executor newExecutor; - if (invocation.getResponseExecutor() instanceof SyncResponseExecutor) { - originalExecutor = (SyncResponseExecutor) invocation.getResponseExecutor(); - newExecutor = command -> { - // retry的场景,对于同步调用, 同步调用的主线程已经被挂起,无法再主线程中进行重试; - // 重试的场景,主线程等待响应线程唤醒。因此需要转换主线程,响应唤醒新的主线程,在重试逻辑成功后,再唤醒原来的主线程。 - // 重试也不能在网络线程(event-loop)中进行,未被保护的阻塞操作会导致网络线程挂起 - RETRY_POOL.submit(command); - }; - invocation.setResponseExecutor(newExecutor); - } else { - originalExecutor = null; - newExecutor = null; - } - - dcs.get().whenComplete((r, e) -> { - if (e == null) { - if (originalExecutor != null) { - originalExecutor.execute(() -> { - asyncResp.complete(r); - }); - } else { - asyncResp.complete(r); - } - return; - } - - if (originalExecutor != null) { - originalExecutor.execute(() -> { - asyncResp.consumerFail(e); - }); - } else { - asyncResp.consumerFail(e); - } - }); - } - - private void addRetry(DecorateCompletionStage dcs, GovernanceRequest request) { - Retry retry = retryHandler.getActuator(request); - if (retry != null) { - dcs.withRetry(retry, RETRY_POOL); - } - } - - private Supplier> createBusinessCompletionStageSupplier(Invocation invocation) { - final int currentHandler = invocation.getHandlerIndex(); - final AtomicBoolean isRetryHolder = new AtomicBoolean(false); - - return () -> { - CompletableFuture result = new CompletableFuture<>(); - if (isRetryHolder.getAndSet(true)) { - invocation.setHandlerIndex(currentHandler); - LOGGER.info("retry operation {}, trace id {}", - invocation.getOperationMeta().getMicroserviceQualifiedName(), invocation.getTraceId()); - } - try { - invocation.next(response -> { - result.complete(response); - }); - } catch (Exception e) { - result.completeExceptionally(e); - } - return result; - }; - } -} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerInstanceBulkheadFilter.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerInstanceBulkheadFilter.java new file mode 100644 index 00000000000..1b007e111ad --- /dev/null +++ b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerInstanceBulkheadFilter.java @@ -0,0 +1,110 @@ +/* + * 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.handler.governance; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.governance.handler.InstanceBulkheadHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import io.github.resilience4j.bulkhead.Bulkhead; +import io.github.resilience4j.bulkhead.BulkheadFullException; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; +import jakarta.ws.rs.core.Response.Status; + +public class ConsumerInstanceBulkheadFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerInstanceBulkheadFilter.class); + + private final InstanceBulkheadHandler instanceBulkheadHandler; + + @Autowired + public ConsumerInstanceBulkheadFilter(InstanceBulkheadHandler instanceBulkheadHandler) { + this.instanceBulkheadHandler = instanceBulkheadHandler; + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1060; + } + + @Override + public String getName() { + return "instance-bulkhead"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (invocation.getEndpoint() == null) { + return CompletableFuture.failedFuture(new InvocationException(Status.INTERNAL_SERVER_ERROR, + new CommonExceptionData("instance bulkhead should work after load balancer."))); + } + Supplier> next = createBusinessCompletionStageSupplier(invocation, nextNode); + DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + + addBulkhead(dcs, request); + + CompletableFuture future = new CompletableFuture<>(); + + dcs.get().whenComplete((r, e) -> { + if (e == null) { + future.complete(r); + return; + } + + if (e instanceof BulkheadFullException) { + // return 503 so that consumer can retry + future.completeExceptionally(new InvocationException(503, "bulkhead is full and does not permit further calls.", + new CommonExceptionData("bulkhead is full and does not permit further calls."))); + LOGGER.warn("bulkhead is full and does not permit further calls by policy : {}", e.getMessage()); + } else { + future.completeExceptionally(e); + } + }); + + return future; + } + + private void addBulkhead(DecorateCompletionStage dcs, GovernanceRequestExtractor request) { + Bulkhead bulkhead = instanceBulkheadHandler.getActuator(request); + if (bulkhead != null) { + dcs.withBulkhead(bulkhead); + } + } + + private Supplier> createBusinessCompletionStageSupplier(Invocation invocation, + FilterNode nextNode) { + return () -> nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerInstanceIsolationFilter.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerInstanceIsolationFilter.java new file mode 100644 index 00000000000..e60d52fab18 --- /dev/null +++ b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ConsumerInstanceIsolationFilter.java @@ -0,0 +1,129 @@ +/* + * 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.handler.governance; + +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.governance.handler.InstanceIsolationHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import io.github.resilience4j.circuitbreaker.CallNotPermittedException; +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; +import jakarta.ws.rs.core.Response.Status; + +public class ConsumerInstanceIsolationFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerInstanceIsolationFilter.class); + + private final InstanceIsolationHandler instanceIsolationHandler; + + private DiscoveryManager discoveryManager; + + @Autowired + public ConsumerInstanceIsolationFilter(InstanceIsolationHandler instanceIsolationHandler) { + this.instanceIsolationHandler = instanceIsolationHandler; + } + + @Autowired + public void setDiscoveryManager(DiscoveryManager discoveryManager) { + this.discoveryManager = discoveryManager; + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1050; + } + + @Override + public String getName() { + return "instance-isolation"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + if (invocation.getEndpoint() == null) { + return CompletableFuture.failedFuture(new InvocationException(Status.INTERNAL_SERVER_ERROR, + new CommonExceptionData("instance isolation should work after load balancer."))); + } + + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + CircuitBreakerPolicy circuitBreakerPolicy = instanceIsolationHandler.matchPolicy(request); + if (circuitBreakerPolicy != null && circuitBreakerPolicy.isForceOpen()) { + return CompletableFuture.failedFuture(new InvocationException(Status.SERVICE_UNAVAILABLE, + new CommonExceptionData("Policy \" + circuitBreakerPolicy.getName() + \" forced open and deny requests\""))); + } + + Supplier> next = createBusinessCompletionStageSupplier(invocation, nextNode); + DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); + + addCircuitBreaker(dcs, request); + + CompletableFuture future = new CompletableFuture<>(); + + dcs.get().whenComplete((r, e) -> { + if (e == null) { + future.complete(r); + return; + } + + if (e instanceof CallNotPermittedException) { + LOGGER.warn("instance isolation circuitBreaker is open by policy : {}", e.getMessage()); + discoveryManager.onInstanceIsolated(invocation.getEndpoint().getMicroserviceInstance(), + Duration.parse(circuitBreakerPolicy.getWaitDurationInOpenState()).toMillis()); + // return 503 so that consumer can retry + future.complete(Response.failResp(new InvocationException(Status.SERVICE_UNAVAILABLE, + new CommonExceptionData("instance isolation circuitBreaker is open.")))); + } else { + future.completeExceptionally(e); + } + }); + + return future; + } + + private void addCircuitBreaker(DecorateCompletionStage dcs, GovernanceRequestExtractor request) { + CircuitBreaker circuitBreaker = instanceIsolationHandler.getActuator(request); + if (circuitBreaker != null) { + dcs.withCircuitBreaker(circuitBreaker); + } + } + + private Supplier> createBusinessCompletionStageSupplier(Invocation invocation, + FilterNode nextNode) { + return () -> nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/HandlerGovernanceConfiguration.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/HandlerGovernanceConfiguration.java new file mode 100644 index 00000000000..9223146a759 --- /dev/null +++ b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/HandlerGovernanceConfiguration.java @@ -0,0 +1,62 @@ +/* + * 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.handler.governance; + +import org.apache.servicecomb.governance.handler.BulkheadHandler; +import org.apache.servicecomb.governance.handler.CircuitBreakerHandler; +import org.apache.servicecomb.governance.handler.InstanceBulkheadHandler; +import org.apache.servicecomb.governance.handler.InstanceIsolationHandler; +import org.apache.servicecomb.governance.handler.RateLimitingHandler; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(value = HandlerGovernanceConfiguration.GOVERNANCE_ENABLED, + havingValue = "true", matchIfMissing = true) +public class HandlerGovernanceConfiguration { + public static final String GOVERNANCE_PREFIX = "servicecomb.governance"; + + public static final String GOVERNANCE_ENABLED = GOVERNANCE_PREFIX + ".enabled"; + + @Bean + public ConsumerInstanceBulkheadFilter scbConsumerInstanceBulkheadFilter( + InstanceBulkheadHandler instanceBulkheadHandler) { + return new ConsumerInstanceBulkheadFilter(instanceBulkheadHandler); + } + + @Bean + public ConsumerInstanceIsolationFilter scbConsumerInstanceIsolationFilter( + InstanceIsolationHandler instanceIsolationHandler) { + return new ConsumerInstanceIsolationFilter(instanceIsolationHandler); + } + + @Bean + public ProviderBulkheadFilter scbProviderBulkheadFilter(BulkheadHandler bulkheadHandler) { + return new ProviderBulkheadFilter(bulkheadHandler); + } + + @Bean + public ProviderCircuitBreakerFilter scbProviderCircuitBreakerFilter(CircuitBreakerHandler circuitBreakerHandler) { + return new ProviderCircuitBreakerFilter(circuitBreakerHandler); + } + + @Bean + public ProviderRateLimitingFilter scbProviderRateLimitingFilter(RateLimitingHandler rateLimitingHandler) { + return new ProviderRateLimitingFilter(rateLimitingHandler); + } +} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/MatchType.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/MatchType.java deleted file mode 100644 index f9f08bd2bf0..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/MatchType.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.handler.governance; - -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.governance.marker.GovernanceRequest; - -public final class MatchType { - public static final String REST = "rest"; - - public static final String RPC = "rpc"; - - public static GovernanceRequest createGovHttpRequest(Invocation invocation) { - GovernanceRequest request = new GovernanceRequest(); - - if (MatchType.REST.equalsIgnoreCase(invocation.getOperationMeta().getConfig().getGovernanceMatchType())) { - if (invocation.isConsumer()) { - request.setUri( - invocation.getSchemaMeta().getSwagger().getBasePath() + invocation.getOperationMeta().getOperationPath()); - request.setMethod(invocation.getOperationMeta().getHttpMethod()); - request.setHeaders(getHeaderMap(invocation, true)); - return request; - } - request.setUri(invocation.getRequestEx().getRequestURI()); - request.setMethod(invocation.getRequestEx().getMethod()); - request.setHeaders(getHeaderMap(invocation, false)); - return request; - } - - if (invocation.isConsumer()) { - request.setUri(invocation.getOperationMeta().getMicroserviceQualifiedName()); - } else { - request.setUri(invocation.getOperationMeta().getSchemaQualifiedName()); - } - request.setMethod(invocation.getOperationMeta().getHttpMethod()); - request.setHeaders(getHeaderMap(invocation, true)); - - return request; - } - - private static Map getHeaderMap(Invocation invocation, boolean fromContext) { - Map headers = new HashMap<>(); - if (fromContext) { - headers.putAll(invocation.getContext()); - } else { - Enumeration names = invocation.getRequestEx().getHeaderNames(); - while (names.hasMoreElements()) { - String name = names.nextElement(); - if (invocation.getRequestEx().getHeader(name) != null) { - headers.put(name, invocation.getRequestEx().getHeader(name)); - } - } - } - - Map arguments = invocation.getSwaggerArguments(); - if (arguments != null) { - arguments.forEach((k, v) -> { - if (v != null) { - headers.put(k, v.toString()); - } - }); - } - return headers; - } -} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderBulkheadFilter.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderBulkheadFilter.java new file mode 100644 index 00000000000..a68ebf08fb1 --- /dev/null +++ b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderBulkheadFilter.java @@ -0,0 +1,105 @@ +/* + * 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.handler.governance; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.governance.handler.BulkheadHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import io.github.resilience4j.bulkhead.Bulkhead; +import io.github.resilience4j.bulkhead.BulkheadFullException; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; + +public class ProviderBulkheadFilter extends AbstractFilter implements ProviderFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ProviderBulkheadFilter.class); + + private final BulkheadHandler bulkheadHandler; + + @Autowired + public ProviderBulkheadFilter(BulkheadHandler bulkheadHandler) { + this.bulkheadHandler = bulkheadHandler; + } + + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 1880; + } + + @Override + public String getName() { + return "provider-bulkhead"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + + Supplier> next = createBusinessCompletionStageSupplier(invocation, nextNode); + DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + + addBulkhead(dcs, request); + + CompletableFuture future = new CompletableFuture<>(); + + dcs.get().whenComplete((r, e) -> { + if (e == null) { + future.complete(r); + return; + } + + if (e instanceof BulkheadFullException) { + future.completeExceptionally( + new InvocationException(429, "bulkhead is full and does not permit further calls.", + new CommonExceptionData("bulkhead is full and does not permit further calls."))); + LOGGER.warn("bulkhead is full and does not permit further calls by policy : {}", e.getMessage()); + } else { + future.completeExceptionally(e); + } + }); + + return future; + } + + private void addBulkhead(DecorateCompletionStage dcs, GovernanceRequestExtractor request) { + Bulkhead bulkhead = bulkheadHandler.getActuator(request); + if (bulkhead != null) { + dcs.withBulkhead(bulkhead); + } + } + + private Supplier> createBusinessCompletionStageSupplier(Invocation invocation, + FilterNode nextNode) { + return () -> nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderCircuitBreakerFilter.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderCircuitBreakerFilter.java new file mode 100644 index 00000000000..dbc0b8978c6 --- /dev/null +++ b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderCircuitBreakerFilter.java @@ -0,0 +1,103 @@ +/* + * 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.handler.governance; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.governance.handler.CircuitBreakerHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import io.github.resilience4j.circuitbreaker.CallNotPermittedException; +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; + +public class ProviderCircuitBreakerFilter extends AbstractFilter implements ProviderFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ProviderCircuitBreakerFilter.class); + + private final CircuitBreakerHandler circuitBreakerHandler; + + @Autowired + public ProviderCircuitBreakerFilter(CircuitBreakerHandler circuitBreakerHandler) { + this.circuitBreakerHandler = circuitBreakerHandler; + } + + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 1890; + } + + @Override + public String getName() { + return "provider-circuit-breaker"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + Supplier> next = createBusinessCompletionStageSupplier(invocation, nextNode); + DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + + addCircuitBreaker(dcs, request); + + CompletableFuture future = new CompletableFuture<>(); + + dcs.get().whenComplete((r, e) -> { + if (e == null) { + future.complete(r); + return; + } + + if (e instanceof CallNotPermittedException) { + future.completeExceptionally(new InvocationException(429, "circuitBreaker is open.", + new CommonExceptionData("circuitBreaker is open."))); + LOGGER.warn("circuitBreaker is open by policy : {}", e.getMessage()); + } else { + future.completeExceptionally(e); + } + }); + + return future; + } + + private void addCircuitBreaker(DecorateCompletionStage dcs, GovernanceRequestExtractor request) { + CircuitBreaker circuitBreaker = circuitBreakerHandler.getActuator(request); + if (circuitBreaker != null) { + dcs.withCircuitBreaker(circuitBreaker); + } + } + + private Supplier> createBusinessCompletionStageSupplier(Invocation invocation, + FilterNode nextNode) { + return () -> nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderGovernanceHandler.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderGovernanceHandler.java deleted file mode 100644 index e31cfd25efe..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderGovernanceHandler.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.handler.governance; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; -import java.util.function.Supplier; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.governance.handler.BulkheadHandler; -import org.apache.servicecomb.governance.handler.CircuitBreakerHandler; -import org.apache.servicecomb.governance.handler.RateLimitingHandler; -import org.apache.servicecomb.governance.marker.GovernanceRequest; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.github.resilience4j.bulkhead.Bulkhead; -import io.github.resilience4j.bulkhead.BulkheadFullException; -import io.github.resilience4j.circuitbreaker.CallNotPermittedException; -import io.github.resilience4j.circuitbreaker.CircuitBreaker; -import io.github.resilience4j.decorators.Decorators; -import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; -import io.github.resilience4j.ratelimiter.RateLimiter; -import io.github.resilience4j.ratelimiter.RequestNotPermitted; - -public class ProviderGovernanceHandler implements Handler { - private static final Logger LOGGER = LoggerFactory.getLogger(ProviderGovernanceHandler.class); - - private RateLimitingHandler rateLimitingHandler = BeanUtils.getBean(RateLimitingHandler.class); - - private CircuitBreakerHandler circuitBreakerHandler = BeanUtils.getBean(CircuitBreakerHandler.class); - - private BulkheadHandler bulkheadHandler = BeanUtils.getBean(BulkheadHandler.class); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - - Supplier> next = createBusinessCompletionStageSupplier(invocation); - DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); - GovernanceRequest request = MatchType.createGovHttpRequest(invocation); - - try { - ServiceCombInvocationContext.setInvocationContext(invocation); - addRateLimiting(dcs, request); - addCircuitBreaker(dcs, request); - addBulkhead(dcs, request); - } finally { - ServiceCombInvocationContext.removeInvocationContext(); - } - - dcs.get().whenComplete((r, e) -> { - if (e == null) { - asyncResp.complete(r); - return; - } - - if (e instanceof RequestNotPermitted) { - asyncResp.complete( - Response.failResp(new InvocationException(429, "rate limited.", new CommonExceptionData("rate limited.")))); - LOGGER.warn("the request is rate limit by policy : {}", e.getMessage()); - } else if (e instanceof CallNotPermittedException) { - asyncResp.complete( - Response.failResp(new InvocationException(429, "circuitBreaker is open.", - new CommonExceptionData("circuitBreaker is open.")))); - LOGGER.warn("circuitBreaker is open by policy : {}", e.getMessage()); - } else if (e instanceof BulkheadFullException) { - asyncResp.complete( - Response.failResp(new InvocationException(429, "bulkhead is full and does not permit further calls.", - new CommonExceptionData("bulkhead is full and does not permit further calls.")))); - LOGGER.warn("bulkhead is full and does not permit further calls by policy : {}", e.getMessage()); - } else { - asyncResp.complete(Response.createProducerFail(e)); - } - }); - } - - private void addBulkhead(DecorateCompletionStage dcs, GovernanceRequest request) { - Bulkhead bulkhead = bulkheadHandler.getActuator(request); - if (bulkhead != null) { - dcs.withBulkhead(bulkhead); - } - } - - private void addCircuitBreaker(DecorateCompletionStage dcs, GovernanceRequest request) { - CircuitBreaker circuitBreaker = circuitBreakerHandler.getActuator(request); - if (circuitBreaker != null) { - dcs.withCircuitBreaker(circuitBreaker); - } - } - - private void addRateLimiting(DecorateCompletionStage dcs, GovernanceRequest request) { - RateLimiter rateLimiter = rateLimitingHandler.getActuator(request); - if (rateLimiter != null) { - dcs.withRateLimiter(rateLimiter); - } - } - - private Supplier> createBusinessCompletionStageSupplier(Invocation invocation) { - return () -> { - CompletableFuture result = new CompletableFuture<>(); - try { - invocation.next(response -> { - if (response.isFailed()) { - // For failed response, create a fail to make circuit breaker work. - // Users application maybe much complicated than this simple logic, - // while they need to customize which error will cause circuit breaker. - result.completeExceptionally(response.getResult()); - } else { - result.complete(response); - } - }); - } catch (Exception e) { - result.completeExceptionally(e); - } - return result; - }; - } -} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderRateLimitingFilter.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderRateLimitingFilter.java new file mode 100644 index 00000000000..732fcf48ab5 --- /dev/null +++ b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ProviderRateLimitingFilter.java @@ -0,0 +1,105 @@ +/* + * 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.handler.governance; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.function.Supplier; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.governance.handler.RateLimitingHandler; +import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import io.github.resilience4j.decorators.Decorators; +import io.github.resilience4j.decorators.Decorators.DecorateCompletionStage; +import io.github.resilience4j.ratelimiter.RateLimiter; +import io.github.resilience4j.ratelimiter.RequestNotPermitted; + +public class ProviderRateLimitingFilter extends AbstractFilter implements ProviderFilter, EdgeFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(ProviderRateLimitingFilter.class); + + private final RateLimitingHandler rateLimitingHandler; + + @Autowired + public ProviderRateLimitingFilter(RateLimitingHandler rateLimitingHandler) { + this.rateLimitingHandler = rateLimitingHandler; + } + + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER - 1900; + } + + @Override + public String getName() { + return "rate-limiting"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + + Supplier> next = createBusinessCompletionStageSupplier(invocation, nextNode); + DecorateCompletionStage dcs = Decorators.ofCompletionStage(next); + GovernanceRequestExtractor request = MatchType.createGovHttpRequest(invocation); + + addRateLimiting(dcs, request); + + CompletableFuture future = new CompletableFuture<>(); + + dcs.get().whenComplete((r, e) -> { + if (e == null) { + future.complete(r); + return; + } + + if (e instanceof RequestNotPermitted) { + future.completeExceptionally( + new InvocationException(429, "rate limited.", new CommonExceptionData("rate limited."))); + LOGGER.warn("the request is rate limit by policy : {}", e.getMessage()); + } else { + future.completeExceptionally(e); + } + }); + + return future; + } + + private void addRateLimiting(DecorateCompletionStage dcs, GovernanceRequestExtractor request) { + RateLimiter rateLimiter = rateLimitingHandler.getActuator(request); + if (rateLimiter != null) { + dcs.withRateLimiter(rateLimiter); + } + } + + private Supplier> createBusinessCompletionStageSupplier(Invocation invocation, + FilterNode nextNode) { + return () -> nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombConfigurationEventAdapter.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombConfigurationEventAdapter.java deleted file mode 100644 index 58e41b8e73c..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombConfigurationEventAdapter.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.handler.governance; - - -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.apache.servicecomb.config.event.RefreshGovernanceConfigurationEvent; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.governance.event.GovernanceConfigurationChangedEvent; -import org.apache.servicecomb.governance.event.GovernanceEventManager; -import org.springframework.stereotype.Component; - -import com.google.common.eventbus.Subscribe; - -@Component -public class ServiceCombConfigurationEventAdapter { - public ServiceCombConfigurationEventAdapter() { - EventManager.register(this); - } - - @Subscribe - public void onConfigurationChangedEvent(RefreshGovernanceConfigurationEvent event) { - Set changedKeys = new HashSet<>(); - addMap(changedKeys, event.getEvent().getAdded()); - addMap(changedKeys, event.getEvent().getDeleted()); - addMap(changedKeys, event.getEvent().getChanged()); - addMap(changedKeys, event.getEvent().getComplete()); - GovernanceConfigurationChangedEvent newEvent = new GovernanceConfigurationChangedEvent(changedKeys); - GovernanceEventManager.post(newEvent); - } - - private void addMap(Set keys, Map changed) { - if (changed != null) { - keys.addAll(changed.keySet()); - } - } -} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombInvocationContext.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombInvocationContext.java deleted file mode 100644 index fdedd0a417e..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombInvocationContext.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.handler.governance; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.governance.InvocationContext; -import org.springframework.stereotype.Component; - -@Component -public class ServiceCombInvocationContext implements InvocationContext { - private static final String CONTEXT_KEY = "x-servicecomb-governance-match"; - - private static ThreadLocal contextMgr = new ThreadLocal<>(); - - public static void setInvocationContext( - org.apache.servicecomb.swagger.invocation.context.InvocationContext invocationContext) { - contextMgr.set(invocationContext); - } - - public static void removeInvocationContext() { - contextMgr.remove(); - } - - @Override - public Map getCalculatedMatches() { - Map result = contextMgr.get().getLocalContext(CONTEXT_KEY); - if (result == null) { - return Collections.emptyMap(); - } - return result; - } - - @Override - public void addMatch(String key, Boolean value) { - Map result = contextMgr.get().getLocalContext(CONTEXT_KEY); - if (result == null) { - result = new HashMap<>(); - contextMgr.get().addLocalContext(CONTEXT_KEY, result); - } - result.put(key, value); - } -} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombMicroserviceMeta.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombMicroserviceMeta.java deleted file mode 100644 index 62a9b548b31..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombMicroserviceMeta.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.handler.governance; - -import org.apache.servicecomb.governance.MicroserviceMeta; -import org.apache.servicecomb.registry.RegistrationManager; -import org.springframework.stereotype.Component; - -@Component -public class ServiceCombMicroserviceMeta implements MicroserviceMeta { - @Override - public String getName() { - return RegistrationManager.INSTANCE.getMicroservice().getServiceName(); - } - - @Override - public String getVersion() { - return RegistrationManager.INSTANCE.getMicroservice().getVersion(); - } -} diff --git a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombRetryExtension.java b/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombRetryExtension.java deleted file mode 100644 index e97cdc573c9..00000000000 --- a/handlers/handler-governance/src/main/java/org/apache/servicecomb/handler/governance/ServiceCombRetryExtension.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.handler.governance; - -import io.vertx.core.VertxException; - -import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.springframework.stereotype.Component; - -import java.io.IOException; -import java.net.ConnectException; -import java.net.NoRouteToHostException; -import java.net.SocketTimeoutException; - -@Component -public class ServiceCombRetryExtension extends AbstractRetryExtension { - @Override - protected String extractStatusCode(Object result) { - if (!(result instanceof Response)) { - return null; - } - Response resp = (Response) result; - if (!resp.isFailed()) { - return null; - } - if (InvocationException.class.isInstance(resp.getResult())) { - InvocationException e = resp.getResult(); - return String.valueOf(e.getStatusCode()); - } - return null; - } - - @Override - @SuppressWarnings({"unchecked", "rawtypes"}) - public Class[] retryExceptions() { - return new Class[] { - ConnectException.class, - SocketTimeoutException.class, - IOException.class, - VertxException.class, - NoRouteToHostException.class, - InvocationException.class}; - } -} diff --git a/handlers/handler-governance/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter b/handlers/handler-governance/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter deleted file mode 100644 index 6222972176a..00000000000 --- a/handlers/handler-governance/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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. -# - diff --git a/handlers/handler-governance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-governance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..1e25fbf7679 --- /dev/null +++ b/handlers/handler-governance/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.servicecomb.handler.governance.HandlerGovernanceConfiguration diff --git a/handlers/handler-governance/src/main/resources/config/cse.handler.xml b/handlers/handler-governance/src/main/resources/config/cse.handler.xml deleted file mode 100644 index c7383f0ccf8..00000000000 --- a/handlers/handler-governance/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/handlers/handler-loadbalance/pom.xml b/handlers/handler-loadbalance/pom.xml index 477cc942b76..0fd42dce838 100644 --- a/handlers/handler-loadbalance/pom.xml +++ b/handlers/handler-loadbalance/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb handlers - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT handler-loadbalance @@ -36,40 +36,13 @@ org.apache.servicecomb java-chassis-core - - com.netflix.ribbon - ribbon - - - com.netflix.ribbon - ribbon-loadbalancer - - - com.netflix.ribbon - ribbon-core - - - com.netflix.archaius - archaius-core - - - io.reactivex - rxjava - org.apache.commons commons-lang3 - - - com.netflix.servo - servo-core - provided - - com.google.code.findbugs - annotations - provided + io.github.resilience4j + resilience4j-all org.apache.servicecomb @@ -82,13 +55,18 @@ test - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl + test + + + org.apache.logging.log4j + log4j-core test - log4j - log4j + org.jmockit + jmockit test diff --git a/handlers/handler-loadbalance/readme.MD b/handlers/handler-loadbalance/readme.MD index 335e494ba88..53b4ef30d91 100644 --- a/handlers/handler-loadbalance/readme.MD +++ b/handlers/handler-loadbalance/readme.MD @@ -1,6 +1,6 @@ 参考: https://github.com/Netflix/ribbon/wiki/Working-with-load-balancers LoadBalancer -Rule -Ping +Rule +Ping ServerList ServerListFilter diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/BeansHolder.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/BeansHolder.java deleted file mode 100644 index d70bfb279d2..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/BeansHolder.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.loadbalance; - -import java.util.List; - -import javax.inject.Inject; - -import org.springframework.stereotype.Component; - -@Component -public class BeansHolder { - @Inject - private List extentionsFactories; - - public void init() { - for (ExtensionsFactory extension : this.extentionsFactories) { - ExtensionsManager.addExtentionsFactory(extension); - } - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java index a31895a5b93..87a527c9aff 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/Configuration.java @@ -19,73 +19,73 @@ import java.util.Map; -import org.apache.servicecomb.registry.config.ConfigurePropertyUtils; - -import com.netflix.config.DynamicPropertyFactory; +import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; /** * configuration items - * */ public final class Configuration { //// 2.1 configuration items public static final String ROOT = "servicecomb.loadbalance."; - public static final String SERVER_EXPIRED_IN_SECONDS = "servicecomb.loadbalance.stats.serverExpiredInSeconds"; - - public static final String TIMER_INTERVAL_IN_MILLIS = "servicecomb.loadbalance.stats.timerIntervalInMillis"; + public static final String RULE_STRATEGY_GLOBAL = "servicecomb.loadbalance.strategy.name"; public static final String RULE_STRATEGY_NAME = "strategy.name"; // 2.0 configuration items public static final String ROOT_20 = "ribbon."; - // retry configurations - public static final String RETRY_HANDLER = "retryHandler"; - - public static final String RETRY_ENABLED = "retryEnabled"; - - public static final String RETRY_ON_NEXT = "retryOnNext"; - - public static final String RETRY_ON_SAME = "retryOnSame"; - - // SessionStickinessRule configruation + // SessionStickinessRule configuration public static final String SESSION_TIMEOUT_IN_SECONDS = "SessionStickinessRule.sessionTimeoutInSeconds"; public static final String SUCCESSIVE_FAILED_TIMES = "SessionStickinessRule.successiveFailedTimes"; - private static final double PERCENT = 100; - public static final String FILTER_ISOLATION = "isolation."; - public static final String FILTER_OPEN = "enabled"; - - public static final String FILTER_ERROR_PERCENTAGE = "errorThresholdPercentage"; - - public static final String FILTER_ENABLE_REQUEST = "enableRequestThreshold"; - - public static final String FILTER_RECOVER_IMMEDIATELY_WHEN_SUCCESS = "recoverImmediatelyWhenSuccess"; - - public static final String FILTER_SINGLE_TEST = "singleTestTime"; - public static final String FILTER_MAX_SINGLE_TEST_WINDOW = "maxSingleTestWindow"; - public static final String FILTER_MIN_ISOLATION_TIME = "minIsolationTime"; - - public static final String FILTER_CONTINUOUS_FAILURE_THRESHOLD = "continuousFailureThreshold"; - public static final String TRANSACTIONCONTROL_OPTIONS_PREFIX_PATTERN = "servicecomb.loadbalance.%s.transactionControl.options"; public static final Configuration INSTANCE = new Configuration(); + public record RuleType(int type, String value) { + public static final int TYPE_SCHEMA = 1; + + public static final int TYPE_OPERATION = 2; + + public String getValue() { + return value; + } + + public int getType() { + return type; + } + } + private Configuration() { } - public String getRuleStrategyName(String microservice) { - return getStringProperty(null, - ROOT + microservice + "." + RULE_STRATEGY_NAME, - ROOT + RULE_STRATEGY_NAME); + public RuleType getRuleStrategyName(Invocation invocation) { + String value = getStringProperty(null, ROOT + invocation.getMicroserviceName() + "." + + invocation.getSchemaId() + "." + invocation.getOperationName() + "." + RULE_STRATEGY_NAME); + if (value != null) { + return new RuleType(RuleType.TYPE_OPERATION, value); + } + value = getStringProperty(null, ROOT + invocation.getMicroserviceName() + "." + + invocation.getSchemaId() + "." + RULE_STRATEGY_NAME); + if (value != null) { + return new RuleType(RuleType.TYPE_SCHEMA, value); + } + value = getStringProperty(null, ROOT + invocation.getMicroserviceName() + "." + + RULE_STRATEGY_NAME); + if (value != null) { + return new RuleType(RuleType.TYPE_SCHEMA, value); + } + return new RuleType(RuleType.TYPE_SCHEMA, + getStringProperty("RoundRobin", RULE_STRATEGY_GLOBAL)); } public int getSessionTimeoutInSeconds(String microservice) { @@ -112,86 +112,6 @@ public int getSuccessiveFailedTimes(String microservice) { } } - public String getRetryHandler(String microservice) { - return getStringProperty("default", - ROOT + microservice + "." + RETRY_HANDLER, - ROOT + RETRY_HANDLER); - } - - public boolean isRetryEnabled(String microservice) { - String p = getStringProperty("false", - ROOT + microservice + "." + RETRY_ENABLED, - ROOT + RETRY_ENABLED); - return Boolean.parseBoolean(p); - } - - public int getRetryNextServer(String microservice) { - return getRetryServer(microservice, RETRY_ON_NEXT); - } - - public int getRetrySameServer(String microservice) { - return getRetryServer(microservice, RETRY_ON_SAME); - } - - private int getRetryServer(String microservice, String retryType) { - final int defaultValue = 0; - String p = getStringProperty("0", - ROOT + microservice + "." + retryType, - ROOT + retryType); - try { - int result = Integer.parseInt(p); - if (result > 0) { - return result; - } - return defaultValue; - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public boolean isIsolationFilterOpen(String microservice) { - String p = getStringProperty("true", - ROOT + microservice + "." + FILTER_ISOLATION + FILTER_OPEN, - ROOT + FILTER_ISOLATION + FILTER_OPEN); - return Boolean.parseBoolean(p); - } - - public int getErrorThresholdPercentage(String microservice) { - final int defaultValue = 0; - String p = getStringProperty("0", - ROOT + microservice + "." + FILTER_ISOLATION + FILTER_ERROR_PERCENTAGE, - ROOT + FILTER_ISOLATION + FILTER_ERROR_PERCENTAGE); - try { - int result = Integer.parseInt(p); - if (result <= PERCENT && result > 0) { - return result; - } - return defaultValue; - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public int getEnableRequestThreshold(String microservice) { - return getThreshold(microservice, FILTER_ENABLE_REQUEST); - } - - public int getSingleTestTime(String microservice) { - final int defaultValue = 60000; - String p = getStringProperty("60000", - ROOT + microservice + "." + FILTER_ISOLATION + FILTER_SINGLE_TEST, - ROOT + FILTER_ISOLATION + FILTER_SINGLE_TEST); - try { - int result = Integer.parseInt(p); - if (result >= 0) { - return result; - } - return defaultValue; - } catch (NumberFormatException e) { - return defaultValue; - } - } - public int getMaxSingleTestWindow() { final int defaultValue = 60000; String p = getStringProperty(Integer.toString(defaultValue), @@ -207,62 +127,19 @@ public int getMaxSingleTestWindow() { } } - public int getMinIsolationTime(String microservice) { - final int defaultValue = 3000; // 3 seconds - String p = getStringProperty("3000", - ROOT + microservice + "." + FILTER_ISOLATION + FILTER_MIN_ISOLATION_TIME, - ROOT + FILTER_ISOLATION + FILTER_MIN_ISOLATION_TIME); - try { - int result = Integer.parseInt(p); - if (result >= 0) { - return result; - } - return defaultValue; - } catch (NumberFormatException e) { - return defaultValue; - } - } - - public boolean isRecoverImmediatelyWhenSuccess(String microservice) { - String p = getStringProperty("true", - ROOT + microservice + "." + FILTER_ISOLATION + FILTER_RECOVER_IMMEDIATELY_WHEN_SUCCESS, - ROOT + FILTER_ISOLATION + FILTER_RECOVER_IMMEDIATELY_WHEN_SUCCESS); - return Boolean.parseBoolean(p); - } - public Map getFlowsplitFilterOptions(String microservice) { String keyPrefix = String.format(TRANSACTIONCONTROL_OPTIONS_PREFIX_PATTERN, microservice); - return ConfigurePropertyUtils.getPropertiesWithPrefix(keyPrefix); + return ConfigUtil.stringPropertiesWithPrefix(LegacyPropertyFactory.getEnvironment(), keyPrefix); } public static String getStringProperty(String defaultValue, String... keys) { String property; for (String key : keys) { - property = DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); + property = LegacyPropertyFactory.getStringProperty(key); if (property != null) { return property; } } return defaultValue; } - - public int getContinuousFailureThreshold(String microservice) { - return getThreshold(microservice, FILTER_CONTINUOUS_FAILURE_THRESHOLD); - } - - private int getThreshold(String microservice, String threshold) { - final int defaultValue = 5; - String p = getStringProperty("5", - ROOT + microservice + "." + FILTER_ISOLATION + threshold, - ROOT + FILTER_ISOLATION + threshold); - try { - int result = Integer.parseInt(p); - if (result > 0) { - return result; - } - return defaultValue; - } catch (NumberFormatException e) { - return defaultValue; - } - } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/DefaultRetryExtensionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/DefaultRetryExtensionsFactory.java deleted file mode 100644 index dcb01b2339f..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/DefaultRetryExtensionsFactory.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.loadbalance; - -import java.io.IOException; -import java.net.ConnectException; -import java.net.NoRouteToHostException; -import java.net.SocketTimeoutException; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.springframework.stereotype.Component; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.netflix.client.DefaultLoadBalancerRetryHandler; -import com.netflix.client.RetryHandler; - -import io.vertx.core.VertxException; - -@Component -public class DefaultRetryExtensionsFactory implements ExtensionsFactory { - private static final Collection ACCEPT_KEYS = Lists.newArrayList( - Configuration.RETRY_HANDLER); - - private static final String RETRY_DEFAULT = "default"; - - private static final Collection ACCEPT_VALUES = Lists.newArrayList( - RETRY_DEFAULT); - - private static final Map, List> strictRetriable = - ImmutableMap., List>builder() - .put(ConnectException.class, Arrays.asList()) - .put(SocketTimeoutException.class, Arrays.asList()) - /* - * deal with some special exceptions caused by the server side close the connection - */ - .put(IOException.class, Arrays.asList(new String[] {"Connection reset by peer"})) - .put(VertxException.class, Arrays.asList(new String[] {"Connection was closed"})) - .put(NoRouteToHostException.class, Arrays.asList()) - .build(); - - @Override - public boolean isSupport(String key, String value) { - return ACCEPT_KEYS.contains(key) && ACCEPT_VALUES.contains(value); - } - - public RetryHandler createRetryHandler(String retryName, String microservice) { - return new DefaultLoadBalancerRetryHandler( - Configuration.INSTANCE.getRetrySameServer(microservice), - Configuration.INSTANCE.getRetryNextServer(microservice), true) { - - @Override - public boolean isRetriableException(Throwable e, boolean sameServer) { - boolean retryable = isPresentAsCause(e); - if (!retryable) { - if (e instanceof InvocationException) { - if (((InvocationException) e).getStatusCode() == 503) { - return true; - } - } - } - return retryable; - } - - public boolean isPresentAsCause(Throwable throwableToSearchIn) { - int infiniteLoopPreventionCounter = 10; - while (throwableToSearchIn != null && infiniteLoopPreventionCounter > 0) { - infiniteLoopPreventionCounter--; - for (Entry, List> c : strictRetriable.entrySet()) { - Class key = c.getKey(); - if (key.isAssignableFrom(throwableToSearchIn.getClass())) { - if (c.getValue() == null || c.getValue().isEmpty()) { - return true; - } else { - String msg = throwableToSearchIn.getMessage(); - for (String val : c.getValue()) { - if (val.equals(msg)) { - return true; - } - } - } - } - } - throwableToSearchIn = throwableToSearchIn.getCause(); - } - return false; - } - }; - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java index ce3dca449ab..dc4cd6b6082 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsFactory.java @@ -16,8 +16,6 @@ */ package org.apache.servicecomb.loadbalance; -import com.netflix.client.RetryHandler; - /** * By implements ExtensionsFactory, users can add new extends for rules, filters, etc. */ @@ -27,12 +25,4 @@ public interface ExtensionsFactory { default RuleExt createLoadBalancerRule(String ruleName) { return null; } - - default ServerListFilterExt createServerListFilter(String key, String value, Object... args) { - return null; - } - - default RetryHandler createRetryHandler(String retryName, String microservice) { - return null; - } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java index ff919637093..2187f59e789 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ExtensionsManager.java @@ -16,31 +16,21 @@ */ package org.apache.servicecomb.loadbalance; -import java.util.ArrayList; import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.client.RetryHandler; - public class ExtensionsManager { - private static final Logger LOGGER = LoggerFactory.getLogger(ExtensionsManager.class); - - private static List extentionFactories = new ArrayList<>(); + private final List extensionsFactories; - public static void addExtentionsFactory(ExtensionsFactory factory) { - extentionFactories.add(factory); + public ExtensionsManager(List extensionsFactories) { + this.extensionsFactories = extensionsFactories; } - public static RuleExt createLoadBalancerRule(String microservice) { + public RuleExt createLoadBalancerRule(String ruleStrategyName) { RuleExt rule = null; - for (ExtensionsFactory factory : extentionFactories) { - if (factory.isSupport(Configuration.RULE_STRATEGY_NAME, - Configuration.INSTANCE.getRuleStrategyName(microservice))) { - rule = factory.createLoadBalancerRule( - Configuration.INSTANCE.getRuleStrategyName(microservice)); + for (ExtensionsFactory factory : extensionsFactories) { + if (factory.isSupport(Configuration.RULE_STRATEGY_NAME, ruleStrategyName)) { + rule = factory.createLoadBalancerRule(ruleStrategyName); break; } } @@ -49,21 +39,6 @@ public static RuleExt createLoadBalancerRule(String microservice) { rule = new RoundRobinRuleExt(); } - LOGGER.info("Using load balance rule {} for microservice {}.", rule.getClass().getName(), microservice); return rule; } - - public static RetryHandler createRetryHandler(String microservice) { - RetryHandler handler = null; - for (ExtensionsFactory factory : extentionFactories) { - if (factory.isSupport(Configuration.RETRY_HANDLER, Configuration.INSTANCE.getRetryHandler(microservice))) { - handler = factory.createRetryHandler(Configuration.INSTANCE.getRetryHandler(microservice), microservice); - break; - } - } - - // handler can not be null. handler will be created for each invocation. - LOGGER.debug("Using retry handler {} for microservice {}.", handler.getClass().getName(), microservice); - return handler; - } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalanceConfiguration.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalanceConfiguration.java new file mode 100644 index 00000000000..d65726e0ada --- /dev/null +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalanceConfiguration.java @@ -0,0 +1,74 @@ +/* + * 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.loadbalance; + +import java.util.List; + +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.loadbalance.filter.InstancePropertyDiscoveryFilter; +import org.apache.servicecomb.loadbalance.filter.PriorityInstancePropertyDiscoveryFilter; +import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter; +import org.apache.servicecomb.loadbalance.filter.ZoneAwareDiscoveryFilter; +import org.apache.servicecomb.registry.discovery.DiscoveryTree; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(value = LoadBalanceConfiguration.LOAD_BALANCE_ENABLED, + havingValue = "true", matchIfMissing = true) +public class LoadBalanceConfiguration { + public static final String LOAD_BALANCE_PREFIX = "servicecomb.loadbalance"; + + public static final String LOAD_BALANCE_ENABLED = LOAD_BALANCE_PREFIX + ".enabled"; + + @Bean + public LoadBalanceFilter scbLoadBalanceFilter(ExtensionsManager extensionsManager, DiscoveryTree discoveryTree, + SCBEngine scbEngine) { + return new LoadBalanceFilter(extensionsManager, discoveryTree, scbEngine); + } + + @Bean + public RuleNameExtensionsFactory scbRuleNameExtensionsFactory() { + return new RuleNameExtensionsFactory(); + } + + @Bean + public ExtensionsManager scbExtensionsManager(List extensionsFactories) { + return new ExtensionsManager(extensionsFactories); + } + + @Bean + public PriorityInstancePropertyDiscoveryFilter scbPriorityInstancePropertyDiscoveryFilter() { + return new PriorityInstancePropertyDiscoveryFilter(); + } + + @Bean + public InstancePropertyDiscoveryFilter scbInstancePropertyDiscoveryFilter() { + return new InstancePropertyDiscoveryFilter(); + } + + @Bean + public ServerDiscoveryFilter scbServerDiscoveryFilter() { + return new ServerDiscoveryFilter(); + } + + @Bean + public ZoneAwareDiscoveryFilter scbZoneAwareDiscoveryFilter() { + return new ZoneAwareDiscoveryFilter(); + } +} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalanceFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalanceFilter.java new file mode 100644 index 00000000000..e97263ac465 --- /dev/null +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalanceFilter.java @@ -0,0 +1,301 @@ +/* + * 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.loadbalance; + +import java.net.URI; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.core.Endpoint; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.governance.RetryContext; +import org.apache.servicecomb.foundation.common.cache.VersionedCache; +import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.loadbalance.Configuration.RuleType; +import org.apache.servicecomb.registry.discovery.DiscoveryContext; +import org.apache.servicecomb.registry.discovery.DiscoveryTree; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.eventbus.Subscribe; + +import io.github.resilience4j.core.metrics.Metrics.Outcome; +import jakarta.ws.rs.core.Response.Status; + +public class LoadBalanceFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + public static final String CONTEXT_KEY_LAST_SERVER = "x-context-last-server"; + + // Enough times to make sure to choose a different server in high volume. + private static final int COUNT = 17; + + public static final String CONTEXT_KEY_SERVER_LIST = "x-context-server-list"; + + public static final String SERVICECOMB_SERVER_ENDPOINT = "scb-endpoint"; + + private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalanceFilter.class); + + private final DiscoveryTree discoveryTree; + + // key为grouping filter qualified name + private final Map loadBalancerMap = new ConcurrentHashMapEx<>(); + + private final Object lock = new Object(); + + private final ExtensionsManager extensionsManager; + + private final SCBEngine scbEngine; + + // set endpoint in invocation.localContext + // ignore logic of loadBalance + public boolean supportDefinedEndpoint; + + @Autowired + public LoadBalanceFilter(ExtensionsManager extensionsManager, + DiscoveryTree discoveryTree, SCBEngine scbEngine) { + preCheck(scbEngine); + this.scbEngine = scbEngine; + this.supportDefinedEndpoint = this.scbEngine.getEnvironment() + .getProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", + boolean.class, false); + this.extensionsManager = extensionsManager; + this.discoveryTree = discoveryTree; + EventManager.register(this); + } + + @Subscribe + @SuppressWarnings("unused") + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + Set changedKeys = event.getChanged(); + for (String key : changedKeys) { + if (key.startsWith(Configuration.ROOT)) { + synchronized (lock) { + clearLoadBalancer(); + } + LOGGER.info("clear load balance rule for configuration changed, {}", key); + break; + } + } + } + + private void preCheck(SCBEngine scbEngine) { + // Old configurations check.Just print an error, because configurations may given in dynamic and fail on runtime. + String policyName = scbEngine.getEnvironment() + .getProperty("servicecomb.loadbalance.NFLoadBalancerRuleClassName"); + if (!StringUtils.isEmpty(policyName)) { + LOGGER.error("[servicecomb.loadbalance.NFLoadBalancerRuleClassName] is not supported anymore." + + "use [servicecomb.loadbalance.strategy.name] instead."); + } + + String filterNames = scbEngine.getEnvironment() + .getProperty("servicecomb.loadbalance.serverListFilters"); + if (!StringUtils.isEmpty(filterNames)) { + LOGGER.error( + "Server list implementation changed to SPI. Configuration [servicecomb.loadbalance.serverListFilters]" + + " is not used any more. For ServiceComb defined filters, you do not need config and can " + + "remove this configuration safely. If you define your own filter, need to change it to SPI to make it work."); + } + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER; + } + + @Override + public String getName() { + return "load-balance"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + try { + if (handleSuppliedEndpoint(invocation)) { + invocation.addLocalContext(RetryContext.RETRY_LOAD_BALANCE, false); + return nextNode.onFilter(invocation); + } + } catch (Exception e) { + return CompletableFuture.failedFuture(e); + } + + invocation.addLocalContext(RetryContext.RETRY_LOAD_BALANCE, true); + + LoadBalancer loadBalancer = getOrCreateLoadBalancer(invocation); + + return send(invocation, nextNode, loadBalancer); + } + + // user's can invoke a service by supplying target Endpoint. + // in this case, do not use load balancer, and no stats of server calculated, no retrying. + private boolean handleSuppliedEndpoint(Invocation invocation) throws Exception { + if (invocation.isEdge()) { + return false; + } + if (invocation.getEndpoint() != null) { + return true; + } + + if (supportDefinedEndpoint) { + return defineEndpointAndHandle(invocation); + } + + return false; + } + + private Endpoint parseEndpoint(String endpointUri) throws Exception { + URI formatUri = new URI(endpointUri); + Transport transport = scbEngine.getTransportManager().findTransport(formatUri.getScheme()); + if (transport == null) { + LOGGER.error("not deployed transport {}, ignore {}.", formatUri.getScheme(), endpointUri); + throw new InvocationException(Status.BAD_REQUEST, + "the endpoint's transport is not found."); + } + return new Endpoint(transport, endpointUri); + } + + private boolean defineEndpointAndHandle(Invocation invocation) throws Exception { + Object endpoint = invocation.getLocalContext(SERVICECOMB_SERVER_ENDPOINT); + if (endpoint == null) { + return false; + } + if (endpoint instanceof String) { + // compatible to old usage + endpoint = parseEndpoint((String) endpoint); + } + + invocation.setEndpoint((Endpoint) endpoint); + return true; + } + + private void clearLoadBalancer() { + loadBalancerMap.clear(); + } + + @VisibleForTesting + CompletableFuture send(Invocation invocation, FilterNode filterNode, LoadBalancer chosenLB) { + long time = System.currentTimeMillis(); + ServiceCombServer server = chooseServer(invocation, chosenLB); + if (null == server) { + return CompletableFuture.failedFuture( + new InvocationException(Status.INTERNAL_SERVER_ERROR, + String.format("No available address found for %s/%s.", invocation.getAppId(), + invocation.getMicroserviceName()))); + } + invocation.setEndpoint(server.getEndpoint()); + return filterNode.onFilter(invocation).whenComplete((r, e) -> { + if (e != null || isFailedResponse(r)) { + server.getServerMetrics().record((System.currentTimeMillis() - time), TimeUnit.MILLISECONDS, Outcome.ERROR); + } else { + server.getServerMetrics().record((System.currentTimeMillis() - time), TimeUnit.MILLISECONDS, Outcome.SUCCESS); + } + }); + } + + private ServiceCombServer chooseServer(Invocation invocation, LoadBalancer chosenLB) { + RetryContext retryContext = invocation.getLocalContext(RetryContext.RETRY_CONTEXT); + if (retryContext == null) { + return chosenLB.chooseServer(invocation); + } + + if (!retryContext.isRetry()) { + ServiceCombServer server = chosenLB.chooseServer(invocation); + invocation.addLocalContext(CONTEXT_KEY_LAST_SERVER, server); + return server; + } + + ServiceCombServer lastServer = invocation.getLocalContext(CONTEXT_KEY_LAST_SERVER); + ServiceCombServer nextServer = lastServer; + if (!retryContext.trySameServer()) { + for (int i = 0; i < COUNT; i++) { + ServiceCombServer s = chosenLB.chooseServer(invocation); + if (s == null) { + break; + } + if (!s.equals(nextServer)) { + nextServer = s; + break; + } + } + } + + LOGGER.warn("operation failed {}, retry to instance [{}], last instance [{}], trace id {}", + invocation.getMicroserviceQualifiedName(), + nextServer == null ? "" : nextServer.getEndpoint().getEndpoint(), + lastServer == null ? "" : nextServer.getEndpoint().getEndpoint(), + invocation.getTraceId()); + invocation.addLocalContext(CONTEXT_KEY_LAST_SERVER, nextServer); + return nextServer; + } + + protected boolean isFailedResponse(Response resp) { + if (resp.isFailed()) { + if (resp.getResult() instanceof InvocationException) { + InvocationException e = resp.getResult(); + return e.getStatusCode() == ExceptionFactory.CONSUMER_INNER_STATUS_CODE + || e.getStatusCode() == Status.SERVICE_UNAVAILABLE.getStatusCode() + || e.getStatusCode() == Status.REQUEST_TIMEOUT.getStatusCode(); + } else { + return true; + } + } else { + return false; + } + } + + protected LoadBalancer getOrCreateLoadBalancer(Invocation invocation) { + DiscoveryContext context = new DiscoveryContext(); + context.setInputParameters(invocation); + VersionedCache serversVersionedCache = discoveryTree.discovery(context, + invocation.getAppId(), + invocation.getMicroserviceName()); + invocation.addLocalContext(CONTEXT_KEY_SERVER_LIST, serversVersionedCache.data()); + + RuleType ruleType = Configuration.INSTANCE.getRuleStrategyName(invocation); + String cacheKey; + if (ruleType.getType() == RuleType.TYPE_SCHEMA) { + cacheKey = invocation.getAppId() + "-" + + invocation.getMicroserviceName() + "-" + invocation.getSchemaId(); + } else { + cacheKey = invocation.getAppId() + "-" + + invocation.getMicroserviceName() + "-" + invocation.getSchemaId() + "-" + invocation.getOperationName(); + } + return loadBalancerMap.computeIfAbsent(cacheKey, + key -> createLoadBalancer(ruleType, key, invocation.getMicroserviceName())); + } + + private LoadBalancer createLoadBalancer(RuleType ruleType, String cacheKey, String microserviceName) { + RuleExt rule = extensionsManager.createLoadBalancerRule(ruleType.getValue()); + LOGGER.info("Using load balance rule {} for microservice {}.", rule.getClass().getName(), cacheKey); + return new LoadBalancer(rule, microserviceName); + } +} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java index ca5479a3d1d..d60581ff5f0 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadBalancer.java @@ -26,7 +26,6 @@ import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; -import com.netflix.loadbalancer.LoadBalancerStats; /** * A load balancer with RuleExt and ServerListFilterExt @@ -34,20 +33,17 @@ public class LoadBalancer { private static final Logger LOGGER = LoggerFactory.getLogger(LoadBalancer.class); - private static AtomicInteger id = new AtomicInteger(0); + private static final AtomicInteger id = new AtomicInteger(0); - private RuleExt rule; + private final RuleExt rule; - private LoadBalancerStats lbStats; - - private String microServiceName; + private final String microServiceName; private List filters; public LoadBalancer(RuleExt rule, String microServiceName) { this.microServiceName = microServiceName; this.rule = rule; - this.lbStats = new LoadBalancerStats(microServiceName + id.getAndDecrement()); // load new instances, because filters work on service information this.filters = SPIServiceUtils.loadSortedService(ServerListFilterExt.class); this.rule.setLoadBalancer(this); @@ -55,7 +51,7 @@ public LoadBalancer(RuleExt rule, String microServiceName) { } public ServiceCombServer chooseServer(Invocation invocation) { - List servers = invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST); + List servers = invocation.getLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST); int serversCount = servers.size(); for (ServerListFilterExt filterExt : filters) { if (!filterExt.enabled()) { @@ -71,21 +67,9 @@ public ServiceCombServer chooseServer(Invocation invocation) { if (null == server) { return null; } - ServiceCombServerStats serverStats = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server); - if (serverStats.isIsolated()) { - LOGGER.info("The Service {}'s instance {} has been isolated for a while, give a single test opportunity.", - invocation.getMicroserviceName(), - server.getInstance().getInstanceId()); - LOGGER.info("stats: {}-{}-{}-{}", serverStats.getTotalRequests(), serverStats.getSuccessRequests(), - serverStats.getFailedRequests(), serverStats.getContinuousFailureCount()); - } return server; } - public LoadBalancerStats getLoadBalancerStats() { - return lbStats; - } - public String getMicroServiceName() { return microServiceName; } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceClientConfig.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceClientConfig.java deleted file mode 100644 index ce55008ca34..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceClientConfig.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.loadbalance; - -import com.netflix.client.config.DefaultClientConfigImpl; - -/** - * 配置转换(暂时没有配置项,待新增) - * - */ -public class LoadbalanceClientConfig extends DefaultClientConfigImpl { - private static final String PREFIX = "servicecomb.loadbalance"; - - public LoadbalanceClientConfig(String namespace) { - super(namespace); - loadProperties(PREFIX); - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java deleted file mode 100644 index 3576e3baad0..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/LoadbalanceHandler.java +++ /dev/null @@ -1,472 +0,0 @@ -/* - * 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.loadbalance; - -import java.net.URI; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.ws.rs.core.Response.Status; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.provider.consumer.SyncResponseExecutor; -import org.apache.servicecomb.foundation.common.cache.VersionedCache; -import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx; -import org.apache.servicecomb.foundation.common.utils.ExceptionUtils; -import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryTree; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.ExceptionFactory; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.loadbalancer.ILoadBalancer; -import com.netflix.loadbalancer.Server; -import com.netflix.loadbalancer.reactive.ExecutionContext; -import com.netflix.loadbalancer.reactive.ExecutionInfo; -import com.netflix.loadbalancer.reactive.ExecutionListener; -import com.netflix.loadbalancer.reactive.LoadBalancerCommand; -import com.netflix.loadbalancer.reactive.ServerOperation; - -import rx.Observable; - -/** - * Load balance handler. - */ -public class LoadbalanceHandler implements Handler { - public static final String CONTEXT_KEY_SERVER_LIST = "x-context-server-list"; - - public static final String SERVICECOMB_SERVER_ENDPOINT = "scb-endpoint"; - - // set endpoint in invocation.localContext - // ignore logic of loadBalance - public static final boolean supportDefinedEndpoint = - DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", false).get(); - - // just a wrapper to make sure in retry mode to choose a different server. - class RetryLoadBalancer implements ILoadBalancer { - // Enough times to make sure to choose a different server in high volume. - static final int COUNT = 17; - - Server lastServer = null; - - LoadBalancer delegate; - - RetryLoadBalancer(LoadBalancer delegate) { - this.delegate = delegate; - } - - @Override - public void addServers(List newServers) { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - public Server chooseServer(Object key) { - Invocation invocation = (Invocation) key; - boolean isRetry = null != lastServer; - for (int i = 0; i < COUNT; i++) { - Server s = delegate.chooseServer(invocation); - if (s == null) { - break; - } - if (!s.equals(lastServer)) { - lastServer = s; - break; - } - } - if (isRetry) { - invocation.getTraceIdLogger().info(LOGGER, "retry to instance [{}]", lastServer.getHostPort()); - } - - return lastServer; - } - - @Override - public void markServerDown(Server server) { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - @Deprecated - public List getServerList(boolean availableOnly) { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - public List getReachableServers() { - throw new UnsupportedOperationException("Not implemented."); - } - - @Override - public List getAllServers() { - throw new UnsupportedOperationException("Not implemented."); - } - } - - private static final Logger LOGGER = LoggerFactory.getLogger(LoadbalanceHandler.class); - - private static final ExecutorService RETRY_POOL = Executors.newCachedThreadPool(new ThreadFactory() { - private AtomicInteger count = new AtomicInteger(0); - - @Override - public Thread newThread(Runnable r) { - Thread thread = new Thread(r, "retry-pool-thread-" + count.getAndIncrement()); - // avoid block shutdown - thread.setDaemon(true); - return thread; - } - }); - - private DiscoveryTree discoveryTree = new DiscoveryTree(); - - // key为grouping filter qualified name - private volatile Map loadBalancerMap = new ConcurrentHashMapEx<>(); - - private final Object lock = new Object(); - - private String strategy = null; - - public LoadbalanceHandler(DiscoveryTree discoveryTree) { - this.discoveryTree = discoveryTree; - } - - public LoadbalanceHandler() { - preCheck(); - discoveryTree.loadFromSPI(DiscoveryFilter.class); - discoveryTree.addFilter(new ServerDiscoveryFilter()); - discoveryTree.sort(); - } - - private void preCheck() { - // Old configurations check.Just print an error, because configurations may given in dynamic and fail on runtime. - - String policyName = DynamicPropertyFactory.getInstance() - .getStringProperty("servicecomb.loadbalance.NFLoadBalancerRuleClassName", null) - .get(); - if (!StringUtils.isEmpty(policyName)) { - LOGGER.error("[servicecomb.loadbalance.NFLoadBalancerRuleClassName] is not supported anymore." + - "use [servicecomb.loadbalance.strategy.name] instead."); - } - - String filterNames = Configuration.getStringProperty(null, "servicecomb.loadbalance.serverListFilters"); - if (!StringUtils.isEmpty(filterNames)) { - LOGGER.error( - "Server list implementation changed to SPI. Configuration [servicecomb.loadbalance.serverListFilters]" + - " is not used any more. For ServiceComb defined filters, you do not need config and can " - + "remove this configuration safely. If you define your own filter, need to change it to SPI to make it work."); - } - } - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - AsyncResponse response = asyncResp; - asyncResp = async -> { - ServiceCombServerStats.checkAndReleaseTryingChance(invocation); - response.handle(async); - }; - - if (handleSuppliedEndpoint(invocation, asyncResp)) { - return; - } - - String strategy = Configuration.INSTANCE.getRuleStrategyName(invocation.getMicroserviceName()); - if (!Objects.equals(strategy, this.strategy)) { - //配置变化,需要重新生成所有的lb实例 - synchronized (lock) { - clearLoadBalancer(); - } - } - this.strategy = strategy; - - LoadBalancer loadBalancer = getOrCreateLoadBalancer(invocation); - - if (!Configuration.INSTANCE.isRetryEnabled(invocation.getMicroserviceName())) { - send(invocation, asyncResp, loadBalancer); - } else { - sendWithRetry(invocation, asyncResp, loadBalancer); - } - } - - // user's can invoke a service by supplying target Endpoint. - // in this case, we do not using load balancer, and no stats of server calculated, no retrying. - private boolean handleSuppliedEndpoint(Invocation invocation, - AsyncResponse asyncResp) throws Exception { - if (invocation.getEndpoint() != null) { - invocation.next(asyncResp); - return true; - } - - if (supportDefinedEndpoint) { - return defineEndpointAndHandle(invocation, asyncResp); - } - - return false; - } - - private Endpoint parseEndpoint(String endpointUri) throws Exception { - URI formatUri = new URI(endpointUri); - Transport transport = SCBEngine.getInstance().getTransportManager().findTransport(formatUri.getScheme()); - if (transport == null) { - LOGGER.error("not deployed transport {}, ignore {}.", formatUri.getScheme(), endpointUri); - throw new InvocationException(Status.BAD_REQUEST, - "the endpoint's transport is not found."); - } - return new Endpoint(transport, endpointUri); - } - - private boolean defineEndpointAndHandle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - Object endpoint = invocation.getLocalContext(SERVICECOMB_SERVER_ENDPOINT); - if (endpoint == null) { - return false; - } - if (endpoint instanceof String) { - // compatible to old usage - endpoint = parseEndpoint((String) endpoint); - } - - invocation.setEndpoint((Endpoint) endpoint); - invocation.next(resp -> { - asyncResp.handle(resp); - }); - return true; - } - - private void clearLoadBalancer() { - loadBalancerMap.clear(); - } - - private void send(Invocation invocation, AsyncResponse asyncResp, LoadBalancer chosenLB) throws Exception { - long time = System.currentTimeMillis(); - ServiceCombServer server = chosenLB.chooseServer(invocation); - if (null == server) { - asyncResp.consumerFail(new InvocationException(Status.INTERNAL_SERVER_ERROR, "No available address found.")); - return; - } - chosenLB.getLoadBalancerStats().incrementNumRequests(server); - invocation.setEndpoint(server.getEndpoint()); - invocation.next(resp -> { - // this stats is for WeightedResponseTimeRule - chosenLB.getLoadBalancerStats().noteResponseTime(server, (System.currentTimeMillis() - time)); - if (isFailedResponse(resp)) { - // this stats is for SessionStickinessRule - chosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - } else { - chosenLB.getLoadBalancerStats().incrementActiveRequestsCount(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - } - asyncResp.handle(resp); - }); - } - - private void sendWithRetry(Invocation invocation, AsyncResponse asyncResp, - LoadBalancer chosenLB) throws Exception { - long time = System.currentTimeMillis(); - // retry in loadbalance, 2.0 feature - int currentHandler = invocation.getHandlerIndex(); - - SyncResponseExecutor originalExecutor; - Executor newExecutor; - if (invocation.getResponseExecutor() instanceof SyncResponseExecutor) { - originalExecutor = (SyncResponseExecutor) invocation.getResponseExecutor(); - newExecutor = new Executor() { - @Override - public void execute(Runnable command) { - // retry的场景,对于同步调用, 同步调用的主线程已经被挂起,无法再主线程中进行重试; - // 重试也不能在网络线程(event-loop)中进行,未被保护的阻塞操作会导致网络线程挂起 - RETRY_POOL.submit(command); - } - }; - invocation.setResponseExecutor(newExecutor); - } else { - originalExecutor = null; - newExecutor = null; - } - - ExecutionListener listener = new ExecutionListener() { - @Override - public void onExecutionStart(ExecutionContext context) throws AbortExecutionException { - } - - @Override - public void onStartWithServer(ExecutionContext context, - ExecutionInfo info) throws AbortExecutionException { - } - - @Override - public void onExceptionWithServer(ExecutionContext context, Throwable exception, - ExecutionInfo info) { - context.getRequest().getTraceIdLogger() - .error(LOGGER, "Invoke server failed. Operation {}; server {}; {}-{} msg {}", - context.getRequest().getInvocationQualifiedName(), - context.getRequest().getEndpoint(), - info.getNumberOfPastServersAttempted(), - info.getNumberOfPastAttemptsOnServer(), - ExceptionUtils.getExceptionMessageWithoutTrace(exception)); - } - - @Override - public void onExecutionSuccess(ExecutionContext context, Response response, - ExecutionInfo info) { - if (info.getNumberOfPastServersAttempted() > 0 || info.getNumberOfPastAttemptsOnServer() > 0) { - context.getRequest().getTraceIdLogger().error(LOGGER, "Invoke server success. Operation {}; server {}", - context.getRequest().getInvocationQualifiedName(), - context.getRequest().getEndpoint()); - } - if (originalExecutor != null) { - originalExecutor.execute(() -> { - asyncResp.complete(response); - }); - } else { - asyncResp.complete(response); - } - } - - @Override - public void onExecutionFailed(ExecutionContext context, Throwable finalException, - ExecutionInfo info) { - context.getRequest().getTraceIdLogger().error(LOGGER, "Invoke all server failed. Operation {}, e={}", - context.getRequest().getInvocationQualifiedName(), - ExceptionUtils.getExceptionMessageWithoutTrace(finalException)); - if (originalExecutor != null) { - originalExecutor.execute(() -> { - fail(finalException); - }); - } else { - fail(finalException); - } - } - - private void fail(Throwable finalException) { - int depth = 10; - Throwable t = finalException; - while (depth-- > 0) { - if (t instanceof InvocationException) { - asyncResp.consumerFail(t); - return; - } - t = finalException.getCause(); - } - asyncResp.consumerFail(finalException); - } - }; - List> listeners = new ArrayList<>(0); - listeners.add(listener); - ExecutionContext context = new ExecutionContext<>(invocation, null, null, null); - - LoadBalancerCommand command = LoadBalancerCommand.builder() - .withLoadBalancer(new RetryLoadBalancer(chosenLB)) - .withServerLocator(invocation) - .withRetryHandler(ExtensionsManager.createRetryHandler(invocation.getMicroserviceName())) - .withListeners(listeners) - .withExecutionContext(context) - .build(); - - Observable observable = command.submit(new ServerOperation() { - public Observable call(Server s) { - return Observable.create(f -> { - try { - ServiceCombServer server = (ServiceCombServer) s; - chosenLB.getLoadBalancerStats().incrementNumRequests(s); - invocation.setHandlerIndex(currentHandler); // for retry - invocation.setEndpoint(server.getEndpoint()); - invocation.next(resp -> { - if (isFailedResponse(resp)) { - invocation.getTraceIdLogger().error(LOGGER, "service {}, call error, msg is {}, server is {} ", - invocation.getInvocationQualifiedName(), - ExceptionUtils.getExceptionMessageWithoutTrace((Throwable) resp.getResult()), - s); - chosenLB.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - f.onError(resp.getResult()); - } else { - chosenLB.getLoadBalancerStats().incrementActiveRequestsCount(s); - chosenLB.getLoadBalancerStats().noteResponseTime(s, - (System.currentTimeMillis() - time)); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - f.onNext(resp); - f.onCompleted(); - } - }); - } catch (Exception e) { - invocation.getTraceIdLogger() - .error(LOGGER, "execution error, msg is {}", ExceptionUtils.getExceptionMessageWithoutTrace(e)); - f.onError(e); - } - }); - } - }); - - observable.subscribe(response -> { - }, error -> { - }, () -> { - }); - } - - protected boolean isFailedResponse(Response resp) { - if (resp.isFailed()) { - if (InvocationException.class.isInstance(resp.getResult())) { - InvocationException e = (InvocationException) resp.getResult(); - return e.getStatusCode() == ExceptionFactory.CONSUMER_INNER_STATUS_CODE - || e.getStatusCode() == Status.SERVICE_UNAVAILABLE.getStatusCode() - || e.getStatusCode() == Status.REQUEST_TIMEOUT.getStatusCode(); - } else { - return true; - } - } else { - return false; - } - } - - protected LoadBalancer getOrCreateLoadBalancer(Invocation invocation) { - DiscoveryContext context = new DiscoveryContext(); - context.setInputParameters(invocation); - VersionedCache serversVersionedCache = discoveryTree.discovery(context, - invocation.getAppId(), - invocation.getMicroserviceName(), - invocation.getMicroserviceVersionRule()); - invocation.addLocalContext(CONTEXT_KEY_SERVER_LIST, serversVersionedCache.data()); - - return loadBalancerMap - .computeIfAbsent(serversVersionedCache.name(), name -> createLoadBalancer(invocation.getMicroserviceName())); - } - - private LoadBalancer createLoadBalancer(String microserviceName) { - RuleExt rule = ExtensionsManager.createLoadBalancerRule(microserviceName); - return new LoadBalancer(rule, microserviceName); - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java index 5f8d26c0ff8..318b45f3839 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RandomRuleExt.java @@ -31,7 +31,7 @@ public ServiceCombServer choose(List servers, Invocation invo if (servers.isEmpty()) { return null; } - int index = Math.abs(ThreadLocalRandom.current().nextInt()) % servers.size(); + int index = ThreadLocalRandom.current().nextInt(servers.size()); return servers.get(index); } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java index ce5103976c2..70d467843f3 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RoundRobinRuleExt.java @@ -26,7 +26,7 @@ * A round robin rule */ public class RoundRobinRuleExt implements RuleExt { - private AtomicInteger counter = new AtomicInteger(0); + private final AtomicInteger counter = new AtomicInteger(0); @Override public ServiceCombServer choose(List servers, Invocation invocation) { diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtensionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtensionsFactory.java new file mode 100644 index 00000000000..9d9b0e0da1b --- /dev/null +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtensionsFactory.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.servicecomb.loadbalance; + +import java.util.Collection; + +import com.google.common.collect.Lists; + +public class RuleNameExtensionsFactory implements ExtensionsFactory { + private static final Collection ACCEPT_KEYS = Lists.newArrayList( + Configuration.RULE_STRATEGY_NAME); + + private static final String RULE_RoundRobin = "RoundRobin"; + + private static final String RULE_Random = "Random"; + + private static final String RULE_WeightedResponse = "WeightedResponse"; + + private static final String RULE_SessionStickiness = "SessionStickiness"; + + private static final Collection ACCEPT_VALUES = Lists.newArrayList( + RULE_RoundRobin, + RULE_Random, + RULE_WeightedResponse, + RULE_SessionStickiness); + + @Override + public boolean isSupport(String key, String value) { + return ACCEPT_KEYS.contains(key) && ACCEPT_VALUES.contains(value); + } + + @Override + public RuleExt createLoadBalancerRule(String ruleName) { + if (RULE_RoundRobin.equals(ruleName)) { + return new RoundRobinRuleExt(); + } else if (RULE_Random.equals(ruleName)) { + return new RandomRuleExt(); + } else if (RULE_WeightedResponse.equals(ruleName)) { + return new WeightedResponseTimeRuleExt(); + } else if (RULE_SessionStickiness.equals(ruleName)) { + return new SessionStickinessRule(); + } else { + throw new IllegalStateException("unexpected code to reach here, value is " + ruleName); + } + } +} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java deleted file mode 100644 index 193d125d50a..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/RuleNameExtentionsFactory.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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.loadbalance; - -import java.util.Collection; - -import org.springframework.stereotype.Component; - -import com.google.common.collect.Lists; - -@Component -public class RuleNameExtentionsFactory implements ExtensionsFactory { - private static final Collection ACCEPT_KEYS = Lists.newArrayList( - Configuration.RULE_STRATEGY_NAME); - - private static final String RULE_RoundRobin = "RoundRobin"; - - private static final String RULE_Random = "Random"; - - private static final String RULE_WeightedResponse = "WeightedResponse"; - - private static final String RULE_SessionStickiness = "SessionStickiness"; - - private static final Collection ACCEPT_VALUES = Lists.newArrayList( - RULE_RoundRobin, - RULE_Random, - RULE_WeightedResponse, - RULE_SessionStickiness); - - @Override - public boolean isSupport(String key, String value) { - return ACCEPT_KEYS.contains(key) && ACCEPT_VALUES.contains(value); - } - - @Override - public RuleExt createLoadBalancerRule(String ruleName) { - if (RULE_RoundRobin.equals(ruleName)) { - return new RoundRobinRuleExt(); - } else if (RULE_Random.equals(ruleName)) { - return new RandomRuleExt(); - } else if (RULE_WeightedResponse.equals(ruleName)) { - return new WeightedResponseTimeRuleExt(); - } else if (RULE_SessionStickiness.equals(ruleName)) { - return new SessionStickinessRule(); - } else { - throw new IllegalStateException("unexpected code to reach here, value is " + ruleName); - } - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java index 9dba0046dd8..9d2d07ceb5f 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerListFilterExt.java @@ -28,8 +28,10 @@ * support this. */ public interface ServerListFilterExt { + int ORDER_NORMAL = 0; + default int getOrder() { - return 0; + return ORDER_NORMAL; } default boolean enabled() { diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerMetrics.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerMetrics.java new file mode 100644 index 00000000000..d756ff40300 --- /dev/null +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServerMetrics.java @@ -0,0 +1,39 @@ +/* + * 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.loadbalance; + +import java.util.concurrent.TimeUnit; + +import io.github.resilience4j.core.metrics.FixedSizeSlidingWindowMetrics; +import io.github.resilience4j.core.metrics.Metrics.Outcome; +import io.github.resilience4j.core.metrics.Snapshot; + +/** + * ServiceCombServer states + */ +public class ServerMetrics { + private final FixedSizeSlidingWindowMetrics metrics = new FixedSizeSlidingWindowMetrics(50); + + public Snapshot record(long duration, TimeUnit durationUnit, Outcome outcome) { + return metrics.record(duration, durationUnit, outcome); + } + + public Snapshot getSnapshot() { + return metrics.getSnapshot(); + } +} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java deleted file mode 100644 index bf40ec629ba..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombLoadBalancerStats.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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.loadbalance; - -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.consumer.MicroserviceInstancePing; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.cache.RemovalListener; -import com.netflix.config.DynamicPropertyFactory; - -/** - * Add special stats that com.netflix.loadbalancer.LoadBalancerStats not provided - */ -public class ServiceCombLoadBalancerStats { - private final static Logger LOGGER = LoggerFactory.getLogger(ServiceCombLoadBalancerStats.class); - - private final Map pingView = new ConcurrentHashMap<>(); - - private int serverExpireInSeconds = DynamicPropertyFactory.getInstance() - .getIntProperty(Configuration.SERVER_EXPIRED_IN_SECONDS, 300).get(); - - private long timerIntervalInMillis = DynamicPropertyFactory.getInstance() - .getLongProperty(Configuration.TIMER_INTERVAL_IN_MILLIS, 10000).get(); - - private LoadingCache serverStatsCache; - - private Map serviceCombServers = new ConcurrentHashMap<>(); - - public static ServiceCombLoadBalancerStats INSTANCE; - - private Timer timer; - - static { - INSTANCE = new ServiceCombLoadBalancerStats(); - INSTANCE.init(); - } - - /** - * Should be singleton, use it only for testing - */ - ServiceCombLoadBalancerStats() { - } - - public void markIsolated(ServiceCombServer server, boolean isolated) { - try { - serverStatsCache.get(server).markIsolated(isolated); - } catch (ExecutionException e) { - LOGGER.error("Not expected to happen, maybe a bug.", e); - } - } - - public void markSuccess(ServiceCombServer server) { - try { - serverStatsCache.get(server).markSuccess(); - } catch (ExecutionException e) { - LOGGER.error("Not expected to happen, maybe a bug.", e); - } - } - - public void markFailure(ServiceCombServer server) { - try { - serverStatsCache.get(server).markFailure(); - } catch (ExecutionException e) { - LOGGER.error("Not expected to happen, maybe a bug.", e); - } - } - - public ServiceCombServerStats getServiceCombServerStats(ServiceCombServer server) { - try { - return serverStatsCache.get(server); - } catch (ExecutionException e) { - LOGGER.error("Not expected to happen, maybe a bug.", e); - return null; - } - } - - public ServiceCombServer getServiceCombServer(MicroserviceInstance instance) { - return serviceCombServers.get(instance.getInstanceId()); - } - - @VisibleForTesting - void setServerExpireInSeconds(int sec) { - this.serverExpireInSeconds = sec; - } - - @VisibleForTesting - void setTimerIntervalInMillis(int millis) { - this.timerIntervalInMillis = millis; - } - - @VisibleForTesting - Map getPingView() { - return this.pingView; - } - - void init() { - // for testing - if (timer != null) { - timer.cancel(); - } - if (serverStatsCache != null) { - serverStatsCache.cleanUp(); - } - - pingView.clear(); - - serverStatsCache = - CacheBuilder.newBuilder() - .expireAfterAccess(serverExpireInSeconds, TimeUnit.SECONDS) - .removalListener( - (RemovalListener) notification -> { - ServiceCombServer server = notification.getKey(); - LOGGER.info("stats of instance {} removed, host is {}", - server.getInstance().getInstanceId(), server.getHost()); - pingView.remove(notification.getKey()); - serviceCombServers.remove(notification.getKey()); - }) - .build( - new CacheLoader() { - public ServiceCombServerStats load(ServiceCombServer server) { - ServiceCombServerStats stats = new ServiceCombServerStats(server.getMicroserviceName()); - pingView.put(server, stats); - serviceCombServers.put(server.getInstance().getInstanceId(), server); - return stats; - } - }); - - timer = new Timer("LoadBalancerStatsTimer", true); - timer.schedule(new TimerTask() { - private MicroserviceInstancePing ping = SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class); - - @Override - public void run() { - try { - Map allServers = pingView; - allServers.entrySet().forEach(serviceCombServerServiceCombServerStatsEntry -> { - ServiceCombServer server = serviceCombServerServiceCombServerStatsEntry.getKey(); - ServiceCombServerStats stats = serviceCombServerServiceCombServerStatsEntry.getValue(); - if ((System.currentTimeMillis() - stats.getLastVisitTime() > timerIntervalInMillis) && !ping - .ping(server.getInstance())) { - LOGGER.info("ping mark server {} failure.", server.getInstance().getInstanceId()); - stats.markFailure(); - } - }); - serverStatsCache.cleanUp(); - } catch (Throwable e) { - LOGGER.warn("LoadBalancerStatsTimer error.", e); - } - } - }, timerIntervalInMillis, timerIntervalInMillis); - } -} - diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java index e9d1375b80a..edfdf322f6e 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServer.java @@ -17,65 +17,27 @@ package org.apache.servicecomb.loadbalance; -import java.net.URI; -import java.net.URISyntaxException; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; - -import com.google.common.annotations.VisibleForTesting; -import com.netflix.loadbalancer.Server; +import org.apache.servicecomb.registry.api.DiscoveryInstance; /** - * 服务器抽象,address只有transport识别, LB模块不识别 - * LB模块不提供服务器状态监测,这块功能是由注册中心进行处理的。 + * Server object used for transports and load balancer. * */ -public class ServiceCombServer extends Server { +public class ServiceCombServer { private final Endpoint endpoint; - // 所属服务实例 - private final MicroserviceInstance instance; - private final String microserviceName; - @VisibleForTesting - ServiceCombServer(String microserviceName, Endpoint endpoint, MicroserviceInstance instance) { - super(null); - this.endpoint = endpoint; - this.instance = instance; - this.microserviceName = microserviceName; - - // Different types of Robin Component Rule have different usages for server status and list. - // e.g. RoundRobinRule using getAllServers & alive & readyToServe - // RandomRule using getReachableServers & alive - // WeightedResponseTimeRule using getAllServers & alive - // To make all rules work only on "how to choose a server from alive servers", we do not rely on Robbin defined status - this.setAlive(true); - this.setReadyToServe(true); - } + private final ServerMetrics serverMetrics; - public ServiceCombServer(String microserviceName, Transport transport, CacheEndpoint cacheEndpoint) { - super(null); + public ServiceCombServer(String microserviceName, Endpoint endpoint) { this.microserviceName = microserviceName; - endpoint = new Endpoint(transport, cacheEndpoint.getEndpoint(), cacheEndpoint.getInstance()); - instance = cacheEndpoint.getInstance(); - - // Different types of Robin Component Rule have different usages for server status and list. - // e.g. RoundRobinRule using getAllServers & alive & readyToServe - // RandomRule using getReachableServers & alive - // WeightedResponseTimeRule using getAllServers & alive - // To make all rules work only on "how to choose a server from alive servers", we do not rely on Robbin defined status - this.setAlive(true); - this.setReadyToServe(true); - try { - URI endpointURI = new URI(endpoint.getEndpoint()); - setHost(endpointURI.getHost()); - setPort(endpointURI.getPort()); - } catch (URISyntaxException ignored) { - } + this.endpoint = endpoint; + this.serverMetrics = new ServerMetrics(); } public String getMicroserviceName() { @@ -86,29 +48,36 @@ public Endpoint getEndpoint() { return endpoint; } - public MicroserviceInstance getInstance() { - return instance; + public DiscoveryInstance getInstance() { + return endpoint.getMicroserviceInstance(); } + @Override public String toString() { return endpoint.getEndpoint(); } - // used in LoadBalancerContext public String getHost() { return endpoint.getEndpoint(); } - // take endpoints that belongs to same instance as same server + public ServerMetrics getServerMetrics() { + return serverMetrics; + } + + @Override public boolean equals(Object o) { if (o instanceof ServiceCombServer) { - return this.instance.getInstanceId().equals(((ServiceCombServer) o).instance.getInstanceId()); + return this.getInstance().getInstanceId() + .equals(((ServiceCombServer) o).getInstance().getInstanceId()) + && StringUtils.equals(endpoint.getEndpoint(), ((ServiceCombServer) o).getEndpoint().getEndpoint()); } else { return false; } } + @Override public int hashCode() { - return this.instance.getInstanceId().hashCode(); + return Objects.hash(this.getInstance().getInstanceId(), this.endpoint); } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServerStats.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServerStats.java deleted file mode 100644 index d867da3aa29..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/ServiceCombServerStats.java +++ /dev/null @@ -1,229 +0,0 @@ -/* - * 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.loadbalance; - -import java.time.Clock; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.utils.TimeUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Special stats that com.netflix.loadbalancer.ServerStats not provided. - * - * In concurrent scenarios, we can't count statistics accurately, but it's fine. - */ -public class ServiceCombServerStats { - private static final long TIME_WINDOW_IN_MILLISECONDS = 60000; - - private static final Logger LOGGER = LoggerFactory.getLogger(ServiceCombServerStats.class); - - private final Object lock = new Object(); - - /** - * There is not more than 1 server allowed to stay in TRYING status concurrently. - * This flag is designed to ensure such mechanism. And it makes the ServiceCombServerStats stateful. - * Therefore, the flag should be reset correctly after the trying server gets handled. - */ - static AtomicReference globalAllowIsolatedServerTryingFlag = new AtomicReference<>(); - - Clock clock; - - private long lastWindow; - - private AtomicLong continuousFailureCount; - - private long lastVisitTime; - - private long lastActiveTime; - - private long isolatedTime; - - private AtomicLong totalRequests; - - private AtomicLong successRequests; - - private AtomicLong failedRequests; - - private boolean isolated = false; - - private String microserviceName; - - public ServiceCombServerStats(String microserviceName) { - this(microserviceName, TimeUtils.getSystemDefaultZoneClock()); - } - - public ServiceCombServerStats(String microserviceName, Clock clock) { - this.clock = clock; - this.microserviceName = microserviceName; - init(); - } - - private void init() { - lastWindow = clock.millis(); - continuousFailureCount = new AtomicLong(0); - lastVisitTime = clock.millis(); - lastActiveTime = clock.millis(); - totalRequests = new AtomicLong(0L); - successRequests = new AtomicLong(0L); - failedRequests = new AtomicLong(0L); - } - - public static boolean isolatedServerCanTry() { - TryingIsolatedServerMarker marker = globalAllowIsolatedServerTryingFlag.get(); - if (marker == null) { - return true; - } - return marker.isOutdated(); - } - - /** - * Applying for a trying chance for the isolated server. There is only 1 trying chance globally concurrently. - * - * @return true if the chance is applied successfully, otherwise false - */ - public static boolean applyForTryingChance(Invocation invocation) { - TryingIsolatedServerMarker marker = globalAllowIsolatedServerTryingFlag.get(); - if (marker == null) { - return globalAllowIsolatedServerTryingFlag.compareAndSet(null, new TryingIsolatedServerMarker(invocation)); - } - if (marker.isOutdated()) { - return globalAllowIsolatedServerTryingFlag.compareAndSet(marker, new TryingIsolatedServerMarker(invocation)); - } - return false; - } - - public static void checkAndReleaseTryingChance(Invocation invocation) { - TryingIsolatedServerMarker marker = globalAllowIsolatedServerTryingFlag.get(); - if (marker == null || marker.getInvocation() != invocation) { - return; - } - globalAllowIsolatedServerTryingFlag.compareAndSet(marker, null); - } - - public void markIsolated(boolean isolated) { - this.isolated = isolated; - this.isolatedTime = System.currentTimeMillis(); - } - - public void markSuccess() { - long time = clock.millis(); - ensureWindow(time); - - if (isolated) { - if (Configuration.INSTANCE.isRecoverImmediatelyWhenSuccess(microserviceName) - && time - this.isolatedTime > Configuration.INSTANCE - .getMinIsolationTime(microserviceName)) { - resetStats(); - LOGGER.info("trying server invocation success, and reset stats."); - } else { - LOGGER.info("trying server invocation success!"); - } - } - - totalRequests.incrementAndGet(); - successRequests.incrementAndGet(); - continuousFailureCount.set(0); - lastVisitTime = time; - lastActiveTime = time; - } - - public void markFailure() { - long time = clock.millis(); - ensureWindow(time); - lastVisitTime = time; - - // when isolated, do not update any failure statistics, or we can not recover from failure very quickly - if (!isolated) { - totalRequests.incrementAndGet(); - failedRequests.incrementAndGet(); - continuousFailureCount.incrementAndGet(); - } - } - - private void ensureWindow(long time) { - if (time - lastWindow > TIME_WINDOW_IN_MILLISECONDS) { - synchronized (lock) { - if (time - lastWindow > TIME_WINDOW_IN_MILLISECONDS) { - if (!isolated) { - resetStats(); - } - lastWindow = time; - } - } - } - } - - private void resetStats() { - continuousFailureCount.set(0); - totalRequests.set(0); - successRequests.set(0); - failedRequests.set(0); - } - - public long getLastVisitTime() { - return lastVisitTime; - } - - public long getIsolatedTime() { - return isolatedTime; - } - - public long getLastActiveTime() { - return lastActiveTime; - } - - public long getContinuousFailureCount() { - return continuousFailureCount.get(); - } - - public long getTotalRequests() { - return totalRequests.get(); - } - - public long getSuccessRequests() { - return successRequests.get(); - } - - public long getFailedRequests() { - return failedRequests.get(); - } - - public int getSuccessRate() { - return calcRequestRate(successRequests); - } - - public int getFailedRate() { - return calcRequestRate(failedRequests); - } - - private int calcRequestRate(AtomicLong requestCnt) { - long totalReqs = totalRequests.get(); - if (totalReqs == 0L) { - return 0; - } - return (int) (requestCnt.get() * 100 / totalReqs); - } - - public boolean isIsolated() { - return isolated; - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java index f997a97fa14..37d94bc0fa1 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/SessionStickinessRule.java @@ -23,8 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.loadbalancer.LoadBalancerStats; -import com.netflix.loadbalancer.ServerStats; +import com.google.common.annotations.VisibleForTesting; /** * 会话保持策略:优先选择上一次选中的服务器,保证请求都发送到同一个服务器上去。 @@ -36,14 +35,12 @@ public class SessionStickinessRule implements RuleExt { private final Object lock = new Object(); - private LoadBalancer loadBalancer; - // use random rule as the trigger rule, to prevent consumer instance select the same producer instance. - private RuleExt triggerRule; + private final RuleExt triggerRule; private volatile ServiceCombServer lastServer = null; - private long lastAccessedTime = 0; + private volatile long lastAccessedTime = 0; private volatile boolean errorThresholdMet = false; @@ -55,9 +52,9 @@ public SessionStickinessRule() { triggerRule = new RoundRobinRuleExt(); } + @Override public void setLoadBalancer(LoadBalancer loadBalancer) { this.microserviceName = loadBalancer.getMicroServiceName(); - this.loadBalancer = loadBalancer; } private ServiceCombServer chooseNextServer(List servers, Invocation invocation) { @@ -75,7 +72,8 @@ private ServiceCombServer chooseInitialServer(List servers, I return lastServer; } - private ServiceCombServer chooseServerWhenTimeout(List servers, Invocation invocation) { + @VisibleForTesting + ServiceCombServer chooseServerWhenTimeout(List servers, Invocation invocation) { synchronized (lock) { if (isTimeOut()) { chooseNextServer(servers, invocation); @@ -101,19 +99,10 @@ private boolean isTimeOut() { * MILLI_COUNT_IN_SECOND); } - private boolean isErrorThresholdMet() { - LoadBalancerStats stats = loadBalancer.getLoadBalancerStats(); - - if (stats != null && stats.getServerStats() != null && stats.getServerStats().size() > 0) { - ServerStats serverStats = stats.getSingleServerStat(lastServer); - int successiveFailedCount = serverStats.getSuccessiveConnectionFailureCount(); - if (Configuration.INSTANCE.getSuccessiveFailedTimes(microserviceName) > 0 - && successiveFailedCount >= Configuration.INSTANCE.getSuccessiveFailedTimes(microserviceName)) { - serverStats.clearSuccessiveConnectionFailureCount(); - return true; - } - } - return false; + private boolean isErrorThresholdMet(ServiceCombServer server) { + int successiveFailedCount = server.getServerMetrics().getSnapshot().getNumberOfFailedCalls(); + return Configuration.INSTANCE.getSuccessiveFailedTimes(microserviceName) > 0 + && successiveFailedCount >= Configuration.INSTANCE.getSuccessiveFailedTimes(microserviceName); } @Override @@ -129,7 +118,7 @@ public ServiceCombServer choose(List servers, Invocation invo this.lastAccessedTime = System.currentTimeMillis(); } - if (isErrorThresholdMet()) { + if (isErrorThresholdMet(lastServer)) { LOG.warn("reached max error. choose another server."); errorThresholdMet = true; return chooseServerErrorThresholdMet(servers, invocation); diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/TryingIsolatedServerMarker.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/TryingIsolatedServerMarker.java deleted file mode 100644 index a741a8d71c5..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/TryingIsolatedServerMarker.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.loadbalance; - -import java.time.Clock; -import java.util.Objects; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.utils.TimeUtils; - -public class TryingIsolatedServerMarker { - Clock clock; - - final long startTryingTimestamp; - - private final Invocation invocation; - - /** - * To make sure even if some error interrupted the releasing operation of - * {@link ServiceCombServerStats#globalAllowIsolatedServerTryingFlag}, - * the state can still be recovered. - */ - private final int maxSingleTestWindow; - - public TryingIsolatedServerMarker(Invocation invocation) { - Objects.requireNonNull(invocation, "invocation should be non-null"); - this.invocation = invocation; - clock = TimeUtils.getSystemDefaultZoneClock(); - startTryingTimestamp = clock.millis(); - maxSingleTestWindow = Configuration.INSTANCE.getMaxSingleTestWindow(); - } - - public boolean isOutdated() { - return this.invocation.isFinished() - || clock.millis() - startTryingTimestamp >= maxSingleTestWindow; - } - - public Invocation getInvocation() { - return invocation; - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java index 7a6fe6c7310..a6462876e93 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/WeightedResponseTimeRuleExt.java @@ -20,33 +20,40 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.core.Invocation; -import com.netflix.loadbalancer.ServerStats; - /** * Rule based on response time. */ public class WeightedResponseTimeRuleExt extends RoundRobinRuleExt { - // 10ms + // when all servers are very fast(less than MIN_GAP), use round-robin rule. private static final double MIN_GAP = 10d; - private static final int RANDOM_PERCENT = 10; + // calculate stats once per RANDOM_PERCENT requests. + private static final int RANDOM_PERCENT = 1000; - private LoadBalancer loadBalancer; + private final Object lock = new Object(); - private double totalWeightsCache = -1d; + private final AtomicInteger counter = new AtomicInteger(0); - @Override - public void setLoadBalancer(LoadBalancer loadBalancer) { - this.loadBalancer = loadBalancer; - } + // notices: rule will always use as a fixed group of instance, see LoadBalancer for details. + private volatile int size = -1; + + private volatile List cacheStates = new ArrayList<>(); @Override public ServiceCombServer choose(List servers, Invocation invocation) { - List stats = calculateTotalWeights(servers); + int count = counter.getAndIncrement(); + if (count % RANDOM_PERCENT == 0 || size != servers.size()) { + synchronized (lock) { + this.cacheStates = doCalculateTotalWeights(servers); + this.size = servers.size(); + } + } + List stats = this.cacheStates; if (stats.size() > 0) { double finalTotal = stats.get(stats.size() - 1); List weights = new ArrayList<>(servers.size()); @@ -65,26 +72,13 @@ public ServiceCombServer choose(List servers, Invocation invo return super.choose(servers, invocation); } - private List calculateTotalWeights(List servers) { - if (Double.compare(totalWeightsCache, 0) < 0 || Double.compare(totalWeightsCache, MIN_GAP * servers.size()) > 0) { - return doCalculateTotalWeights(servers); - } - // 10% possibilities to use weighed response rule when the normal access is very fast. - if (ThreadLocalRandom.current().nextInt(RANDOM_PERCENT) == 0) { - return doCalculateTotalWeights(servers); - } else { - return new ArrayList<>(); - } - } - - private List doCalculateTotalWeights(List servers) { + private static List doCalculateTotalWeights(List servers) { List stats = new ArrayList<>(servers.size() + 1); double totalWeights = 0; boolean needRandom = false; for (ServiceCombServer server : servers) { - ServerStats serverStats = loadBalancer.getLoadBalancerStats().getSingleServerStat(server); - //getResponseTimeAvgRecent()按照时间窗口统计,时间窗口大小为1分钟;getResponseTimeAvg()一直累积 - double avgTime = serverStats.getResponseTimeAvgRecent(); + // this method will create new instance, so we cache the states. + double avgTime = server.getServerMetrics().getSnapshot().getAverageDuration().toMillis(); if (!needRandom && avgTime > MIN_GAP) { needRandom = true; } @@ -92,7 +86,6 @@ private List doCalculateTotalWeights(List servers) { stats.add(avgTime); } stats.add(totalWeights); - totalWeightsCache = totalWeights; if (needRandom) { return stats; } else { diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java deleted file mode 100644 index 115a161bdb5..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/event/IsolationServerEvent.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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.loadbalance.event; - -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.event.AlarmEvent; -import org.apache.servicecomb.loadbalance.ServiceCombServerStats; -import org.apache.servicecomb.loadbalance.filter.IsolationDiscoveryFilter; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; - -public class IsolationServerEvent extends AlarmEvent { - - private String microserviceName; - - private Endpoint endpoint; - - private MicroserviceInstance instance; - - //当前实例总请求数 - private long currentTotalRequest; - - //当前实例连续出错次数 - private long currentCountinuousFailureCount; - - //当前实例出错百分比 - private double currentErrorPercentage; - - private int minIsolationTime; - - private long enableRequestThreshold; - - private int continuousFailureThreshold; - - private int errorThresholdPercentage; - - private long singleTestTime; - - public IsolationServerEvent(Invocation invocation, MicroserviceInstance instance, - ServiceCombServerStats serverStats, - IsolationDiscoveryFilter.Settings settings, Type type, Endpoint endpoint) { - super(type); - this.microserviceName = invocation.getMicroserviceName(); - this.endpoint = endpoint; - this.currentTotalRequest = serverStats.getTotalRequests(); - this.currentCountinuousFailureCount = serverStats.getContinuousFailureCount(); - this.currentErrorPercentage = serverStats.getFailedRate(); - this.minIsolationTime = settings.minIsolationTime; - this.enableRequestThreshold = settings.enableRequestThreshold; - this.continuousFailureThreshold = settings.continuousFailureThreshold; - this.errorThresholdPercentage = settings.errorThresholdPercentage; - this.singleTestTime = settings.singleTestTime; - this.instance = instance; - } - - public String getMicroserviceName() { - return microserviceName; - } - - public long getCurrentTotalRequest() { - return currentTotalRequest; - } - - public long getCurrentCountinuousFailureCount() { - return currentCountinuousFailureCount; - } - - public double getCurrentErrorPercentage() { - return currentErrorPercentage; - } - - public long getEnableRequestThreshold() { - return enableRequestThreshold; - } - - public int getContinuousFailureThreshold() { - return continuousFailureThreshold; - } - - public int getErrorThresholdPercentage() { - return errorThresholdPercentage; - } - - public long getSingleTestTime() { - return singleTestTime; - } - - public MicroserviceInstance getInstance() { - return instance; - } - - public int getMinIsolationTime() { - return minIsolationTime; - } - - public Endpoint getEndpoint() { - return endpoint; - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/exception/LoadbalanceExceptionUtils.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/exception/LoadbalanceExceptionUtils.java index 62c2db42583..3a4bde530c3 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/exception/LoadbalanceExceptionUtils.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/exception/LoadbalanceExceptionUtils.java @@ -30,7 +30,6 @@ public class LoadbalanceExceptionUtils extends ExceptionUtils { public static CseException createLoadbalanceException(String code, Throwable cause, Object... args) { String msg = String.format(ERROR_DESC_MGR.ensureFindValue(code), args); - CseException exception = new CseException(code, msg, cause); - return exception; + return new CseException(code, msg, cause); } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/InstancePropertyDiscoveryFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/InstancePropertyDiscoveryFilter.java index bf9e05ec8ad..2b4c3eb6b20 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/InstancePropertyDiscoveryFilter.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/InstancePropertyDiscoveryFilter.java @@ -17,25 +17,27 @@ package org.apache.servicecomb.loadbalance.filter; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.loadbalance.Configuration; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; import org.apache.servicecomb.registry.discovery.AbstractDiscoveryFilter; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; - -import com.netflix.config.DynamicPropertyFactory; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; /** - * Instance property based filter + * Instance property based filter */ public class InstancePropertyDiscoveryFilter extends AbstractDiscoveryFilter { + private static final String MATCHED = "matched"; + public static final String SERVICECOMB_LOADBALANCE_FILTER_INSTANCE_PROPERTY_ENABLED = "servicecomb.loadbalance.filter.instanceProperty.enabled"; + @Override public int getOrder() { return 400; @@ -43,8 +45,13 @@ public int getOrder() { @Override public boolean enabled() { - return DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.loadbalance.filter.instanceProperty.enabled", true).get(); + + if (enabled == null) { + enabled = dynamicProperties.getBooleanProperty(SERVICECOMB_LOADBALANCE_FILTER_INSTANCE_PROPERTY_ENABLED, + value -> enabled = value, + true); + } + return enabled; } @Override @@ -54,15 +61,14 @@ public boolean isGroupingFilter() { @Override protected void init(DiscoveryContext context, DiscoveryTreeNode parent) { - Map matchedInstance = new HashMap<>(); + List matchedInstance = new ArrayList<>(); Invocation invocation = context.getInputParameters(); - Map instances = parent.data(); + List instances = parent.data(); Map filterOptions = Configuration.INSTANCE.getFlowsplitFilterOptions(invocation.getMicroserviceName()); - instances.entrySet().forEach(stringMicroserviceInstanceEntry -> { - MicroserviceInstance target = stringMicroserviceInstanceEntry.getValue(); + instances.forEach((target) -> { if (allowVisit(target, filterOptions)) { - matchedInstance.put(stringMicroserviceInstanceEntry.getKey(), target); + matchedInstance.add(target); } }); parent.child(MATCHED, new DiscoveryTreeNode() @@ -75,7 +81,7 @@ protected String findChildName(DiscoveryContext context, DiscoveryTreeNode paren return MATCHED; } - protected boolean allowVisit(MicroserviceInstance instance, Map filterOptions) { + protected boolean allowVisit(StatefulDiscoveryInstance instance, Map filterOptions) { Map propertiesMap = instance.getProperties(); for (Entry entry : filterOptions.entrySet()) { if (!entry.getValue().equals(propertiesMap.get(entry.getKey()))) { diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilter.java deleted file mode 100644 index c8693d9fc8f..00000000000 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilter.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * 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.loadbalance.filter; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.event.AlarmEvent.Type; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.loadbalance.Configuration; -import org.apache.servicecomb.loadbalance.ServiceCombLoadBalancerStats; -import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.loadbalance.ServiceCombServerStats; -import org.apache.servicecomb.loadbalance.event.IsolationServerEvent; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.eventbus.EventBus; -import com.netflix.config.DynamicBooleanProperty; -import com.netflix.config.DynamicPropertyFactory; - -/** - * Isolate instances by error metrics - */ -public class IsolationDiscoveryFilter implements DiscoveryFilter { - - public static final String TRYING_INSTANCES_EXISTING = "scb-hasTryingInstances"; - - private static final Logger LOGGER = LoggerFactory.getLogger(IsolationDiscoveryFilter.class); - - private static final String EMPTY_INSTANCE_PROTECTION = "servicecomb.loadbalance.filter.isolation.emptyInstanceProtectionEnabled"; - - private final DynamicBooleanProperty emptyProtection = DynamicPropertyFactory.getInstance() - .getBooleanProperty(EMPTY_INSTANCE_PROTECTION, false); - - public class Settings { - public int errorThresholdPercentage; - - public long singleTestTime; - - public long enableRequestThreshold; - - public int continuousFailureThreshold; - - public int minIsolationTime; // to avoid isolation recover too fast due to no concurrent control in concurrent scenario - } - - public EventBus eventBus = EventManager.getEventBus(); - - @Override - public int getOrder() { - return 500; - } - - public IsolationDiscoveryFilter() { - emptyProtection.addCallback(() -> { - boolean newValue = emptyProtection.get(); - LOGGER.info("{} changed from {} to {}", EMPTY_INSTANCE_PROTECTION, emptyProtection, newValue); - }); - } - - @Override - public boolean enabled() { - return DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.loadbalance.filter.isolation.enabled", true).get(); - } - - @Override - public boolean isGroupingFilter() { - return false; - } - - @Override - public DiscoveryTreeNode discovery(DiscoveryContext context, DiscoveryTreeNode parent) { - Map instances = parent.data(); - Invocation invocation = context.getInputParameters(); - if (!Configuration.INSTANCE.isIsolationFilterOpen(invocation.getMicroserviceName())) { - return parent; - } - - Map filteredServers = new HashMap<>(); - instances.entrySet().forEach(stringMicroserviceInstanceEntry -> { - MicroserviceInstance instance = stringMicroserviceInstanceEntry.getValue(); - if (allowVisit(invocation, instance)) { - filteredServers.put(stringMicroserviceInstanceEntry.getKey(), instance); - } - }); - - DiscoveryTreeNode child = new DiscoveryTreeNode(); - if (ZoneAwareDiscoveryFilter.GROUP_Instances_All - .equals(context.getContextParameter(ZoneAwareDiscoveryFilter.KEY_ZONE_AWARE_STEP)) && filteredServers.isEmpty() - && emptyProtection.get()) { - LOGGER.warn("All servers have been isolated, allow one of them based on load balance rule."); - child.data(instances); - } else { - child.data(filteredServers); - } - parent.child("filterred", child); - return child; - } - - private Settings createSettings(Invocation invocation) { - Settings settings = new Settings(); - settings.errorThresholdPercentage = Configuration.INSTANCE - .getErrorThresholdPercentage(invocation.getMicroserviceName()); - settings.singleTestTime = Configuration.INSTANCE.getSingleTestTime(invocation.getMicroserviceName()); - settings.enableRequestThreshold = Configuration.INSTANCE - .getEnableRequestThreshold(invocation.getMicroserviceName()); - settings.continuousFailureThreshold = Configuration.INSTANCE - .getContinuousFailureThreshold(invocation.getMicroserviceName()); - settings.minIsolationTime = Configuration.INSTANCE - .getMinIsolationTime(invocation.getMicroserviceName()); - return settings; - } - - private boolean allowVisit(Invocation invocation, MicroserviceInstance instance) { - ServiceCombServer server = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServer(instance); - if (server == null) { - // first time accessed. - return true; - } - ServiceCombServerStats serverStats = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server); - Settings settings = createSettings(invocation); - if (!checkThresholdAllowed(settings, serverStats)) { - if (serverStats.isIsolated() - && (System.currentTimeMillis() - serverStats.getLastVisitTime()) > settings.singleTestTime) { - return ServiceCombServerStats.applyForTryingChance(invocation); - } - if (!serverStats.isIsolated()) { - // checkThresholdAllowed is not concurrent control, may print several logs/events in current access. - serverStats.markIsolated(true); - eventBus.post( - new IsolationServerEvent(invocation, instance, serverStats, - settings, Type.OPEN, server.getEndpoint())); - LOGGER.warn("Isolate service {}'s instance {}.", invocation.getMicroserviceName(), - instance.getInstanceId()); - } - return false; - } - if (serverStats.isIsolated()) { - // [2] so that we add a feature to isolate for at least a minimal time, and we can avoid - // high volume of concurrent requests with a percentage of error(e.g. 50%) scenario with no isolation - if ((System.currentTimeMillis() - serverStats.getIsolatedTime()) <= settings.minIsolationTime) { - return false; - } - serverStats.markIsolated(false); - eventBus.post(new IsolationServerEvent(invocation, instance, serverStats, - settings, Type.CLOSE, server.getEndpoint())); - LOGGER.warn("Recover service {}'s instance {} from isolation.", invocation.getMicroserviceName(), - instance.getInstanceId()); - } - return true; - } - - private boolean checkThresholdAllowed(Settings settings, ServiceCombServerStats serverStats) { - if (serverStats.getTotalRequests() < settings.enableRequestThreshold) { - return true; - } - - if (settings.continuousFailureThreshold > 0) { - // continuousFailureThreshold has higher priority to decide the result - if (serverStats.getContinuousFailureCount() >= settings.continuousFailureThreshold) { - return false; - } - } - - if (settings.errorThresholdPercentage == 0) { - return true; - } - return serverStats.getFailedRate() < settings.errorThresholdPercentage; - } -} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/PriorityInstancePropertyDiscoveryFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/PriorityInstancePropertyDiscoveryFilter.java new file mode 100644 index 00000000000..d890b7ea229 --- /dev/null +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/PriorityInstancePropertyDiscoveryFilter.java @@ -0,0 +1,217 @@ +/* + * 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.loadbalance.filter; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.registry.discovery.AbstractDiscoveryFilter; +import org.apache.servicecomb.registry.discovery.DiscoveryContext; +import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +import jakarta.validation.constraints.NotNull; + +/** + * Instance property with priority filter + */ +public class PriorityInstancePropertyDiscoveryFilter extends AbstractDiscoveryFilter { + + private static final Logger LOGGER = LoggerFactory.getLogger(PriorityInstancePropertyDiscoveryFilter.class); + + private static final String ALL_INSTANCE = "allInstance"; + + public static final String SERVICECOMB_LOADBALANCE_FILTER_PRIORITY_INSTANCE_PROPERTY_KEY = "servicecomb.loadbalance.filter.priorityInstanceProperty.key"; + + private String propertyKey; + + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Override + protected void init(DiscoveryContext context, DiscoveryTreeNode parent) { + + propertyKey = dynamicProperties.getStringProperty(SERVICECOMB_LOADBALANCE_FILTER_PRIORITY_INSTANCE_PROPERTY_KEY, + value -> propertyKey = value, + "environment"); + + // group all instance by property + List instances = parent.data(); + Map> groupByProperty = new HashMap<>(); + for (StatefulDiscoveryInstance microserviceInstance : instances) { + String propertyValue = new PriorityInstanceProperty(propertyKey, microserviceInstance).getPropertyValue(); + groupByProperty.computeIfAbsent(propertyValue, key -> new ArrayList<>()) + .add(microserviceInstance); + } + Map children = new HashMap<>(); + for (Map.Entry> entry : groupByProperty.entrySet()) { + children.put(entry.getKey(), + new DiscoveryTreeNode().subName(parent, entry.getKey()).data(entry.getValue())); + } + children.put(ALL_INSTANCE, new DiscoveryTreeNode().subName(parent, ALL_INSTANCE).data(instances)); + parent.children(children); + } + + @Override + protected String findChildName(DiscoveryContext context, DiscoveryTreeNode parent) { + Invocation invocation = context.getInputParameters(); + + // context property has precedence over instance property + String initPropertyValue = invocation.getContext() + .computeIfAbsent("x-" + propertyKey, + key -> new PriorityInstanceProperty(propertyKey, + BootStrapProperties.readServiceProperties(environment).get(propertyKey)) + .getPropertyValue()); + + PriorityInstanceProperty currentProperty = context.getContextParameter(propertyKey); + // start with initial value, then search with priority + if (Objects.isNull(currentProperty)) { + currentProperty = new PriorityInstanceProperty(propertyKey, initPropertyValue); + while (!parent.children().containsKey(currentProperty.getPropertyValue()) + && currentProperty.hasChildren()) { + currentProperty = currentProperty.child(); + } + } else { + if (currentProperty.hasChildren()) { + currentProperty = currentProperty.child(); + } + } + LOGGER.debug("Discovery instance filter by {}", currentProperty); + context.putContextParameter(propertyKey, currentProperty); + + // stop push filter stack if property is empty + if (currentProperty.isEmpty()) { + return currentProperty.getPropertyValue(); + } + context.pushRerunFilter(); + return currentProperty.getPropertyValue(); + } + + @Override + public boolean enabled() { + + if (enabled == null) { + enabled = dynamicProperties.getBooleanProperty("servicecomb.loadbalance.filter.priorityInstanceProperty.enabled", + value -> enabled = value, + false); + } + return enabled; + } + + @Override + public int getOrder() { + return new InstancePropertyDiscoveryFilter().getOrder() + 1; + } + + static class PriorityInstanceProperty { + private static final int MAX_LENGTH = 10000; + + private static final String SEPARATOR = "."; + + private final String propertyKey; + + private final String propertyVal; + + /** + * Constructor + * + * @param key property key + * @param value property value + */ + public PriorityInstanceProperty(@NotNull String key, String value) { + propertyKey = key; + if (Objects.isNull(value)) { + value = StringUtils.EMPTY; + } + if (value.length() > MAX_LENGTH) { + throw new IllegalArgumentException("property value exceed max length"); + } + propertyVal = value; + } + + /** + * Constructor + * + * @param key property key + * @param microserviceInstance instance + */ + public PriorityInstanceProperty(@NotNull String key, @NotNull StatefulDiscoveryInstance microserviceInstance) { + this(key, Optional.ofNullable(microserviceInstance.getProperties().get(key)) + .orElse(StringUtils.EMPTY)); + } + + /** + * whether property is empty + * + * @return result + */ + public boolean isEmpty() { + return StringUtils.isEmpty(propertyVal); + } + + /** + * does property have lower priority children + * + * @return result + */ + public boolean hasChildren() { + return StringUtils.isNotEmpty(propertyVal); + } + + /** + * get lower priority child + * + * @return result + */ + public PriorityInstanceProperty child() { + if (propertyVal.contains(SEPARATOR)) { + return new PriorityInstanceProperty(propertyKey, StringUtils.substringBeforeLast(propertyVal, SEPARATOR)); + } + return new PriorityInstanceProperty(propertyKey, StringUtils.EMPTY); + } + + /** + * get property value + * + * @return propertyVal + */ + public String getPropertyValue() { + return propertyVal; + } + + @Override + public String toString() { + return "PriorityInstanceProperty{key=" + propertyKey + ", value=" + propertyVal + '}'; + } + } +} diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ServerDiscoveryFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ServerDiscoveryFilter.java index 9e6b22eaef4..50baab772fb 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ServerDiscoveryFilter.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ServerDiscoveryFilter.java @@ -17,29 +17,32 @@ package org.apache.servicecomb.loadbalance.filter; +import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.Transport; import org.apache.servicecomb.core.registry.discovery.EndpointDiscoveryFilter; import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; import org.apache.servicecomb.registry.discovery.DiscoveryContext; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ServerDiscoveryFilter extends EndpointDiscoveryFilter { private static final Logger LOGGER = LoggerFactory.getLogger(ServerDiscoveryFilter.class); + public ServerDiscoveryFilter() { + } + @Override protected Object createEndpoint(DiscoveryContext context, String transportName, String endpoint, - MicroserviceInstance instance) { - Transport transport = SCBEngine.getInstance().getTransportManager().findTransport(transportName); + StatefulDiscoveryInstance instance) { + Transport transport = scbEngine.getTransportManager().findTransport(transportName); if (transport == null) { LOGGER.info("not deployed transport {}, ignore {}.", transportName, endpoint); return null; } Invocation invocation = context.getInputParameters(); - return new ServiceCombServer(invocation.getMicroserviceName(), transport, new CacheEndpoint(endpoint, instance)); + return new ServiceCombServer(invocation.getMicroserviceName(), + new Endpoint(transport, endpoint, instance)); } } diff --git a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java index 6abf19cb245..0e521397f13 100644 --- a/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java +++ b/handlers/handler-loadbalance/src/main/java/org/apache/servicecomb/loadbalance/filter/ZoneAwareDiscoveryFilter.java @@ -17,117 +17,160 @@ package org.apache.servicecomb.loadbalance.filter; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; -import org.apache.servicecomb.foundation.common.exceptions.ServiceCombException; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.discovery.AbstractDiscoveryFilter; +import org.apache.servicecomb.config.DataCenterProperties; +import org.apache.servicecomb.registry.discovery.AbstractGroupDiscoveryFilter; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.springframework.beans.factory.annotation.Autowired; -import com.netflix.config.DynamicPropertyFactory; +public class ZoneAwareDiscoveryFilter extends AbstractGroupDiscoveryFilter { + public static final String PARAMETER = "zone_aware_level"; + public static final String GROUP_PREFIX = "zone_aware_group_"; -public class ZoneAwareDiscoveryFilter extends AbstractDiscoveryFilter { - public static final String KEY_ZONE_AWARE_STEP = "_KEY_ZONE_AWARE_STEP"; + public static final String GROUP_SIZE = "zone_aware_group_size"; - private static final String GROUP_RegionAndAZMatch = "instancesRegionAndAZMatch"; + public static final String CONFIG_ENABLED = "servicecomb.loadbalance.filter.zoneaware.enabled"; - private static final String GROUP_InstancesAZMatch = "instancesAZMatch"; + public static final String CONFIG_RATIO = "servicecomb.loadbalance.filter.zoneaware.ratio"; - private static final String GROUP_InstancesNoMatch = "instancesNoMatch"; + public static final String CONFIG_RATIO_CEILING = "servicecomb.loadbalance.filter.zoneaware.ratioCeiling"; - public static final String GROUP_Instances_All = "instancesAll"; + private DataCenterProperties dataCenterProperties; + + private Integer ratio; + + private Integer ratioCeiling; + + + @Autowired + @SuppressWarnings("unused") + public void setDataCenterProperties(DataCenterProperties dataCenterProperties) { + this.dataCenterProperties = dataCenterProperties; + } @Override public int getOrder() { - return 300; + return -9000; } @Override public boolean enabled() { - return DynamicPropertyFactory.getInstance() - .getBooleanProperty("servicecomb.loadbalance.filter.zoneaware.enabled", true).get(); + + if (enabled == null) { + enabled = dynamicProperties.getBooleanProperty(CONFIG_ENABLED, + value -> enabled = value, + true); + } + return enabled; + } + + private int getRatio() { + + if (ratio == null) { + ratio = dynamicProperties.getIntProperty(CONFIG_RATIO, + value -> ratio = value, + 30); + } + return ratio; + } + + private int getRatioCeiling(int defaultValue) { + + if (ratioCeiling == null) { + ratioCeiling = dynamicProperties.getIntProperty(CONFIG_RATIO_CEILING, + value -> ratioCeiling = value, + defaultValue); + } + return ratioCeiling; } @Override - public boolean isGroupingFilter() { - return true; + protected String contextParameter() { + return PARAMETER; } @Override - protected void init(DiscoveryContext context, DiscoveryTreeNode parent) { - MicroserviceInstance myself = RegistrationManager.INSTANCE.getMicroserviceInstance(); - - Map instancesRegionAndAZMatch = new HashMap<>(); - Map instancesAZMatch = new HashMap<>(); - Map instancesNoMatch = new HashMap<>(); - Map instances = parent.data(); - instances.entrySet().forEach(stringMicroserviceInstanceEntry -> { - String id = stringMicroserviceInstanceEntry.getKey(); - MicroserviceInstance target = stringMicroserviceInstanceEntry.getValue(); - if (regionAndAZMatch(myself, target)) { - instancesRegionAndAZMatch.put(id, target); - } else if (regionMatch(myself, target)) { - instancesAZMatch.put(id, target); - } else { - instancesNoMatch.put(id, target); - } - }); - Map children = new HashMap<>(); - children.put(GROUP_RegionAndAZMatch, new DiscoveryTreeNode() - .subName(parent, GROUP_RegionAndAZMatch) - .data(instancesRegionAndAZMatch)); - children.put(GROUP_InstancesAZMatch, new DiscoveryTreeNode() - .subName(parent, GROUP_InstancesAZMatch) - .data(instancesAZMatch)); - children.put(GROUP_InstancesNoMatch, new DiscoveryTreeNode() - .subName(parent, GROUP_InstancesNoMatch) - .data(instancesNoMatch)); - children.put(GROUP_Instances_All, new DiscoveryTreeNode() - .subName(parent, GROUP_Instances_All) - .data(instances)); - parent.children(children); + protected String groupsSizeParameter() { + return GROUP_SIZE; + } + + @Override + protected String groupPrefix() { + return GROUP_PREFIX; } @Override - protected String findChildName(DiscoveryContext context, DiscoveryTreeNode parent) { - String key = context.getContextParameter(KEY_ZONE_AWARE_STEP); - if (key == null) { - key = GROUP_RegionAndAZMatch; - context.pushRerunFilter(); - } else if (GROUP_RegionAndAZMatch.equals(key)) { - key = GROUP_InstancesAZMatch; - context.pushRerunFilter(); - } else if (GROUP_InstancesAZMatch.equals(key)) { - key = GROUP_InstancesNoMatch; - context.pushRerunFilter(); - } else if (GROUP_InstancesNoMatch.equals(key)) { - key = GROUP_Instances_All; + public void init(DiscoveryContext context, DiscoveryTreeNode parent) { + List instances = parent.data(); + List instancesRegionAndAZMatch = new ArrayList<>(); + List instancesAZMatch = new ArrayList<>(); + List instancesNoMatch = new ArrayList<>(); + + int groups = 1; + + for (StatefulDiscoveryInstance server : instances) { + if (regionAndAZMatch(server)) { + instancesRegionAndAZMatch.add(server); + } else if (regionMatch(server)) { + instancesAZMatch.add(server); + } else { + instancesNoMatch.add(server); + } + } + + int ratio = getRatio(); + int ratioCeiling = getRatioCeiling(100 - ratio); + + if (hasEnoughMembers(instances.size(), instancesRegionAndAZMatch.size(), ratio, ratioCeiling)) { + parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode() + .subName(parent, GROUP_PREFIX + groups).data(instancesRegionAndAZMatch)); + groups++; + } else { + instancesAZMatch.addAll(instancesRegionAndAZMatch); + } + + if (hasEnoughMembers(instances.size(), instancesAZMatch.size(), ratio, ratioCeiling)) { + parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode() + .subName(parent, GROUP_PREFIX + groups).data(instancesAZMatch)); + groups++; } else { - throw new ServiceCombException("not possible happen, maybe a bug."); + instancesNoMatch.addAll(instancesAZMatch); } - context.putContextParameter(KEY_ZONE_AWARE_STEP, key); - return key; + + parent.child(GROUP_PREFIX + groups, new DiscoveryTreeNode() + .subName(parent, GROUP_PREFIX + groups).data(instancesNoMatch)); + + parent.attribute(GROUP_SIZE, groups); } - private boolean regionAndAZMatch(MicroserviceInstance myself, MicroserviceInstance target) { - if (myself.getDataCenterInfo() == null) { - // when instance have no datacenter info, it will match all other datacenters - return true; + private boolean hasEnoughMembers(int totalSize, int groupSize, int ratio, int ratioCeiling) { + if (totalSize == 0 || groupSize == 0) { + return false; } - if (target.getDataCenterInfo() != null) { - return myself.getDataCenterInfo().getRegion().equals(target.getDataCenterInfo().getRegion()) && - myself.getDataCenterInfo().getAvailableZone().equals(target.getDataCenterInfo().getAvailableZone()); + int actual = Math.floorDiv(groupSize * 100, totalSize); + return actual >= ratio && actual <= ratioCeiling; + } + + private boolean regionAndAZMatch(StatefulDiscoveryInstance target) { + if (dataCenterProperties.getRegion() != null + && dataCenterProperties.getAvailableZone() != null && target.getDataCenterInfo() != null) { + return dataCenterProperties.getRegion() + .equals(target.getDataCenterInfo().getRegion()) && + dataCenterProperties.getAvailableZone() + .equals(target.getDataCenterInfo().getAvailableZone()); } return false; } - private boolean regionMatch(MicroserviceInstance myself, MicroserviceInstance target) { - if (target.getDataCenterInfo() != null) { - return myself.getDataCenterInfo().getRegion().equals(target.getDataCenterInfo().getRegion()); + private boolean regionMatch(StatefulDiscoveryInstance target) { + if (dataCenterProperties.getRegion() != null && target.getDataCenterInfo() != null) { + return dataCenterProperties.getRegion() + .equals(target.getDataCenterInfo().getRegion()); } return false; } diff --git a/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter b/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter deleted file mode 100644 index c191ce881fa..00000000000 --- a/handlers/handler-loadbalance/src/main/resources/META-INF/services/org.apache.servicecomb.registry.discovery.DiscoveryFilter +++ /dev/null @@ -1,20 +0,0 @@ -# -# 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.servicecomb.loadbalance.filter.ZoneAwareDiscoveryFilter -org.apache.servicecomb.loadbalance.filter.IsolationDiscoveryFilter -org.apache.servicecomb.loadbalance.filter.InstancePropertyDiscoveryFilter \ No newline at end of file diff --git a/handlers/handler-loadbalance/src/main/resources/META-INF/spring/cse.bean.xml b/handlers/handler-loadbalance/src/main/resources/META-INF/spring/cse.bean.xml deleted file mode 100644 index 7953580741a..00000000000 --- a/handlers/handler-loadbalance/src/main/resources/META-INF/spring/cse.bean.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - diff --git a/handlers/handler-loadbalance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-loadbalance/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..995d86d443a --- /dev/null +++ b/handlers/handler-loadbalance/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.servicecomb.loadbalance.LoadBalanceConfiguration diff --git a/handlers/handler-loadbalance/src/main/resources/config/cse.handler.xml b/handlers/handler-loadbalance/src/main/resources/config/cse.handler.xml deleted file mode 100644 index ab5181156b5..00000000000 --- a/handlers/handler-loadbalance/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java index 2dfaa52de77..81f24cd8b60 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestConfiguration.java @@ -17,176 +17,60 @@ package org.apache.servicecomb.loadbalance; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.junit.After; +import org.junit.Before; import org.junit.Test; - -import com.netflix.config.ConcurrentCompositeConfiguration; - -import mockit.Mock; -import mockit.MockUp; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; /** * */ public class TestConfiguration { + Environment environment = Mockito.mock(Environment.class); + + @Before + public void setUp() { + LegacyPropertyFactory.setEnvironment(environment); + } + @After public void after() { - ArchaiusUtils.resetConfig(); } @Test public void testConstants() { - assertEquals("servicecomb.loadbalance.", Configuration.ROOT); - assertEquals("ribbon.", Configuration.ROOT_20); - assertEquals("retryEnabled", Configuration.RETRY_ENABLED); - assertEquals("retryOnNext", Configuration.RETRY_ON_NEXT); - assertEquals("retryOnSame", Configuration.RETRY_ON_SAME); - assertEquals("SessionStickinessRule.successiveFailedTimes", Configuration.SUCCESSIVE_FAILED_TIMES); - assertEquals("maxSingleTestWindow", Configuration.FILTER_MAX_SINGLE_TEST_WINDOW); + Assertions.assertEquals("servicecomb.loadbalance.", Configuration.ROOT); + Assertions.assertEquals("ribbon.", Configuration.ROOT_20); + Assertions.assertEquals("SessionStickinessRule.successiveFailedTimes", Configuration.SUCCESSIVE_FAILED_TIMES); + Assertions.assertEquals("maxSingleTestWindow", Configuration.FILTER_MAX_SINGLE_TEST_WINDOW); - assertNotNull(Configuration.INSTANCE); + Assertions.assertNotNull(Configuration.INSTANCE); } @Test public void testFullConfigurationWithArgsString() { - assertNotNull(Configuration.INSTANCE.getRetryNextServer("test")); - assertNotNull(Configuration.INSTANCE.getRetrySameServer("test")); - assertNotNull(Configuration.INSTANCE.isRetryEnabled("test")); - assertNotNull(Configuration.INSTANCE.getSuccessiveFailedTimes("test")); - assertNotNull(Configuration.INSTANCE.getSessionTimeoutInSeconds("test")); - } - - @Test - public void testConfigurationWithGetpropertyReturnsStringChar() { - - new MockUp() { - @Mock - private String getProperty(String defaultValue, String... keys) { - return "tyt"; - } - }; - - Configuration.INSTANCE.getRetryNextServer("test"); - - assertNotNull(Configuration.INSTANCE.getRetryNextServer("test")); - } - - @Test - public void testConfigurationWithGetpropertyReturnsStringNum() { - - new MockUp() { - - @Mock - private String getProperty(String defaultValue, String... keys) { - return "1234"; - } - }; - - Configuration.INSTANCE.getRetryNextServer("test"); - - assertNotNull(Configuration.INSTANCE.getRetryNextServer("test")); - } - - @Test - public void testGetRetryOnSameWithGetpropertyReturnsStringChar() { - - new MockUp() { - @Mock - private String getProperty(String defaultValue, String... keys) { - return "tyt"; - } - }; - - Configuration.INSTANCE.getRetrySameServer("test"); - assertNotNull(Configuration.INSTANCE.getRetrySameServer("test")); - } - - @Test - public void testGetRetryOnSameWithGetpropertyReturnsStringNum() { - - new MockUp() { - - @Mock - private String getProperty(String defaultValue, String... keys) { - return "1234"; - } - }; - - Configuration.INSTANCE.getRetrySameServer("test"); - assertNotNull(Configuration.INSTANCE.getRetrySameServer("test")); - } - - @Test - public void testIsRetryEnabledWithGetpropertyReturnsStringChar() { - - new MockUp() { - @Mock - private String getProperty(String defaultValue, String... keys) { - return "tyt"; - } - }; - - Configuration.INSTANCE.isRetryEnabled("test"); - assertNotNull(Configuration.INSTANCE.isRetryEnabled("test")); - } - - @Test - public void testIsRetryEnabledWithGetpropertyReturnsStringNum() { - - new MockUp() { - - @Mock - private String getProperty(String defaultValue, String... keys) { - return "1234"; - } - }; - - Configuration.INSTANCE.isRetryEnabled("test"); - assertNotNull(Configuration.INSTANCE.isRetryEnabled("test")); + Assertions.assertNotNull(Configuration.INSTANCE.getSuccessiveFailedTimes("test")); + Assertions.assertNotNull(Configuration.INSTANCE.getSessionTimeoutInSeconds("test")); } @Test public void testGetSuccessiveFailedTimes() { - assertNotNull(Configuration.INSTANCE.getSuccessiveFailedTimes("test")); + Assertions.assertNotNull(Configuration.INSTANCE.getSuccessiveFailedTimes("test")); } @Test public void testGetSessionTimeoutInSeconds() { - assertNotNull(Configuration.INSTANCE.getSessionTimeoutInSeconds("test")); - } - - - /** - * The property key of timerIntervalInMilis changed from servicecomb.loadbalance.stats.timerIntervalInMilis - * to servicecomb.loadbalance.stats.timerIntervalInMillis, check the compatibility - */ - @Test - public void testGetTimerIntervalInMillis() { - System.setProperty(Configuration.TIMER_INTERVAL_IN_MILLIS, "100"); - ConcurrentCompositeConfiguration localConfiguration = ConfigUtil.createLocalConfig(); - assertEquals("100", localConfiguration.getProperty(Configuration.TIMER_INTERVAL_IN_MILLIS)); - - System.clearProperty(Configuration.TIMER_INTERVAL_IN_MILLIS); - localConfiguration = ConfigUtil.createLocalConfig(); - assertNull(localConfiguration.getProperty(Configuration.TIMER_INTERVAL_IN_MILLIS)); - - System.setProperty("servicecomb.loadbalance.stats.timerIntervalInMilis", "100"); - localConfiguration = ConfigUtil.createLocalConfig(); - assertEquals("100", localConfiguration.getProperty(Configuration.TIMER_INTERVAL_IN_MILLIS)); + Assertions.assertNotNull(Configuration.INSTANCE.getSessionTimeoutInSeconds("test")); } @Test public void testGetMaxSingleTestWindow() { - assertEquals(60000, Configuration.INSTANCE.getMaxSingleTestWindow()); - - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.maxSingleTestWindow", 5000); - assertEquals(5000, Configuration.INSTANCE.getMaxSingleTestWindow()); + Assertions.assertEquals(60000, Configuration.INSTANCE.getMaxSingleTestWindow()); + Mockito.when(environment.getProperty("servicecomb.loadbalance.isolation.maxSingleTestWindow")).thenReturn("5000"); + Assertions.assertEquals(5000, Configuration.INSTANCE.getMaxSingleTestWindow()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestDefaultRetryhandler.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestDefaultRetryhandler.java deleted file mode 100644 index b0bd4ab2415..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestDefaultRetryhandler.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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.loadbalance; - -import java.io.IOException; -import java.net.ConnectException; -import java.net.NoRouteToHostException; -import java.net.SocketTimeoutException; - -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.netflix.client.RetryHandler; - -import io.vertx.core.VertxException; - -public class TestDefaultRetryhandler { - - private static final String RETYR_NAME = "default"; - - private static final String MICROSERVICE_NAME = "servicename"; - - private RetryHandler retryHandler; - - @Before - public void setup() { - DefaultRetryExtensionsFactory factory = new DefaultRetryExtensionsFactory(); - retryHandler = factory.createRetryHandler(RETYR_NAME, MICROSERVICE_NAME); - } - - @Test - public void testRetryWithConnectionException() { - Exception target = new ConnectException("connectin refused"); - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - } - - @Test - public void testRetryWithSocketTimeout() { - Exception target = new SocketTimeoutException("Read timed out"); - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - } - - @Test - public void testRetryWithIOException() { - Exception target = new IOException("Connection reset by peer"); - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - - target = new IOException("Target not exist"); - root = new Exception(target); - retriable = retryHandler.isRetriableException(root, false); - Assert.assertFalse(retriable); - } - - @Test - public void testRetryVertxException() { - Exception target = new VertxException("Connection was closed"); - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - - target = new IOException(""); - root = new Exception(target); - retriable = retryHandler.isRetriableException(root, false); - Assert.assertFalse(retriable); - } - - @Test - public void testRetryNoRouteToHostException() { - Exception target = new NoRouteToHostException("Host is unreachable"); - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - - target = new NoRouteToHostException("No route to host"); - root = new Exception(target); - retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - } - - @Test - public void testRetryInvocation503() { - Exception root = new InvocationException(503, "Service Unavailable", "Error"); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - } - - @Test - public void testRetryEqualTen() { - Exception target = new ConnectException("connectin refused"); - for (int i = 0; i < 8; i++) { - target = new Exception("Level" + i, target); - } - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertTrue(retriable); - } - - @Test - public void testRetryOverTen() { - Exception target = new ConnectException("connectin refused"); - for (int i = 0; i < 9; i++) { - target = new Exception("Level" + i, target); - } - Exception root = new Exception(target); - boolean retriable = retryHandler.isRetriableException(root, false); - Assert.assertFalse(retriable); - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java index 3b1faacc8e5..2b159d38339 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestExtensionsManager.java @@ -16,85 +16,40 @@ */ package org.apache.servicecomb.loadbalance; -import java.io.IOException; -import java.net.ConnectException; -import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.List; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.netflix.client.DefaultLoadBalancerRetryHandler; -import com.netflix.client.RetryHandler; - -import mockit.Deencapsulation; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestExtensionsManager { - @Before + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach public void setUp() { - ConfigUtil.createLocalConfig(); - Deencapsulation.setField(ExtensionsManager.class, "extentionFactories", new ArrayList<>()); + LegacyPropertyFactory.setEnvironment(environment); } - @After + @AfterEach public void tearDown() { - Deencapsulation.setField(ExtensionsManager.class, "extentionFactories", new ArrayList<>()); - ArchaiusUtils.resetConfig(); } @Test public void testRuleName() { - System.setProperty("servicecomb.loadbalance.mytest1.strategy.name", "RoundRobin"); - System.setProperty("servicecomb.loadbalance.mytest2.strategy.name", "Random"); - System.setProperty("servicecomb.loadbalance.mytest3.strategy.name", "WeightedResponse"); - System.setProperty("servicecomb.loadbalance.mytest4.strategy.name", "SessionStickiness"); - - BeansHolder holder = new BeansHolder(); - List extensionsFactories = new ArrayList<>(); - extensionsFactories.add(new RuleNameExtentionsFactory()); - extensionsFactories.add(new DefaultRetryExtensionsFactory()); - Deencapsulation.setField(holder, "extentionsFactories", extensionsFactories); - holder.init(); - - Assert.assertEquals(RoundRobinRuleExt.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest1").getClass().getName()); - Assert.assertEquals(RandomRuleExt.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest2").getClass().getName()); - Assert.assertEquals(WeightedResponseTimeRuleExt.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest3").getClass().getName()); - Assert.assertEquals(SessionStickinessRule.class.getName(), - ExtensionsManager.createLoadBalancerRule("mytest4").getClass().getName()); - - System.getProperties().remove("servicecomb.loadbalance.mytest1.strategy.name"); - System.getProperties().remove("servicecomb.loadbalance.mytest2.strategy.name"); - System.getProperties().remove("servicecomb.loadbalance.mytest3.strategy.name"); - System.getProperties().remove("servicecomb.loadbalance.mytest4.strategy.name"); - } - - - @Test - public void testRuleClassName() { - BeansHolder holder = new BeansHolder(); List extensionsFactories = new ArrayList<>(); - extensionsFactories.add(new RuleNameExtentionsFactory()); - extensionsFactories.add(new DefaultRetryExtensionsFactory()); - Deencapsulation.setField(holder, "extentionsFactories", extensionsFactories); - holder.init(); - RetryHandler retryHandler = ExtensionsManager.createRetryHandler("mytest1"); - Assert.assertTrue(DefaultLoadBalancerRetryHandler.class.isInstance(retryHandler)); - Assert.assertFalse(retryHandler.isRetriableException(new InvocationException(400, "", ""), false)); - Assert.assertFalse(retryHandler.isRetriableException(new InvocationException(400, "", ""), true)); - Assert.assertTrue(retryHandler.isRetriableException(new InvocationException(503, "", ""), true)); - Assert.assertTrue(retryHandler.isRetriableException(new ConnectException(), false)); - Assert.assertTrue(retryHandler.isRetriableException(new ConnectException(), true)); - Assert.assertTrue(retryHandler.isRetriableException(new SocketTimeoutException(), false)); - Assert.assertTrue(retryHandler.isRetriableException(new SocketTimeoutException(), true)); - Assert.assertFalse(retryHandler.isRetriableException(new IOException(), true)); + extensionsFactories.add(new RuleNameExtensionsFactory()); + ExtensionsManager extensionsManager = new ExtensionsManager(extensionsFactories); + + Assertions.assertEquals(RoundRobinRuleExt.class.getName(), + extensionsManager.createLoadBalancerRule("RoundRobin").getClass().getName()); + Assertions.assertEquals(RandomRuleExt.class.getName(), + extensionsManager.createLoadBalancerRule("Random").getClass().getName()); + Assertions.assertEquals(WeightedResponseTimeRuleExt.class.getName(), + extensionsManager.createLoadBalancerRule("WeightedResponse").getClass().getName()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java index dc0489e1499..1ee1824c6d6 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceCreator.java @@ -23,14 +23,12 @@ import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.junit.Assert; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; -import com.netflix.loadbalancer.Server; - -import mockit.Deencapsulation; import mockit.Expectations; import mockit.Injectable; @@ -41,15 +39,18 @@ public void testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable Invocation in // Robin components implementations require getReachableServers & getServerList have the same size, we add a test case for this. RoundRobinRuleExt rule = new RoundRobinRuleExt(); List servers = new ArrayList<>(); - Endpoint host1 = new Endpoint(transport, "host1"); - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("instance1"); - ServiceCombServer server = new ServiceCombServer(null, host1, instance1); - Endpoint host2 = new Endpoint(transport, "host2"); - MicroserviceInstance instance2 = new MicroserviceInstance(); - instance2.setInstanceId("instance2"); - ServiceCombServer server2 = new ServiceCombServer(null, host2, instance2); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance1 = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("instance1"); + Endpoint host1 = new Endpoint(transport, "host1", instance1); + ServiceCombServer server = new ServiceCombServer(null, host1); + + DiscoveryInstance discoveryInstance2 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance2 = new StatefulDiscoveryInstance(discoveryInstance2); + Mockito.when(discoveryInstance2.getInstanceId()).thenReturn("instance2"); + Endpoint host2 = new Endpoint(transport, "host2", instance2); + ServiceCombServer server2 = new ServiceCombServer(null, host2); servers.add(server); servers.add(server2); @@ -57,34 +58,30 @@ public void testLoadBalanceWithRoundRobinRuleAndFilter(@Injectable Invocation in List filters = new ArrayList<>(); - filters.add(new ServerListFilterExt() { - @Override - public List getFilteredListOfServers(List serverList, - Invocation invocation) { - List filteredServers = new ArrayList<>(); - for (ServiceCombServer server : servers) { - if (server.getHost().equals("host1")) { - continue; - } - filteredServers.add(server); + filters.add((serverList, invocation1) -> { + List filteredServers = new ArrayList<>(); + for (ServiceCombServer server1 : servers) { + if (server1.getHost().equals("host1")) { + continue; } - return filteredServers; + filteredServers.add(server1); } + return filteredServers; }); lb.setFilters(filters); new Expectations() { { - invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST); + invocation.getLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST); result = servers; } }; - Server s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); + ServiceCombServer s = lb.chooseServer(invocation); + Assertions.assertEquals(server2, s); s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); + Assertions.assertEquals(server2, s); s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); + Assertions.assertEquals(server2, s); } @Test @@ -95,47 +92,46 @@ public void testLoadBalanceWithRandomRuleAndFilter(@Injectable Invocation invoca LoadBalancer lb = new LoadBalancer(rule, "service"); List servers = new ArrayList<>(); - Endpoint host1 = new Endpoint(transport, "host1"); - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("instance1"); - ServiceCombServer server = new ServiceCombServer(null, host1, instance1); - Endpoint host2 = new Endpoint(transport, "host2"); - MicroserviceInstance instance2 = new MicroserviceInstance(); - instance2.setInstanceId("instance2"); - ServiceCombServer server2 = new ServiceCombServer(null, host2, instance2); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance1 = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("instance1"); + Endpoint host1 = new Endpoint(transport, "host1", instance1); + ServiceCombServer server = new ServiceCombServer(null, host1); + + DiscoveryInstance discoveryInstance2 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance2 = new StatefulDiscoveryInstance(discoveryInstance2); + Mockito.when(discoveryInstance2.getInstanceId()).thenReturn("instance2"); + Endpoint host2 = new Endpoint(transport, "host2", instance2); + ServiceCombServer server2 = new ServiceCombServer(null, host2); servers.add(server); servers.add(server2); List filters = new ArrayList<>(); - filters.add(new ServerListFilterExt() { - @Override - public List getFilteredListOfServers(List serverList, - Invocation invocation) { - List filteredServers = new ArrayList<>(); - for (ServiceCombServer server : servers) { - if (server.getHost().equals("host1")) { - continue; - } - filteredServers.add(server); + filters.add((serverList, invocation1) -> { + List filteredServers = new ArrayList<>(); + for (ServiceCombServer server1 : servers) { + if (server1.getHost().equals("host1")) { + continue; } - return filteredServers; + filteredServers.add(server1); } + return filteredServers; }); lb.setFilters(filters); new Expectations() { { - invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST); + invocation.getLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST); result = servers; } }; - Server s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); + ServiceCombServer s = lb.chooseServer(invocation); + Assertions.assertEquals(server2, s); s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); + Assertions.assertEquals(server2, s); s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); + Assertions.assertEquals(server2, s); } @Test @@ -146,100 +142,56 @@ public void testLoadBalanceWithWeightedResponseTimeRuleAndFilter(@Injectable End LoadBalancer lb = new LoadBalancer(rule, "service"); List servers = new ArrayList<>(); - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("ii01"); - MicroserviceInstance instance2 = new MicroserviceInstance(); - instance2.setInstanceId("ii02"); - ServiceCombServer server = new ServiceCombServer(null, endpoint1, instance1); - ServiceCombServer server2 = new ServiceCombServer(null, endpoint2, instance2); + + DiscoveryInstance discoveryInstance1 = Mockito.mock(DiscoveryInstance.class); +// StatefulDiscoveryInstance instance1 = new StatefulDiscoveryInstance(discoveryInstance1); + Mockito.when(discoveryInstance1.getInstanceId()).thenReturn("ii01"); + + DiscoveryInstance discoveryInstance2 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance2 = new StatefulDiscoveryInstance(discoveryInstance2); + Mockito.when(discoveryInstance2.getInstanceId()).thenReturn("ii02"); new Expectations() { { endpoint1.getEndpoint(); result = "host1"; +// endpoint1.getMicroserviceInstance(); +// result = instance1; endpoint2.getEndpoint(); result = "host2"; + endpoint2.getMicroserviceInstance(); + result = instance2; } }; + ServiceCombServer server = new ServiceCombServer(null, endpoint1); + ServiceCombServer server2 = new ServiceCombServer(null, endpoint2); + servers.add(server); servers.add(server2); List filters = new ArrayList<>(); - filters.add(new ServerListFilterExt() { - @Override - public List getFilteredListOfServers(List serverList, - Invocation invocation) { - List filteredServers = new ArrayList<>(); - for (ServiceCombServer server : servers) { - if (server.getHost().equals("host1")) { - continue; - } - filteredServers.add(server); + filters.add((serverList, invocation1) -> { + List filteredServers = new ArrayList<>(); + for (ServiceCombServer server1 : servers) { + if (server1.getHost().equals("host1")) { + continue; } - return filteredServers; + filteredServers.add(server1); } + return filteredServers; }); lb.setFilters(filters); new Expectations() { { - invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST); - result = servers; - } - }; - Server s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); - s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); - s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); - } - - @Test - public void testLoadBalanceWithSessionSticknessRule(@Injectable Invocation invocation, - @Injectable Transport transport) { - SessionStickinessRule rule = new SessionStickinessRule(); - LoadBalancer lb = new LoadBalancer(rule, "service"); - - List servers = new ArrayList<>(); - Endpoint host1 = new Endpoint(transport, "host1"); - MicroserviceInstance instance1 = new MicroserviceInstance(); - ServiceCombServer server = new ServiceCombServer(null, host1, instance1); - instance1.setInstanceId("instance1"); - - Endpoint host2 = new Endpoint(transport, "host2"); - MicroserviceInstance instance2 = new MicroserviceInstance(); - ServiceCombServer server2 = new ServiceCombServer(null, host2, instance2); - instance2.setInstanceId("instance2"); - - servers.add(server); - servers.add(server2); - - lb.setFilters(new ArrayList<>()); - new Expectations() { - { - invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST); + invocation.getLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST); result = servers; } }; - - Server s = lb.chooseServer(invocation); - Assert.assertEquals(server, s); - s = lb.chooseServer(invocation); - Assert.assertEquals(server, s); - - long time = Deencapsulation.getField(rule, "lastAccessedTime"); - Deencapsulation.setField(rule, "lastAccessedTime", time - 1000 * 300); - ArchaiusUtils.setProperty("cse.loadbalance.service.SessionStickinessRule.sessionTimeoutInSeconds", 9); + ServiceCombServer s = lb.chooseServer(invocation); + Assertions.assertEquals(server2, s); s = lb.chooseServer(invocation); - Assert.assertEquals(server2, s); - - ArchaiusUtils.setProperty("cse.loadbalance.service.SessionStickinessRule.successiveFailedTimes", 5); - lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); - lb.getLoadBalancerStats().incrementSuccessiveConnectionFailureCount(s); + Assertions.assertEquals(server2, s); s = lb.chooseServer(invocation); - Assert.assertEquals(server, s); + Assertions.assertEquals(server2, s); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter.java new file mode 100644 index 00000000000..123f23ac514 --- /dev/null +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter.java @@ -0,0 +1,139 @@ +/* + * 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.loadbalance; + +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.apache.servicecomb.core.transport.TransportManager; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.registry.discovery.DiscoveryTree; +import org.apache.servicecomb.registry.discovery.TelnetInstancePing; +import org.apache.servicecomb.swagger.invocation.AsyncResponse; +import org.apache.servicecomb.swagger.invocation.Response; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +import mockit.Deencapsulation; +import mockit.Injectable; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; + +/** + * + * + */ +public class TestLoadBalanceFilter { + static SCBEngine scbEngine; + + static TransportManager transportManager; + + String microserviceName = "ms"; + + LoadBalanceFilter handler; + + Map loadBalancerMap; + + @Injectable + Invocation invocation; + + @Mocked + Transport restTransport; + + Response sendResponse; + + @Before + public void setUp() { + Environment environment = Mockito.mock(Environment.class); + scbEngine = SCBBootstrap.createSCBEngineForTest(environment); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)) + .thenReturn(BootStrapProperties.DEFAULT_APPLICATION); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_NAME); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_ENVIRONMENT)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_ENVIRONMENT); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", + boolean.class, false)).thenReturn(false); + scbEngine.run(); + transportManager = scbEngine.getTransportManager(); + + new MockUp(invocation) { + @Mock + String getMicroserviceName() { + return microserviceName; + } + + @Mock + void next(AsyncResponse asyncResp) throws Exception { + asyncResp.handle(sendResponse); + } + + @Mock + public T getLocalContext(String key) { + return (T) null; + } + }; + + new MockUp(transportManager) { + @Mock + Transport findTransport(String transportName) { + return restTransport; + } + }; + + List extensionsFactories = new ArrayList<>(); + extensionsFactories.add(new RuleNameExtensionsFactory()); + ExtensionsManager extensionsManager = new ExtensionsManager(extensionsFactories); + + DiscoveryTree discoveryTree = new DiscoveryTree( + new DiscoveryManager(Collections.emptyList(), List.of(new TelnetInstancePing()))); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), + discoveryTree, scbEngine); + loadBalancerMap = Deencapsulation.getField(handler, "loadBalancerMap"); + } + + @After + public void teardown() { + scbEngine.destroy(); + } + + @Test + public void testIsFailedResponse() { + Assertions.assertFalse(handler.isFailedResponse(Response.create(400, "", ""))); + Assertions.assertFalse(handler.isFailedResponse(Response.create(500, "", ""))); + Assertions.assertTrue(handler.isFailedResponse(Response.create(490, "", ""))); + Assertions.assertTrue(handler.isFailedResponse(Response.consumerFailResp(new NullPointerException()))); + } +} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java new file mode 100644 index 00000000000..4c2fb5f5b45 --- /dev/null +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceFilter2.java @@ -0,0 +1,581 @@ +/* + * 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.loadbalance; + +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +import org.apache.servicecomb.config.DataCenterProperties; +import org.apache.servicecomb.config.DynamicProperties; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.NonSwaggerInvocation; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.core.definition.InvocationRuntimeType; +import org.apache.servicecomb.core.definition.MicroserviceMeta; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.definition.SchemaMeta; +import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; +import org.apache.servicecomb.core.transport.TransportManager; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter; +import org.apache.servicecomb.loadbalance.filter.ZoneAwareDiscoveryFilter; +import org.apache.servicecomb.registry.DiscoveryManager; +import org.apache.servicecomb.registry.api.DataCenterInfo; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.api.MicroserviceInstanceStatus; +import org.apache.servicecomb.registry.discovery.DiscoveryTree; +import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; + +public class TestLoadBalanceFilter2 { + DynamicProperties dynamicProperties = Mockito.mock(DynamicProperties.class); + + Environment environment = Mockito.mock(Environment.class); + + @BeforeEach + public void setUp() { + + Mockito.when(environment.getProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", + boolean.class, false)).thenReturn(false); + + Mockito.when(dynamicProperties.getBooleanProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.enabled"), + Mockito.any(), + Mockito.eq(true))) + .thenReturn(true); + Mockito.when(dynamicProperties.getIntProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.ratio"), + Mockito.any(), + Mockito.eq(30))) + .thenReturn(0); + Mockito.when(dynamicProperties.getIntProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.ratioCeiling"), + Mockito.any(), + Mockito.eq(100))) + .thenReturn(100); + + LegacyPropertyFactory.setEnvironment(environment); + } + + @Test + public void testZoneAwareFilterWorks() { + ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); + SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); + when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Operation operation = Mockito.mock(Operation.class); + when(operationMeta.getSwaggerOperation()).thenReturn(operation); + when(operation.getExtensions()).thenReturn(null); + OpenAPI openAPI = Mockito.mock(OpenAPI.class); + when(schemaMeta.getSwagger()).thenReturn(openAPI); + when(openAPI.getExtensions()).thenReturn(null); + MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); + when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); + when(microserviceMeta.getAppId()).thenReturn("testApp"); + when(referenceConfig.getTransport()).thenReturn("rest"); + Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); + TransportManager transportManager = Mockito.mock(TransportManager.class); + Transport transport = Mockito.mock(Transport.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getEnvironment()).thenReturn(environment); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test-Region"); + myself.setAvailableZone("test-zone"); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance allmatchInstance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test-Region"); + info.setAvailableZone("test-zone"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:9090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance"); + + DiscoveryInstance regionMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance regionMatchInstance = new StatefulDiscoveryInstance(regionMatchDiscoveryInstance); + DataCenterInfo regionMatchInfo = new DataCenterInfo(); + regionMatchInfo.setName("test"); + regionMatchInfo.setRegion("test-Region"); + regionMatchInfo.setAvailableZone("test-zone2"); + List regionMatchEndpoint = new ArrayList<>(); + regionMatchEndpoint.add("rest://localhost:9091"); + Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint); + Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo); + Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance"); + + DiscoveryInstance noneMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance noneMatchInstance = new StatefulDiscoveryInstance(noneMatchDiscoveryInstance); + DataCenterInfo noneMatchInfo = new DataCenterInfo(); + noneMatchInfo.setName("test"); + noneMatchInfo.setRegion("test-Region2"); + noneMatchInfo.setAvailableZone("test-zone2"); + List noMatchEndpoint = new ArrayList<>(); + noMatchEndpoint.add("rest://localhost:9092"); + Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint); + Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo); + Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance"); + + List data = new ArrayList<>(); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + when(transportManager.findTransport("rest")).thenReturn(transport); + + LoadBalanceFilter handler; + LoadBalancer loadBalancer; + ServiceCombServer server; + + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + Mockito.when(discoveryManager.getOrCreateVersionedCache("testApp", "testMicroserviceName")) + .thenReturn(parent); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new ZoneAwareDiscoveryFilter(); + zoneAwareDiscoveryFilter.setDynamicProperties(dynamicProperties); + zoneAwareDiscoveryFilter.setDataCenterProperties(myself); + ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter(); + serverDiscoveryFilter.setScbEngine(scbEngine); + discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter, + serverDiscoveryFilter)); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), + discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertNull(server); + + data.add(noneMatchInstance); + parent.cacheVersion(1); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), + discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9092", server.getEndpoint().getEndpoint()); + + data.add(regionMatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); + + data.add(allmatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); + } + + + @Test + public void testIsolationEventWithEndpoint() { + ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); + SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); + when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + Operation operation = Mockito.mock(Operation.class); + when(operationMeta.getSwaggerOperation()).thenReturn(operation); + when(operation.getExtensions()).thenReturn(null); + OpenAPI openAPI = Mockito.mock(OpenAPI.class); + when(schemaMeta.getSwagger()).thenReturn(openAPI); + when(openAPI.getExtensions()).thenReturn(null); + MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); + when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); + when(microserviceMeta.getAppId()).thenReturn("testApp"); + when(referenceConfig.getTransport()).thenReturn("rest"); + Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); + TransportManager transportManager = Mockito.mock(TransportManager.class); + Transport transport = Mockito.mock(Transport.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getEnvironment()).thenReturn(environment); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test"); + myself.setAvailableZone("test"); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test"); + info.setAvailableZone("test"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:9090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("instance"); + + List data = new ArrayList<>(); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + + when(transportManager.findTransport("rest")).thenReturn(transport); + + LoadBalanceFilter handler; + LoadBalancer loadBalancer; + ServiceCombServer server; + + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + Mockito.when(discoveryManager.getOrCreateVersionedCache("testApp", "testMicroserviceName")) + .thenReturn(parent); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new ZoneAwareDiscoveryFilter(); + zoneAwareDiscoveryFilter.setDynamicProperties(dynamicProperties); + zoneAwareDiscoveryFilter.setDataCenterProperties(myself); + ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter(); + serverDiscoveryFilter.setScbEngine(scbEngine); + discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter, + serverDiscoveryFilter)); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), + discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertNull(server); + + data.add(instance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); + } + + @Test + public void testZoneAwareFilterWorksEmptyInstanceProtectionEnabled() { + ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); + OperationMeta operationMeta = Mockito.mock(OperationMeta.class); + InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); + SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); + when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); + MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); + when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); + when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); + Operation operation = Mockito.mock(Operation.class); + when(operationMeta.getSwaggerOperation()).thenReturn(operation); + when(operation.getExtensions()).thenReturn(null); + OpenAPI openAPI = Mockito.mock(OpenAPI.class); + when(schemaMeta.getSwagger()).thenReturn(openAPI); + when(openAPI.getExtensions()).thenReturn(null); + when(microserviceMeta.getAppId()).thenReturn("testApp"); + when(referenceConfig.getTransport()).thenReturn("rest"); + Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); + TransportManager transportManager = Mockito.mock(TransportManager.class); + Transport transport = Mockito.mock(Transport.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + Mockito.when(scbEngine.getEnvironment()).thenReturn(environment); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test-Region"); + myself.setAvailableZone("test-zone"); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance allmatchInstance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test-Region"); + info.setAvailableZone("test-zone"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:9090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance"); + + DiscoveryInstance regionMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance regionMatchInstance = new StatefulDiscoveryInstance(regionMatchDiscoveryInstance); + DataCenterInfo regionMatchInfo = new DataCenterInfo(); + regionMatchInfo.setName("test"); + regionMatchInfo.setRegion("test-Region"); + regionMatchInfo.setAvailableZone("test-zone2"); + List regionMatchEndpoint = new ArrayList<>(); + regionMatchEndpoint.add("rest://localhost:9091"); + Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint); + Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo); + Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance"); + + DiscoveryInstance noneMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance noneMatchInstance = new StatefulDiscoveryInstance(noneMatchDiscoveryInstance); + DataCenterInfo noneMatchInfo = new DataCenterInfo(); + noneMatchInfo.setName("test"); + noneMatchInfo.setRegion("test-Region2"); + noneMatchInfo.setAvailableZone("test-zone2"); + List noMatchEndpoint = new ArrayList<>(); + noMatchEndpoint.add("rest://localhost:9092"); + Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint); + Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo); + Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance"); + + List data = new ArrayList<>(); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + + when(transportManager.findTransport("rest")).thenReturn(transport); + + LoadBalanceFilter handler; + LoadBalancer loadBalancer; + ServiceCombServer server; + + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + Mockito.when(discoveryManager.getOrCreateVersionedCache("testApp", "testMicroserviceName")) + .thenReturn(parent); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new ZoneAwareDiscoveryFilter(); + zoneAwareDiscoveryFilter.setDynamicProperties(dynamicProperties); + zoneAwareDiscoveryFilter.setDataCenterProperties(myself); + ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter(); + serverDiscoveryFilter.setScbEngine(scbEngine); + discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter, + serverDiscoveryFilter)); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertNull(server); + + data.add(noneMatchInstance); + parent.cacheVersion(1); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9092", server.getEndpoint().getEndpoint()); + + data.add(regionMatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); + + data.add(allmatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); + } + + @Test + public void testZoneAwareFilterUsingMockedInvocationWorks() { + Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName"); + TransportManager transportManager = Mockito.mock(TransportManager.class); + Transport transport = Mockito.mock(Transport.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + Mockito.when(scbEngine.getEnvironment()).thenReturn(environment); + Mockito.when(environment.getProperty("servicecomb.loadbalance.filter.operation.enabled", + boolean.class, true)).thenReturn(false); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test-Region"); + myself.setAvailableZone("test-zone"); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance allmatchInstance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test-Region"); + info.setAvailableZone("test-zone"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:7090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance"); + + DiscoveryInstance regionMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance regionMatchInstance = new StatefulDiscoveryInstance(regionMatchDiscoveryInstance); + DataCenterInfo regionMatchInfo = new DataCenterInfo(); + regionMatchInfo.setName("test"); + regionMatchInfo.setRegion("test-Region"); + regionMatchInfo.setAvailableZone("test-zone2"); + List regionMatchEndpoint = new ArrayList<>(); + regionMatchEndpoint.add("rest://localhost:7091"); + Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint); + Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo); + Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance"); + + DiscoveryInstance noneMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance noneMatchInstance = new StatefulDiscoveryInstance(noneMatchDiscoveryInstance); + DataCenterInfo noneMatchInfo = new DataCenterInfo(); + noneMatchInfo.setName("test"); + noneMatchInfo.setRegion("test-Region2"); + noneMatchInfo.setAvailableZone("test-zone2"); + List noMatchEndpoint = new ArrayList<>(); + noMatchEndpoint.add("rest://localhost:7092"); + Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint); + Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo); + Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance"); + + List data = new ArrayList<>(); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + + when(transportManager.findTransport("rest")).thenReturn(transport); + + LoadBalanceFilter handler; + LoadBalancer loadBalancer; + ServiceCombServer server; + + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + Mockito.when(discoveryManager.getOrCreateVersionedCache("testApp", "testMicroserviceName")) + .thenReturn(parent); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new ZoneAwareDiscoveryFilter(); + zoneAwareDiscoveryFilter.setDynamicProperties(dynamicProperties); + zoneAwareDiscoveryFilter.setDataCenterProperties(myself); + ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter(); + serverDiscoveryFilter.setScbEngine(scbEngine); + discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter, + serverDiscoveryFilter)); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertNull(server); + + data.add(noneMatchInstance); + parent.cacheVersion(1); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:7092", server.getEndpoint().getEndpoint()); + + data.add(regionMatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); + + data.add(allmatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); + } + + @Test + public void testStatusFilterUsingMockedInvocationWorks() { + Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName"); + TransportManager transportManager = Mockito.mock(TransportManager.class); + Transport transport = Mockito.mock(Transport.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + Mockito.when(scbEngine.getEnvironment()).thenReturn(environment); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test-Region"); + myself.setAvailableZone("test-zone"); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance allmatchInstance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test-Region"); + info.setAvailableZone("test-zone"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:7090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance"); + Mockito.when(discoveryInstance.getStatus()).thenReturn(MicroserviceInstanceStatus.TESTING); + + DiscoveryInstance regionMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance regionMatchInstance = new StatefulDiscoveryInstance(regionMatchDiscoveryInstance); + DataCenterInfo regionMatchInfo = new DataCenterInfo(); + regionMatchInfo.setName("test"); + regionMatchInfo.setRegion("test-Region"); + regionMatchInfo.setAvailableZone("test-zone2"); + List regionMatchEndpoint = new ArrayList<>(); + regionMatchEndpoint.add("rest://localhost:7091"); + Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint); + Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo); + Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance"); + + DiscoveryInstance noneMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance noneMatchInstance = new StatefulDiscoveryInstance(noneMatchDiscoveryInstance); + DataCenterInfo noneMatchInfo = new DataCenterInfo(); + noneMatchInfo.setName("test"); + noneMatchInfo.setRegion("test-Region2"); + noneMatchInfo.setAvailableZone("test-zone2"); + List noMatchEndpoint = new ArrayList<>(); + noMatchEndpoint.add("rest://localhost:7092"); + Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint); + Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo); + Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance"); + + List data = new ArrayList<>(); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + + when(transportManager.findTransport("rest")).thenReturn(transport); + + LoadBalanceFilter handler; + LoadBalancer loadBalancer; + ServiceCombServer server; + + DiscoveryManager discoveryManager = Mockito.mock(DiscoveryManager.class); + Mockito.when(discoveryManager.getOrCreateVersionedCache("testApp", "testMicroserviceName")) + .thenReturn(parent); + DiscoveryTree discoveryTree = new DiscoveryTree(discoveryManager); + ZoneAwareDiscoveryFilter zoneAwareDiscoveryFilter = new ZoneAwareDiscoveryFilter(); + zoneAwareDiscoveryFilter.setDynamicProperties(dynamicProperties); + zoneAwareDiscoveryFilter.setDataCenterProperties(myself); + ServerDiscoveryFilter serverDiscoveryFilter = new ServerDiscoveryFilter(); + serverDiscoveryFilter.setScbEngine(scbEngine); + discoveryTree.setDiscoveryFilters(Arrays.asList(zoneAwareDiscoveryFilter, + serverDiscoveryFilter)); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertNull(server); + + data.add(noneMatchInstance); + parent.cacheVersion(1); + handler = new LoadBalanceFilter(new ExtensionsManager(new ArrayList<>()), discoveryTree, scbEngine); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:7092", server.getEndpoint().getEndpoint()); + + data.add(regionMatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); + + data.add(allmatchInstance); + parent.cacheVersion(parent.cacheVersion() + 1); + loadBalancer = handler.getOrCreateLoadBalancer(invocation); + server = loadBalancer.chooseServer(invocation); + Assertions.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); + } +} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java deleted file mode 100644 index 7d0938a72fd..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalanceHandler2.java +++ /dev/null @@ -1,992 +0,0 @@ -/* - * 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.loadbalance; - -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.NonSwaggerInvocation; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.core.definition.InvocationRuntimeType; -import org.apache.servicecomb.core.definition.MicroserviceMeta; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.core.definition.SchemaMeta; -import org.apache.servicecomb.core.provider.consumer.ReferenceConfig; -import org.apache.servicecomb.core.transport.TransportManager; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.loadbalance.event.IsolationServerEvent; -import org.apache.servicecomb.loadbalance.filter.IsolationDiscoveryFilter; -import org.apache.servicecomb.loadbalance.filter.ServerDiscoveryFilter; -import org.apache.servicecomb.loadbalance.filter.ZoneAwareDiscoveryFilter; -import org.apache.servicecomb.localregistry.LocalRegistryStore; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.DataCenterInfo; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstanceStatus; -import org.apache.servicecomb.registry.cache.InstanceCacheManager; -import org.apache.servicecomb.registry.discovery.DiscoveryTree; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.mockito.Mockito; - -import com.google.common.eventbus.Subscribe; - -import mockit.Mock; -import mockit.MockUp; - -/** - * - * - */ -public class TestLoadBalanceHandler2 { - private Holder mockTimeMillis; - - private static SCBEngine scbEngine; - - @BeforeClass - public static void beforeClass() { - ConfigUtil.installDynamicConfig(); - ArchaiusUtils.setProperty("servicecomb.loadbalance.userDefinedEndpoint.enabled", "true"); - scbEngine = SCBBootstrap.createSCBEngineForTest().run(); - } - - @AfterClass - public static void afterClass() { - scbEngine.destroy(); - ArchaiusUtils.resetConfig(); - } - - @Before - public void setUp() { - - // avoid mock - ServiceCombLoadBalancerStats.INSTANCE.init(); - TestServiceCombServerStats.releaseTryingChance(); - - mockTimeMillis = new Holder<>(1L); - new MockUp() { - @Mock - long currentTimeMillis() { - return mockTimeMillis.value; - } - }; - } - - @After - public void teardown() { - TestServiceCombServerStats.releaseTryingChance(); - } - - @Test - public void testZoneAwareAndIsolationFilterWorks() throws Exception { - ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); - OperationMeta operationMeta = Mockito.mock(OperationMeta.class); - InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); - SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); - when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); - MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); - when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); - when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); - when(microserviceMeta.getAppId()).thenReturn("testApp"); - when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); - when(referenceConfig.getTransport()).thenReturn("rest"); - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); - - InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class); - TransportManager transportManager = Mockito.mock(TransportManager.class); - Transport transport = Mockito.mock(Transport.class); - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false"); - - // set up data - MicroserviceInstance myself = new MicroserviceInstance(); - DataCenterInfo info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - myself.setDataCenterInfo(info); - - MicroserviceInstance allmatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - List allMatchEndpoint = new ArrayList<>(); - allMatchEndpoint.add("rest://localhost:9090"); - allmatchInstance.setEndpoints(allMatchEndpoint); - allmatchInstance.setDataCenterInfo(info); - allmatchInstance.setInstanceId("allmatchInstance"); - - MicroserviceInstance regionMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone2"); - List regionMatchEndpoint = new ArrayList<>(); - regionMatchEndpoint.add("rest://localhost:9091"); - regionMatchInstance.setEndpoints(regionMatchEndpoint); - regionMatchInstance.setDataCenterInfo(info); - regionMatchInstance.setInstanceId("regionMatchInstance"); - - MicroserviceInstance noneMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region2"); - info.setAvailableZone("test-zone2"); - List noMatchEndpoint = new ArrayList<>(); - noMatchEndpoint.add("rest://localhost:9092"); - noneMatchInstance.setEndpoints(noMatchEndpoint); - noneMatchInstance.setDataCenterInfo(info); - noneMatchInstance.setInstanceId("noneMatchInstance"); - - Map data = new HashMap<>(); - DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); - scbEngine.setTransportManager(transportManager); - LocalRegistryStore.INSTANCE.initSelfWithMocked(null, myself); - mockUpInstanceCacheManager(instanceCacheManager); - when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+")) - .thenReturn(parent); - when(transportManager.findTransport("rest")).thenReturn(transport); - - LoadbalanceHandler handler = null; - LoadBalancer loadBalancer = null; - ServiceCombServer server = null; - - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals(null, server); - - data.put("noneMatchInstance", noneMatchInstance); - parent.cacheVersion(1); - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9092", server.getEndpoint().getEndpoint()); - - data.put("regionMatchInstance", regionMatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - - data.put("allmatchInstance", allmatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - - //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - - //if errorThresholdPercentage greater than 0, it will activate. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10"); - ServiceCombServer server2 = server; - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - mockDelayMillis(20); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - } - - public class IsolationEndpointListener { - Holder count; - - public IsolationEndpointListener(Holder count) { - this.count = count; - } - - @Subscribe - public void listener(IsolationServerEvent event) { - count.value++; - Assert.assertSame("Isolation Endpoint", "rest://localhost:9090", event.getEndpoint().getEndpoint()); - } - } - - @Test - public void testIsolationEventWithEndpoint() throws Exception { - ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); - OperationMeta operationMeta = Mockito.mock(OperationMeta.class); - InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); - SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); - when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); - MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); - when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); - when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); - when(microserviceMeta.getAppId()).thenReturn("testApp"); - when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); - when(referenceConfig.getTransport()).thenReturn("rest"); - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); - - InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class); - TransportManager transportManager = Mockito.mock(TransportManager.class); - Transport transport = Mockito.mock(Transport.class); - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false"); - - // set up data - MicroserviceInstance myself = new MicroserviceInstance(); - DataCenterInfo info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test"); - info.setAvailableZone("test"); - myself.setDataCenterInfo(info); - - MicroserviceInstance instance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test"); - info.setAvailableZone("test"); - List allMatchEndpoint = new ArrayList<>(); - allMatchEndpoint.add("rest://localhost:9090"); - instance.setEndpoints(allMatchEndpoint); - instance.setDataCenterInfo(info); - instance.setInstanceId("instance"); - - Map data = new HashMap<>(); - DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); - scbEngine.setTransportManager(transportManager); - - LocalRegistryStore.INSTANCE.initSelfWithMocked(null, myself); - mockUpInstanceCacheManager(instanceCacheManager); - when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+")) - .thenReturn(parent); - when(transportManager.findTransport("rest")).thenReturn(transport); - - LoadbalanceHandler handler = null; - LoadBalancer loadBalancer = null; - ServiceCombServer server = null; - - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertNull(server); - - data.put("instance", instance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - - //if errorThresholdPercentage greater than 0, it will activate. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "10"); - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10"); - - Holder count = new Holder<>(0); - IsolationEndpointListener isolationEndpointListener = new IsolationEndpointListener(count); - EventManager.getEventBus().register(isolationEndpointListener); - Assert.assertEquals(0, count.value.intValue()); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - // no server is available - Assert.assertNull(server); - Assert.assertEquals(1, count.value.intValue()); - EventManager.unregister(isolationEndpointListener); - } - - @Test - public void testZoneAwareAndIsolationFilterWorksEmptyInstanceProtectionEnabled() throws Exception { - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.isolation.emptyInstanceProtectionEnabled", "true"); - ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); - OperationMeta operationMeta = Mockito.mock(OperationMeta.class); - InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); - SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); - when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); - MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); - when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); - when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); - when(microserviceMeta.getAppId()).thenReturn("testApp"); - when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); - when(referenceConfig.getTransport()).thenReturn("rest"); - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); - - InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class); - TransportManager transportManager = Mockito.mock(TransportManager.class); - Transport transport = Mockito.mock(Transport.class); - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false"); - - // set up data - MicroserviceInstance myself = new MicroserviceInstance(); - DataCenterInfo info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - myself.setDataCenterInfo(info); - - MicroserviceInstance allmatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - List allMatchEndpoint = new ArrayList<>(); - allMatchEndpoint.add("rest://localhost:9090"); - allmatchInstance.setEndpoints(allMatchEndpoint); - allmatchInstance.setDataCenterInfo(info); - allmatchInstance.setInstanceId("allmatchInstance"); - - MicroserviceInstance regionMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone2"); - List regionMatchEndpoint = new ArrayList<>(); - regionMatchEndpoint.add("rest://localhost:9091"); - regionMatchInstance.setEndpoints(regionMatchEndpoint); - regionMatchInstance.setDataCenterInfo(info); - regionMatchInstance.setInstanceId("regionMatchInstance"); - - MicroserviceInstance noneMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region2"); - info.setAvailableZone("test-zone2"); - List noMatchEndpoint = new ArrayList<>(); - noMatchEndpoint.add("rest://localhost:9092"); - noneMatchInstance.setEndpoints(noMatchEndpoint); - noneMatchInstance.setDataCenterInfo(info); - noneMatchInstance.setInstanceId("noneMatchInstance"); - - Map data = new HashMap<>(); - DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); - scbEngine.setTransportManager(transportManager); - - LocalRegistryStore.INSTANCE.initSelfWithMocked(null, myself); - mockUpInstanceCacheManager(instanceCacheManager); - when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+")) - .thenReturn(parent); - when(transportManager.findTransport("rest")).thenReturn(transport); - - LoadbalanceHandler handler = null; - LoadBalancer loadBalancer = null; - ServiceCombServer server = null; - - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals(null, server); - - data.put("noneMatchInstance", noneMatchInstance); - parent.cacheVersion(1); - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9092", server.getEndpoint().getEndpoint()); - - data.put("regionMatchInstance", regionMatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - - data.put("allmatchInstance", allmatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - - //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - - //if errorThresholdPercentage greater than 0, it will activate. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "30"); - ServiceCombServer server2 = server; - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - mockDelayMillis(31); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9090", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:9091", server.getEndpoint().getEndpoint()); - } - - @Test - public void testZoneAwareAndIsolationFilterUsingMockedInvocationWorks() throws Exception { - Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> { - aysnc.success("OK"); - }); - - InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class); - TransportManager transportManager = Mockito.mock(TransportManager.class); - Transport transport = Mockito.mock(Transport.class); - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false"); - - // set up data - MicroserviceInstance myself = new MicroserviceInstance(); - DataCenterInfo info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - myself.setDataCenterInfo(info); - - MicroserviceInstance allmatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - List allMatchEndpoint = new ArrayList<>(); - allMatchEndpoint.add("rest://localhost:7090"); - allmatchInstance.setEndpoints(allMatchEndpoint); - allmatchInstance.setDataCenterInfo(info); - allmatchInstance.setInstanceId("allmatchInstance"); - - MicroserviceInstance regionMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone2"); - List regionMatchEndpoint = new ArrayList<>(); - regionMatchEndpoint.add("rest://localhost:7091"); - regionMatchInstance.setEndpoints(regionMatchEndpoint); - regionMatchInstance.setDataCenterInfo(info); - regionMatchInstance.setInstanceId("regionMatchInstance"); - - MicroserviceInstance noneMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region2"); - info.setAvailableZone("test-zone2"); - List noMatchEndpoint = new ArrayList<>(); - noMatchEndpoint.add("rest://localhost:7092"); - noneMatchInstance.setEndpoints(noMatchEndpoint); - noneMatchInstance.setDataCenterInfo(info); - noneMatchInstance.setInstanceId("noneMatchInstance"); - - Map data = new HashMap<>(); - DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); - scbEngine.setTransportManager(transportManager); - - LocalRegistryStore.INSTANCE.initSelfWithMocked(null, myself); - mockUpInstanceCacheManager(instanceCacheManager); - when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+")) - .thenReturn(parent); - when(transportManager.findTransport("rest")).thenReturn(transport); - - LoadbalanceHandler handler = null; - LoadBalancer loadBalancer = null; - ServiceCombServer server = null; - - DiscoveryTree discoveryTree = new DiscoveryTree(); - discoveryTree.addFilter(new IsolationDiscoveryFilter()); - discoveryTree.addFilter(new ZoneAwareDiscoveryFilter()); - discoveryTree.addFilter(new ServerDiscoveryFilter()); - discoveryTree.sort(); - handler = new LoadbalanceHandler(discoveryTree); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals(null, server); - - data.put("noneMatchInstance", noneMatchInstance); - parent.cacheVersion(1); - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7092", server.getEndpoint().getEndpoint()); - handler.handle(invocation, (response) -> { - Assert.assertEquals("OK", response.getResult()); - }); - - data.put("regionMatchInstance", regionMatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - handler.handle(invocation, (response) -> { - Assert.assertEquals("OK", response.getResult()); - }); - - data.put("allmatchInstance", allmatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); - - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - - //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); - - //if errorThresholdPercentage greater than 0, it will activate. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "30"); - ServiceCombServer server2 = server; - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - mockDelayMillis(31); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - handler.handle(invocation, (response) -> { - Assert.assertEquals("OK", response.getResult()); - }); - } - - @Test - public void testStatusFilterUsingMockedInvocationWorks() throws Exception { - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.status.enabled", "false"); - - Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", (inv, aysnc) -> { - aysnc.success("OK"); - }); - - InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class); - TransportManager transportManager = Mockito.mock(TransportManager.class); - Transport transport = Mockito.mock(Transport.class); - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false"); - - // set up data - MicroserviceInstance myself = new MicroserviceInstance(); - DataCenterInfo info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - myself.setDataCenterInfo(info); - - MicroserviceInstance allmatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone"); - List allMatchEndpoint = new ArrayList<>(); - allMatchEndpoint.add("rest://localhost:7090"); - allmatchInstance.setEndpoints(allMatchEndpoint); - allmatchInstance.setDataCenterInfo(info); - allmatchInstance.setInstanceId("allmatchInstance"); - allmatchInstance.setStatus(MicroserviceInstanceStatus.TESTING); - - MicroserviceInstance regionMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region"); - info.setAvailableZone("test-zone2"); - List regionMatchEndpoint = new ArrayList<>(); - regionMatchEndpoint.add("rest://localhost:7091"); - regionMatchInstance.setEndpoints(regionMatchEndpoint); - regionMatchInstance.setDataCenterInfo(info); - regionMatchInstance.setInstanceId("regionMatchInstance"); - - MicroserviceInstance noneMatchInstance = new MicroserviceInstance(); - info = new DataCenterInfo(); - info.setName("test"); - info.setRegion("test-Region2"); - info.setAvailableZone("test-zone2"); - List noMatchEndpoint = new ArrayList<>(); - noMatchEndpoint.add("rest://localhost:7092"); - noneMatchInstance.setEndpoints(noMatchEndpoint); - noneMatchInstance.setDataCenterInfo(info); - noneMatchInstance.setInstanceId("noneMatchInstance"); - - Map data = new HashMap<>(); - DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); - scbEngine.setTransportManager(transportManager); - - LocalRegistryStore.INSTANCE.initSelfWithMocked(null, myself); - mockUpInstanceCacheManager(instanceCacheManager); - when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+")) - .thenReturn(parent); - when(transportManager.findTransport("rest")).thenReturn(transport); - - LoadbalanceHandler handler = null; - LoadBalancer loadBalancer = null; - ServiceCombServer server = null; - - DiscoveryTree discoveryTree = new DiscoveryTree(); - discoveryTree.addFilter(new IsolationDiscoveryFilter()); - discoveryTree.addFilter(new ZoneAwareDiscoveryFilter()); - discoveryTree.addFilter(new ServerDiscoveryFilter()); - discoveryTree.sort(); - handler = new LoadbalanceHandler(discoveryTree); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals(null, server); - - data.put("noneMatchInstance", noneMatchInstance); - parent.cacheVersion(1); - handler = new LoadbalanceHandler(); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7092", server.getEndpoint().getEndpoint()); - handler.handle(invocation, (response) -> { - Assert.assertEquals("OK", response.getResult()); - }); - - data.put("regionMatchInstance", regionMatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - handler.handle(invocation, (response) -> { - Assert.assertEquals("OK", response.getResult()); - }); - - data.put("allmatchInstance", allmatchInstance); - parent.cacheVersion(parent.cacheVersion() + 1); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); - - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server); - - //if errorThresholdPercentage is 0,that means errorThresholdPercentage is not active. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "0"); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); - - //if errorThresholdPercentage greater than 0, it will activate. - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.errorThresholdPercentage", "20"); - ArchaiusUtils.setProperty("servicecomb.loadbalance.isolation.minIsolationTime", "10"); - ServiceCombServer server2 = server; - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - mockDelayMillis(20); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7090", server.getEndpoint().getEndpoint()); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server2); - loadBalancer = handler.getOrCreateLoadBalancer(invocation); - server = loadBalancer.chooseServer(invocation); - Assert.assertEquals("rest://localhost:7091", server.getEndpoint().getEndpoint()); - handler.handle(invocation, (response) -> { - Assert.assertEquals("OK", response.getResult()); - }); - } - - @Test - public void testConfigEndpoint() { - ReferenceConfig referenceConfig = Mockito.mock(ReferenceConfig.class); - OperationMeta operationMeta = Mockito.mock(OperationMeta.class); - InvocationRuntimeType invocationRuntimeType = Mockito.mock(InvocationRuntimeType.class); - SchemaMeta schemaMeta = Mockito.mock(SchemaMeta.class); - when(operationMeta.getSchemaMeta()).thenReturn(schemaMeta); - MicroserviceMeta microserviceMeta = Mockito.mock(MicroserviceMeta.class); - when(schemaMeta.getMicroserviceMeta()).thenReturn(microserviceMeta); - when(schemaMeta.getMicroserviceName()).thenReturn("testMicroserviceName"); - when(microserviceMeta.getAppId()).thenReturn("testApp"); - when(referenceConfig.getVersionRule()).thenReturn("0.0.0+"); - when(referenceConfig.getTransport()).thenReturn("rest"); - Invocation invocation = new Invocation(referenceConfig, operationMeta, invocationRuntimeType, new HashMap<>()); - AsyncResponse asyncResp = Mockito.mock(AsyncResponse.class); - - InstanceCacheManager instanceCacheManager = Mockito.mock(InstanceCacheManager.class); - TransportManager transportManager = Mockito.mock(TransportManager.class); - Transport transport = Mockito.mock(Transport.class); - ArchaiusUtils.setProperty("servicecomb.loadbalance.filter.operation.enabled", "false"); - - // set up data - MicroserviceInstance myself = new MicroserviceInstance(); - - MicroserviceInstance findInstance = new MicroserviceInstance(); - List findEndpoint = new ArrayList<>(); - findEndpoint.add("rest://localhost:9092"); - findInstance.setEndpoints(findEndpoint); - findInstance.setInstanceId("findInstance"); - - Map data = new HashMap<>(); - DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); - scbEngine.setTransportManager(transportManager); - SCBEngine.getInstance().setTransportManager(transportManager); - - LocalRegistryStore.INSTANCE.initSelfWithMocked(null, myself); - mockUpInstanceCacheManager(instanceCacheManager); - when(instanceCacheManager.getOrCreateVersionedCache("testApp", "testMicroserviceName", "0.0.0+")) - .thenReturn(parent); - when(transportManager.findTransport("rest")).thenReturn(transport); - - data.put("findInstance", findInstance); - parent.cacheVersion(1); - LoadbalanceHandler handler = new LoadbalanceHandler(); - try { - handler.handle(invocation, asyncResp); - } catch (Exception e) { - - } - Assert.assertEquals("rest://localhost:9092", invocation.getEndpoint().getEndpoint()); - - // reset - invocation.setEndpoint(null); - - //success - invocation.addLocalContext("scb-endpoint", "rest://127.0.0.1:8080?sslEnabled=true&protocol=http2"); - try { - handler.handle(invocation, asyncResp); - } catch (Exception e) { - - } - Assert.assertEquals("rest://127.0.0.1:8080?sslEnabled=true&protocol=http2", invocation.getEndpoint().getEndpoint()); - - // reset - invocation.setEndpoint(null); - - //endpoint format is not correct - invocation.addLocalContext("scb-endpoint", "127.0.0.1:8080"); - try { - handler.handle(invocation, asyncResp); - Assert.assertEquals("endpoint's format is not correct, throw exception", " but not throw exception"); - } catch (Exception e) { - Assert.assertTrue(e.getMessage() - .contains("Illegal character in scheme name")); - } - - // reset - invocation.setEndpoint(null); - - //transport is not find - invocation.addLocalContext("scb-endpoint", "my://127.0.0.1:8080?sslEnabled=true&protocol=http2"); - try { - handler.handle(invocation, asyncResp); - Assert.assertEquals("endpoint's transport not found, throw exception", "but not throw exception"); - } catch (Exception e) { - Assert.assertTrue(e.getMessage().contains("the endpoint's transport is not found.")); - } - } - - @Test - public void trying_chance_should_be_released() { - List servers = new ArrayList<>(); - ServiceCombServer serviceCombServer = createMockedServer("instanceId", "rest://127.0.0.1:8080"); - servers.add(serviceCombServer); - - DiscoveryTree discoveryTree = createMockedDiscoveryTree(servers); - LoadbalanceHandler handler = new LoadbalanceHandler(discoveryTree); - - // mock the process of the isolated server selected and changed to TRYING status - ServiceCombServerStats serviceCombServerStats = - mockServiceCombServerStats(serviceCombServer, 5, true); - - Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", - (inv, aysnc) -> { - Assert.assertEquals("rest://127.0.0.1:8080", inv.getEndpoint().getEndpoint()); - Assert.assertTrue(serviceCombServerStats.isIsolated()); - Assert.assertEquals(5, serviceCombServerStats.getContinuousFailureCount()); - Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); - aysnc.success("OK"); - }); - - Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); - invocation.addLocalContext(IsolationDiscoveryFilter.TRYING_INSTANCES_EXISTING, true); - try { - handler.handle(invocation, (response) -> Assert.assertEquals("OK", response.getResult())); - } catch (Exception e) { - Assert.fail("unexpected exception " + e.getMessage()); - } - Assert.assertEquals("rest://127.0.0.1:8080", invocation.getEndpoint().getEndpoint()); - Assert.assertTrue(serviceCombServerStats.isIsolated()); - Assert.assertEquals(0, serviceCombServerStats.getContinuousFailureCount()); - Assert.assertTrue(ServiceCombServerStats.isolatedServerCanTry()); - } - - /** - * Two available instances, first time the normal instance is selected and failed. Then retry to the TRYING status - * instance. In the whole procedure, the TRYING status instance should keep the TRYING status. - */ - @Test - public void first_normal_instance_then_trying_instance() { - ExtensionsManager.addExtentionsFactory(new DefaultRetryExtensionsFactory()); - ArchaiusUtils.setProperty("servicecomb.loadbalance.retryEnabled", true); - ArchaiusUtils.setProperty("servicecomb.loadbalance.retryOnNext", 1); - - ArrayList servers = new ArrayList<>(); - ServiceCombServer server0 = createMockedServer("instanceId0", "rest://127.0.0.1:8080"); - ServiceCombServer server1 = createMockedServer("instanceId1", "rest://127.0.0.1:8081"); - servers.add(server0); - servers.add(server1); - - ServiceCombServerStats stats0 = mockServiceCombServerStats(server0, 0, false); - ServiceCombServerStats stats1 = mockServiceCombServerStats(server1, 5, true); - - DiscoveryTree discoveryTree = createMockedDiscoveryTree(servers); - LoadbalanceHandler handler = new LoadbalanceHandler(discoveryTree); - - Holder counter = new Holder<>(0); - Invocation invocation = new NonSwaggerInvocation("testApp", "testMicroserviceName", "0.0.0+", - (inv, aysnc) -> { - Assert.assertFalse(stats0.isIsolated()); - Assert.assertTrue(stats1.isIsolated()); - Assert.assertEquals(5, stats1.getContinuousFailureCount()); - Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); - if (counter.value == 0) { - Assert.assertEquals("rest://127.0.0.1:8080", inv.getEndpoint().getEndpoint()); - Assert.assertEquals(0, stats0.getContinuousFailureCount()); - counter.value++; - aysnc.producerFail(new InvocationException(503, "RETRY", "retry to next instance")); - } else if (counter.value == 1) { - Assert.assertEquals("rest://127.0.0.1:8081", inv.getEndpoint().getEndpoint()); - Assert.assertEquals(1, stats0.getContinuousFailureCount()); - counter.value++; - aysnc.success("OK"); - } else { - aysnc.producerFail(new InvocationException(400, "UNEXPECTED", "Unexpected Counter Value")); - } - }); - - Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); - invocation.addLocalContext(IsolationDiscoveryFilter.TRYING_INSTANCES_EXISTING, true); - try { - handler.handle(invocation, (response) -> Assert.assertEquals("OK", response.getResult())); - } catch (Exception e) { - Assert.fail("unexpected exception " + e.getMessage()); - } - Assert.assertEquals("rest://127.0.0.1:8081", invocation.getEndpoint().getEndpoint()); - Assert.assertFalse(stats0.isIsolated()); - Assert.assertEquals(1, stats0.getContinuousFailureCount()); - Assert.assertTrue(stats1.isIsolated()); - Assert.assertEquals(0, stats1.getContinuousFailureCount()); - Assert.assertTrue(ServiceCombServerStats.isolatedServerCanTry()); - } - - /** - * Mock the statistics of the specified {@code serviceCombServer}, set the failureCount and status. - * @return the ServiceCombServerStats object corresponding to the param {@code serviceCombServer} - */ - private ServiceCombServerStats mockServiceCombServerStats(ServiceCombServer serviceCombServer, int failureCount, - boolean isIsolatedStatus) { - ServiceCombServerStats serviceCombServerStats = - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer); - for (int i = 0; i < failureCount; ++i) { - serviceCombServerStats.markFailure(); - } - serviceCombServerStats.markIsolated(isIsolatedStatus); - return serviceCombServerStats; - } - - /** - * Create a mocked ServiceCombServer with specified microserviceInstanceId and endpoint. - */ - private ServiceCombServer createMockedServer(String microserviceInstanceId, String endpoint) { - MicroserviceInstance microserviceInstance = new MicroserviceInstance(); - microserviceInstance.setInstanceId(microserviceInstanceId); - return new ServiceCombServer(null, - new Endpoint(Mockito.mock(Transport.class), endpoint), - microserviceInstance); - } - - /** - * Create a mocked DiscoveryTree that always returns {@code servers} as the versionedCache result. - */ - private DiscoveryTree createMockedDiscoveryTree(List servers) { - DiscoveryTree discoveryTree = Mockito.mock(DiscoveryTree.class); - DiscoveryTreeNode versionedCache = new DiscoveryTreeNode() - .name("testVersionedCacheName") - .data(servers); - Mockito.when(discoveryTree.discovery(Mockito.any(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString())) - .thenReturn(versionedCache); - return discoveryTree; - } - - private void mockDelayMillis(long delay) { - mockTimeMillis.value += delay; - } - - private void mockUpInstanceCacheManager(InstanceCacheManager instanceCacheManager) { - new MockUp() { - @Mock - public InstanceCacheManager getInstanceCacheManager() { - return instanceCacheManager; - } - }; - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java index 430e4b0cc79..ba17976e0ba 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadBalancer.java @@ -17,37 +17,36 @@ package org.apache.servicecomb.loadbalance; -import static org.mockito.Mockito.when; - import java.util.ArrayList; import java.util.List; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class TestLoadBalancer { - private RuleExt rule = Mockito.mock(RuleExt.class); + private final RuleExt rule = Mockito.mock(RuleExt.class); @Test public void testLoadBalancerFullOperationWithoutException() { List newServers = new ArrayList<>(); ServiceCombServer server = Mockito.mock(ServiceCombServer.class); Invocation invocation = Mockito.mock(Invocation.class); - MicroserviceInstance microserviceInstance = Mockito.mock(MicroserviceInstance.class); + StatefulDiscoveryInstance microserviceInstance = Mockito.mock(StatefulDiscoveryInstance.class); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); newServers.add(server); - when(invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST)).thenReturn(newServers); - when(server.getInstance()).thenReturn(microserviceInstance); - when(microserviceInstance.getInstanceId()).thenReturn("123456"); + Mockito.when(invocation.getLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST)).thenReturn(newServers); + Mockito.when(server.getInstance()).thenReturn(microserviceInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("123456"); LoadBalancer loadBalancer = new LoadBalancer(rule, "test"); loadBalancer.chooseServer(invocation); - when(rule.choose(newServers, invocation)).thenReturn(server); + Mockito.when(rule.choose(newServers, invocation)).thenReturn(server); - Assert.assertEquals(server, loadBalancer.chooseServer(invocation)); - Assert.assertNotNull(loadBalancer.getLoadBalancerStats()); - Assert.assertEquals("test", loadBalancer.getMicroServiceName()); + Assertions.assertEquals(server, loadBalancer.chooseServer(invocation)); + Assertions.assertEquals("test", loadBalancer.getMicroServiceName()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceClientConfig.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceClientConfig.java deleted file mode 100644 index b2c57a21b6d..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceClientConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.loadbalance; - -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; - -/** - * - * - */ -public class TestLoadbalanceClientConfig { - - @Test - public void testLoadbalanceConstructor() { - - LoadbalanceClientConfig lbc = new LoadbalanceClientConfig("test"); - - assertNotNull(lbc); - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java deleted file mode 100644 index 754c6ddbeaf..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestLoadbalanceHandler.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * 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.loadbalance; - -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.core.transport.TransportManager; -import org.apache.servicecomb.foundation.common.Holder; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; -import org.apache.servicecomb.registry.cache.InstanceCacheManager; -import org.apache.servicecomb.registry.discovery.DiscoveryFilter; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import com.netflix.loadbalancer.LoadBalancerStats; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -/** - * - * - */ -public class TestLoadbalanceHandler { - static SCBEngine scbEngine; - - static InstanceCacheManager instanceCacheManager; - - static TransportManager transportManager; - - String microserviceName = "ms"; - -// IRule rule = Mockito.mock(IRule.class); - - LoadbalanceHandler handler; - - Map loadBalancerMap; - - @Injectable - Invocation invocation; - - @Mocked - Transport restTransport; - - Response sendResponse; - -// List results = new ArrayList<>(); - - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setUp() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest().run(); - transportManager = scbEngine.getTransportManager(); - - new MockUp(invocation) { - @Mock - String getMicroserviceName() { - return microserviceName; - } - - @Mock - void next(AsyncResponse asyncResp) throws Exception { - asyncResp.handle(sendResponse); - } - }; - - new MockUp(transportManager) { - @Mock - Transport findTransport(String transportName) { - return restTransport; - } - }; - - new Expectations(SPIServiceUtils.class) { - { - SPIServiceUtils.getSortedService(DiscoveryFilter.class); - result = Collections.emptyList(); - } - }; - - BeansHolder holder = new BeansHolder(); - List extensionsFactories = new ArrayList<>(); - extensionsFactories.add(new RuleNameExtentionsFactory()); - extensionsFactories.add(new DefaultRetryExtensionsFactory()); - Deencapsulation.setField(holder, "extentionsFactories", extensionsFactories); - holder.init(); - - handler = new LoadbalanceHandler(); - loadBalancerMap = Deencapsulation.getField(handler, "loadBalancerMap"); - } - - @After - public void teardown() { - scbEngine.destroy(); - ArchaiusUtils.resetConfig(); - } - - @Test - public void send_noEndPoint(@Injectable LoadBalancer loadBalancer) { - new Expectations(loadBalancer) { - { - loadBalancer.chooseServer(invocation); - result = null; - } - }; - - Holder result = new Holder<>(); - Deencapsulation.invoke(handler, "send", invocation, (AsyncResponse) resp -> { - result.value = (Throwable) resp.getResult(); - }, loadBalancer); - - Assert.assertEquals("InvocationException: code=500;msg=CommonExceptionData [message=No available address found.]", - result.value.getMessage()); - } - - @Test - public void send_failed2(@Injectable LoadBalancer loadBalancer) { - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("1234"); - CacheEndpoint cacheEndpoint = new CacheEndpoint("rest://localhost:8080", instance1); - ServiceCombServer server = new ServiceCombServer(null, restTransport, cacheEndpoint); - LoadBalancerStats stats = new LoadBalancerStats("test"); - new Expectations(loadBalancer) { - { - loadBalancer.chooseServer(invocation); - result = server; - loadBalancer.getLoadBalancerStats(); - result = stats; - } - }; - sendResponse = Response.create(Status.BAD_REQUEST, "send failed"); - - Holder result = new Holder<>(); - Deencapsulation.invoke(handler, "send", invocation, (AsyncResponse) resp -> { - result.value = (Throwable) resp.getResult(); - }, loadBalancer); - - // InvocationException is not taken as a failure - Assert.assertEquals(0, - loadBalancer.getLoadBalancerStats().getSingleServerStat(server).getSuccessiveConnectionFailureCount()); - Assert.assertEquals("InvocationException: code=400;msg=send failed", - result.value.getMessage()); - } - - @Test - public void send_failed(@Injectable LoadBalancer loadBalancer) { - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("1234"); - CacheEndpoint cacheEndpoint = new CacheEndpoint("rest://localhost:8080", instance1); - ServiceCombServer server = new ServiceCombServer(null, restTransport, cacheEndpoint); - LoadBalancerStats stats = new LoadBalancerStats("test"); - new Expectations(loadBalancer) { - { - loadBalancer.chooseServer(invocation); - result = server; - loadBalancer.getLoadBalancerStats(); - result = stats; - } - }; - sendResponse = Response.consumerFailResp(new SocketException()); - - Holder result = new Holder<>(); - Deencapsulation.invoke(handler, "send", invocation, (AsyncResponse) resp -> { - result.value = (Throwable) resp.getResult(); - }, loadBalancer); - - Assert.assertEquals(1, - loadBalancer.getLoadBalancerStats().getSingleServerStat(server).getSuccessiveConnectionFailureCount()); - Assert.assertEquals( - "InvocationException: code=490;msg=CommonExceptionData [message=Unexpected consumer error, please check logs for details]", - result.value.getMessage()); - } - - @Test - public void send_success(@Injectable LoadBalancer loadBalancer) { - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("1234"); - CacheEndpoint cacheEndpoint = new CacheEndpoint("rest://localhost:8080", instance1); - ServiceCombServer server = new ServiceCombServer(null, restTransport, cacheEndpoint); - LoadBalancerStats stats = new LoadBalancerStats("test"); - new Expectations(loadBalancer) { - { - loadBalancer.chooseServer(invocation); - result = server; - loadBalancer.getLoadBalancerStats(); - result = stats; - } - }; - sendResponse = Response.ok("success"); - - Holder result = new Holder<>(); - Deencapsulation.invoke(handler, "send", invocation, (AsyncResponse) resp -> { - result.value = resp.getResult(); - }, loadBalancer); - - Assert.assertEquals(1, - loadBalancer.getLoadBalancerStats().getSingleServerStat(server).getActiveRequestsCount()); - Assert.assertEquals("success", result.value); - } - - @Test - public void sendWithRetry(@Injectable LoadBalancer loadBalancer) { - Holder result = new Holder<>(); - Deencapsulation.invoke(handler, "sendWithRetry", invocation, (AsyncResponse) resp -> { - result.value = resp.getResult(); - }, loadBalancer); - - // no exception - } - - @Test - public void testIsFailedResponse() { - Assert.assertFalse(handler.isFailedResponse(Response.create(400, "", ""))); - Assert.assertFalse(handler.isFailedResponse(Response.create(500, "", ""))); - Assert.assertTrue(handler.isFailedResponse(Response.create(490, "", ""))); - Assert.assertTrue(handler.isFailedResponse(Response.consumerFailResp(new NullPointerException()))); - } - - @Test - public void retryPoolDaemon() throws ExecutionException, InterruptedException { - ExecutorService RETRY_POOL = Deencapsulation.getField(handler, "RETRY_POOL"); - - Holder nameHolder = new Holder<>(); - - RETRY_POOL.submit(() -> { - nameHolder.value = Thread.currentThread(); - }).get(); - - Assert.assertThat(nameHolder.value.getName(), Matchers.startsWith("retry-pool-thread-")); - Assert.assertTrue(nameHolder.value.isDaemon()); - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java index ce78b503e7f..d381703f445 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestRoundRobinRuleExt.java @@ -22,22 +22,20 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.servicecomb.core.Invocation; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; public class TestRoundRobinRuleExt { @Test public void testRoundRobin() { RoundRobinRuleExt rule = new RoundRobinRuleExt(); - LoadBalancer loadBalancer = new LoadBalancer(rule, "testService"); List servers = new ArrayList<>(); Invocation invocation = Mockito.mock(Invocation.class); for (int i = 0; i < 2; i++) { ServiceCombServer server = Mockito.mock(ServiceCombServer.class); Mockito.when(server.toString()).thenReturn("server " + i); servers.add(server); - loadBalancer.getLoadBalancerStats().noteResponseTime(server, 1); } AtomicInteger server1 = new AtomicInteger(0); @@ -49,21 +47,19 @@ public void testRoundRobin() { server2.incrementAndGet(); } } - Assert.assertEquals(server1.get(), server2.get()); + Assertions.assertEquals(server1.get(), server2.get()); } @Test public void testBenchmarkRobin() { // less than 0.001ms RoundRobinRuleExt rule = new RoundRobinRuleExt(); - LoadBalancer loadBalancer = new LoadBalancer(rule, "testService"); List servers = new ArrayList<>(); Invocation invocation = Mockito.mock(Invocation.class); for (int i = 0; i < 100; i++) { ServiceCombServer server = Mockito.mock(ServiceCombServer.class); Mockito.when(server.toString()).thenReturn("server " + i); servers.add(server); - loadBalancer.getLoadBalancerStats().noteResponseTime(server, 2); } long begin = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) { @@ -71,6 +67,6 @@ public void testBenchmarkRobin() { } long taken = System.currentTimeMillis() - begin; System.out.println("taken " + taken); - Assert.assertEquals("actual token " + taken, taken < 10 * 5, true); // 5 * times make slow machine happy + Assertions.assertTrue(taken < 10 * 5, "actual token " + taken); // 5 * times make slow machine happy } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java deleted file mode 100644 index c539d410229..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombLoadBalancerStats.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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.loadbalance; - -import static org.awaitility.Awaitility.await; - -import java.util.Map; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; -import org.apache.servicecomb.registry.consumer.MicroserviceInstancePing; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import mockit.Deencapsulation; -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mocked; - -public class TestServiceCombLoadBalancerStats { - @Before - public void before() { - // Ensure clean all of mocked server cache before running testMultiThread - // Or the mocked server without instance will cause NPE and the target server will never get ping mark failure - Map pingView = - Deencapsulation.getField(ServiceCombLoadBalancerStats.INSTANCE, "pingView"); - pingView.clear(); - ServiceCombLoadBalancerStats.INSTANCE.init(); - } - - @AfterClass - public static void afterClass() { - Map pingView = - Deencapsulation.getField(ServiceCombLoadBalancerStats.INSTANCE, "pingView"); - pingView.clear(); - ServiceCombLoadBalancerStats.INSTANCE.init(); - } - - @Test - public void testServiceExpire(@Injectable Transport transport, @Mocked SPIServiceUtils utils, @Injectable - MicroserviceInstancePing ping) { - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("instance1"); - - new Expectations() { - { - SPIServiceUtils.getPriorityHighestService(MicroserviceInstancePing.class); - result = ping; - ping.ping(instance); - result = false; - } - }; - - ServiceCombLoadBalancerStats serviceCombLoadBalancerStats = new ServiceCombLoadBalancerStats(); - serviceCombLoadBalancerStats.setServerExpireInSeconds(2); - serviceCombLoadBalancerStats.setTimerIntervalInMillis(500); - serviceCombLoadBalancerStats.init(); - - ServiceCombServer serviceCombServer = new ServiceCombServer(null, transport, - new CacheEndpoint("rest://localhost:8080", instance)); - serviceCombLoadBalancerStats.markSuccess(serviceCombServer); - ServiceCombServerStats stats = serviceCombLoadBalancerStats.getServiceCombServerStats(serviceCombServer); - Assert.assertEquals(serviceCombLoadBalancerStats.getPingView().size(), 1); - await().atMost(5, TimeUnit.SECONDS) - .until(() -> serviceCombLoadBalancerStats.getPingView().size() <= 0); - Assert.assertEquals(serviceCombLoadBalancerStats.getPingView().size(), 0); - System.out.print(stats.getFailedRequests()); - Assert.assertTrue(stats.getFailedRequests() >= 1); - } - - @Test - public void testSimpleThread(@Injectable Transport transport) { - long time = System.currentTimeMillis(); - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("instance1"); - ServiceCombServer serviceCombServer = new ServiceCombServer(null, transport, - new CacheEndpoint("rest://localhost:8080", instance)); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getContinuousFailureCount(), - 2); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getContinuousFailureCount(), - 0); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); - Assert - .assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getTotalRequests(), 4); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRate(), 50); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getSuccessRate(), 50); - Assert.assertTrue( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime() <= System - .currentTimeMillis() - && ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime() - >= time); - } - - @Test - public void testMultiThread(@Injectable Transport transport) throws Exception { - long time = System.currentTimeMillis(); - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("instance2"); - ServiceCombServer serviceCombServer = new ServiceCombServer(null, transport, - new CacheEndpoint("rest://localhost:8080", instance)); - - CountDownLatch latch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - new Thread(() -> { - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markFailure(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(serviceCombServer); - latch.countDown(); - }).start(); - } - latch.await(30, TimeUnit.SECONDS); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getTotalRequests(), - 4 * 10); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRate(), 50); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getSuccessRate(), 50); - Assert.assertEquals( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getSuccessRequests(), 20); - Assert.assertTrue( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime() <= System - .currentTimeMillis() - && ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getLastVisitTime() - >= time); - - // time consuming test for timers, taking about 20 seconds. ping timer will update instance status to failure - Assert.assertTrue( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRate() <= 50); - long beginTime = System.currentTimeMillis(); - long rate = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRequests(); - while (rate <= 20 && - System.currentTimeMillis() - beginTime <= 30000) { - Thread.sleep(2000); - rate = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRequests(); - System.out.println("failedRequests: " + rate); - } - - Assert.assertTrue(System.currentTimeMillis() - beginTime < 30000); - Assert - .assertTrue( - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer).getFailedRequests() - > 20); - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServer.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServer.java index 13acd191729..e914ae20c6a 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServer.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServer.java @@ -17,14 +17,13 @@ package org.apache.servicecomb.loadbalance; -import static org.junit.Assert.assertNotNull; - +import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; -import org.junit.Assert; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; import org.junit.Before; import org.junit.Test; +import org.junit.jupiter.api.Assertions; import org.mockito.Mockito; /** @@ -33,58 +32,61 @@ */ public class TestServiceCombServer { - private Transport transport = Mockito.mock(Transport.class); + private final Transport transport = Mockito.mock(Transport.class); private ServiceCombServer cs; @Before public void setUp() { - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("123456"); - cs = new ServiceCombServer(null, transport, new CacheEndpoint("abcd", instance)); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("123456"); + cs = new ServiceCombServer(null, new Endpoint(transport, "abcd", instance)); } @Test public void testCseServerObj() { - assertNotNull(cs); + Assertions.assertNotNull(cs); } @Test public void testGetEndpoint() { cs.getEndpoint(); - assertNotNull(cs.getEndpoint()); + Assertions.assertNotNull(cs.getEndpoint()); } @Test public void testEqualsMethod() { - Assert.assertFalse(cs.equals((Object) "abcd")); + Assertions.assertNotEquals(cs, (Object) "abcd"); - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("1234"); - ServiceCombServer other = new ServiceCombServer(null, transport, new CacheEndpoint("1234", instance1)); - Assert.assertFalse(cs.equals(other)); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance1 = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("1234"); + ServiceCombServer other = new ServiceCombServer(null, new Endpoint(transport, "1234", instance1)); + Assertions.assertNotEquals(cs, other); - MicroserviceInstance instance2 = new MicroserviceInstance(); - instance2.setInstanceId("123456"); - other = new ServiceCombServer(null, transport, new CacheEndpoint("abcd", instance2)); - Assert.assertTrue(cs.equals(other)); + DiscoveryInstance discoveryInstance2 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance2 = new StatefulDiscoveryInstance(discoveryInstance2); + Mockito.when(discoveryInstance2.getInstanceId()).thenReturn("123456"); + other = new ServiceCombServer(null, new Endpoint(transport, "abcd", instance2)); + Assertions.assertEquals(cs, other); } @Test public void testToStringMethod() { cs.toString(); - assertNotNull(cs.toString()); + Assertions.assertNotNull(cs.toString()); } @Test public void testGetHost() { cs.getHost(); - assertNotNull(cs.getHost()); + Assertions.assertNotNull(cs.getHost()); } @Test public void testHashCodeMethod() { cs.hashCode(); - assertNotNull(cs.hashCode()); + Assertions.assertNotNull(cs.hashCode()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServerStats.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServerStats.java deleted file mode 100644 index dc6d5d9a73d..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestServiceCombServerStats.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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.loadbalance; - -import java.util.Optional; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.test.scaffolding.time.MockClock; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestServiceCombServerStats { - @Before - public void before() { - releaseTryingChance(); - } - - @After - public void after() { - releaseTryingChance(); - } - - @Test - public void testSimpleThread() { - long time = System.currentTimeMillis(); - ServiceCombServerStats stats = new ServiceCombServerStats(null); - stats.markFailure(); - stats.markFailure(); - Assert.assertEquals(2, stats.getContinuousFailureCount()); - stats.markSuccess(); - Assert.assertEquals(0, stats.getContinuousFailureCount()); - stats.markSuccess(); - Assert.assertEquals(4, stats.getTotalRequests()); - Assert.assertEquals(50, stats.getFailedRate()); - Assert.assertEquals(50, stats.getSuccessRate()); - Assert.assertTrue(stats.getLastVisitTime() <= System.currentTimeMillis() && stats.getLastVisitTime() >= time); - Assert.assertTrue(stats.getLastActiveTime() <= System.currentTimeMillis() && stats.getLastActiveTime() >= time); - } - - @Test - public void testMiltiThread() throws Exception { - long time = System.currentTimeMillis(); - ServiceCombServerStats stats = new ServiceCombServerStats(null); - CountDownLatch latch = new CountDownLatch(10); - for (int i = 0; i < 10; i++) { - new Thread(() -> { - stats.markFailure(); - stats.markFailure(); - stats.markSuccess(); - stats.markSuccess(); - latch.countDown(); - }).start(); - } - latch.await(30, TimeUnit.SECONDS); - Assert.assertEquals(4 * 10, stats.getTotalRequests()); - Assert.assertEquals(50, stats.getFailedRate()); - Assert.assertEquals(50, stats.getSuccessRate()); - Assert.assertTrue(stats.getLastVisitTime() <= System.currentTimeMillis() && stats.getLastVisitTime() >= time); - Assert.assertTrue(stats.getLastActiveTime() <= System.currentTimeMillis() && stats.getLastActiveTime() >= time); - } - - @Test - public void testTimeWindow() { - ServiceCombServerStats stats = new ServiceCombServerStats(null, new MockClock(1000L)); - Assert.assertEquals(1000, stats.getLastVisitTime()); - stats.markSuccess(); - stats.markFailure(); - Assert.assertEquals(2, stats.getTotalRequests()); - Assert.assertEquals(50, stats.getFailedRate()); - Assert.assertEquals(50, stats.getSuccessRate()); - stats.clock = new MockClock(60000L + 2000L); - stats.markSuccess(); - Assert.assertEquals(1, stats.getTotalRequests()); - Assert.assertEquals(0, stats.getFailedRate()); - Assert.assertEquals(100, stats.getSuccessRate()); - } - - @Test - public void testGlobalAllowIsolatedServerTryingFlag_apply_with_null_precondition() { - Invocation invocation = new Invocation(); - Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); - Assert.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation()); - } - - @Test - public void testGlobalAllowIsolatedServerTryingFlag_apply_with_chance_occupied() { - Invocation invocation = new Invocation(); - Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); - Assert.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation()); - - Invocation otherInvocation = new Invocation(); - Assert.assertFalse(ServiceCombServerStats.applyForTryingChance(otherInvocation)); - Assert.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation()); - } - - @Test - public void testGlobalAllowIsolatedServerTryingFlag_apply_with_flag_outdated() { - Invocation invocation = new Invocation(); - Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(invocation)); - Assert.assertSame(invocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation()); - ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().clock = new MockClock( - ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().startTryingTimestamp + 60000 - ); - - Invocation otherInvocation = new Invocation(); - Assert.assertTrue(ServiceCombServerStats.applyForTryingChance(otherInvocation)); - Assert - .assertSame(otherInvocation, ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get().getInvocation()); - } - - public static void releaseTryingChance() { - ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.set(null); - } - - public static Invocation getTryingIsolatedServerInvocation() { - return Optional.ofNullable(ServiceCombServerStats.globalAllowIsolatedServerTryingFlag.get()) - .map(TryingIsolatedServerMarker::getInvocation) - .orElse(null); - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionStickinessRule.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionStickinessRule.java new file mode 100644 index 00000000000..9a60b18657c --- /dev/null +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionStickinessRule.java @@ -0,0 +1,223 @@ +/* + * 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.loadbalance; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.servicecomb.core.Endpoint; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.Transport; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.mockito.Mockito; + +import mockit.Deencapsulation; +import mockit.Mock; +import mockit.MockUp; + +public class TestSessionStickinessRule { + @Test + public void testServerWithoutTimeoutAndWithThreshold() { + + boolean status = true; + + SessionStickinessRule ss = new SessionStickinessRule(); + + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List servers = new ArrayList<>(); + servers.add(server); + + Deencapsulation.setField(ss, "lastServer", server); + + ServerMetrics serverMetrics = new ServerMetrics(); + Mockito.when(server.getServerMetrics()).thenReturn(serverMetrics); + + new MockUp() { + + @Mock + private boolean isTimeOut() { + return false; + } + }; + + new MockUp() { + + @Mock + private boolean isErrorThresholdMet(ServiceCombServer server) { + return true; + } + }; + + try { + ss.choose(servers, invocation); + } catch (Exception e) { + e.printStackTrace(); + status = false; + } + Assertions.assertTrue(status); + } + + @Test + public void testServerWithTimeout() { + + boolean status = true; + + SessionStickinessRule ss = new SessionStickinessRule(); + + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List servers = new ArrayList<>(); + servers.add(server); + + Deencapsulation.setField(ss, "lastServer", server); + + new MockUp() { + + @Mock + private boolean isTimeOut() { + return true; + } + }; + + try { + ss.choose(servers, invocation); + } catch (Exception e) { + status = false; + } + + Assertions.assertTrue(status); + } + + @Test + public void testServerWithoutTimeoutException() { + + boolean status = true; + + SessionStickinessRule ss = new SessionStickinessRule(); + + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List servers = new ArrayList<>(); + servers.add(server); + + Deencapsulation.setField(ss, "lastServer", server); + + new MockUp() { + + @Mock + private boolean isTimeOut() { + return false; + } + }; + + try { + ss.choose(servers, invocation); + } catch (Exception e) { + status = false; + } + Assertions.assertFalse(status); + } + + @Test + public void testServerWithoutTimeoutAndThreshold() { + + boolean status = true; + + SessionStickinessRule ss = new SessionStickinessRule(); + + Invocation invocation = mock(Invocation.class); + ServiceCombServer server = mock(ServiceCombServer.class); + List servers = new ArrayList<>(); + servers.add(server); + + Deencapsulation.setField(ss, "lastServer", server); + + new MockUp() { + + @Mock + private boolean isTimeOut() { + return false; + } + }; + + new MockUp() { + + @Mock + private boolean isErrorThresholdMet(ServiceCombServer server) { + return false; + } + }; + + new MockUp() { + + @Mock + private boolean isLastServerExists(ServiceCombServer server) { + return true; + } + }; + + try { + ss.choose(servers, invocation); + } catch (Exception e) { + status = false; + } + Assertions.assertTrue(status); + } + + @Test + public void testLastServerNotExist() { + SessionStickinessRule rule = new SessionStickinessRule(); + + Transport transport = mock(Transport.class); + Invocation invocation = mock(Invocation.class); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance1 = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("1234"); + ServiceCombServer mockedServer = + new ServiceCombServer(null, new Endpoint(transport, "rest:127.0.0.1:8890", instance1)); + List allServers = Arrays.asList(mockedServer); + LoadBalancer lb = new LoadBalancer(rule, "mockedServer"); + when(invocation.getLocalContext(LoadBalanceFilter.CONTEXT_KEY_SERVER_LIST)).thenReturn(allServers); + rule.setLoadBalancer(lb); + ServiceCombServer server = new ServiceCombServer(null, + new Endpoint(transport, "rest:127.0.0.1:8890", instance1)); + Deencapsulation.setField(rule, "lastServer", server); + + new MockUp(rule) { + @Mock + private boolean isTimeOut() { + return false; + } + + @Mock + private boolean isErrorThresholdMet(ServiceCombServer server) { + return false; + } + }; + ServiceCombServer s = rule.choose(allServers, invocation); + Assertions.assertEquals(mockedServer, s); + } +} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java deleted file mode 100644 index ad392b62579..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestSessionSticknessRule.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * 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.loadbalance; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import com.netflix.loadbalancer.LoadBalancerStats; -import com.netflix.loadbalancer.Server; - -import mockit.Deencapsulation; -import mockit.Mock; -import mockit.MockUp; - -public class TestSessionSticknessRule { - - @Test - public void testRuleFullOperation() { - SessionStickinessRule rule = new SessionStickinessRule(); - - LoadBalancer mockedLb = mock(LoadBalancer.class); - Transport transport = mock(Transport.class); - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("1234"); - ServiceCombServer mockedServer = - new ServiceCombServer(null, transport, new CacheEndpoint("rest:127.0.0.1:8889", instance1)); - Invocation invocation = mock(Invocation.class); - LoadBalancerStats stats = mock(LoadBalancerStats.class); - Mockito.when(mockedLb.getLoadBalancerStats()).thenReturn(stats); - Deencapsulation.invoke(rule, "chooseServerWhenTimeout", Arrays.asList(mockedServer), invocation); - mockedServer.setAlive(true); - mockedServer.setReadyToServe(true); - List allServers = Arrays.asList(mockedServer); - rule.setLoadBalancer(mockedLb); - - - Server s = rule.choose(allServers, invocation); - Assert.assertEquals(s, mockedServer); - - s = rule.choose(allServers, invocation); - Assert.assertEquals(s, mockedServer); - } - - @Test - public void testServerWithoutTimeoutAndWithThreshold() { - - boolean status = true; - - SessionStickinessRule ss = new SessionStickinessRule(); - - Invocation invocation = mock(Invocation.class); - ServiceCombServer server = mock(ServiceCombServer.class); - List servers = new ArrayList<>(); - servers.add(server); - - Deencapsulation.setField(ss, "lastServer", server); - - new MockUp() { - - @Mock - private boolean isTimeOut() { - return false; - } - }; - - new MockUp() { - - @Mock - private boolean isErrorThresholdMet() { - return true; - } - }; - - try { - ss.choose(servers, invocation); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - } - - @Test - public void testServerWithTimeout() { - - boolean status = true; - - SessionStickinessRule ss = new SessionStickinessRule(); - - Invocation invocation = mock(Invocation.class); - ServiceCombServer server = mock(ServiceCombServer.class); - List servers = new ArrayList<>(); - servers.add(server); - - Deencapsulation.setField(ss, "lastServer", server); - - new MockUp() { - - @Mock - private boolean isTimeOut() { - return true; - } - }; - - try { - ss.choose(servers, invocation); - } catch (Exception e) { - status = false; - } - - Assert.assertTrue(status); - } - - @Test - public void testServerWithoutTimeoutException() { - - boolean status = true; - - SessionStickinessRule ss = new SessionStickinessRule(); - - Invocation invocation = mock(Invocation.class); - ServiceCombServer server = mock(ServiceCombServer.class); - List servers = new ArrayList<>(); - servers.add(server); - - Deencapsulation.setField(ss, "lastServer", server); - - new MockUp() { - - @Mock - private boolean isTimeOut() { - return false; - } - }; - - try { - ss.choose(servers, invocation); - } catch (Exception e) { - status = false; - } - Assert.assertFalse(status); - } - - @Test - public void testServerWithoutTimeoutAndThreshold() { - - boolean status = true; - - SessionStickinessRule ss = new SessionStickinessRule(); - - Invocation invocation = mock(Invocation.class); - ServiceCombServer server = mock(ServiceCombServer.class); - List servers = new ArrayList<>(); - servers.add(server); - - Deencapsulation.setField(ss, "lastServer", server); - - new MockUp() { - - @Mock - private boolean isTimeOut() { - return false; - } - }; - - new MockUp() { - - @Mock - private boolean isErrorThresholdMet() { - return false; - } - }; - - new MockUp() { - - @Mock - private boolean isLastServerExists(Server server) { - return true; - } - }; - - try { - ss.choose(servers, invocation); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - } - - @Test - public void testServerWithActualServerObj() { - - boolean status = true; - SessionStickinessRule ss = new SessionStickinessRule(); - - Invocation invocation = mock(Invocation.class); - ServiceCombServer server = mock(ServiceCombServer.class); - List servers = new ArrayList<>(); - servers.add(server); - - Deencapsulation.setField(ss, "lastServer", server); - try { - ss.choose(servers, invocation); - } catch (Exception e) { - status = false; - } - Assert.assertTrue(status); - } - - @Test - public void testLastServerNotExist() { - SessionStickinessRule rule = new SessionStickinessRule(); - - Transport transport = mock(Transport.class); - Invocation invocation = mock(Invocation.class); - MicroserviceInstance instance1 = new MicroserviceInstance(); - instance1.setInstanceId("1234"); - ServiceCombServer mockedServer = - new ServiceCombServer(null, transport, new CacheEndpoint("rest:127.0.0.1:8890", instance1)); - mockedServer.setAlive(true); - mockedServer.setReadyToServe(true); - mockedServer.setId("mockedServer"); - List allServers = Arrays.asList(mockedServer); - LoadBalancer lb = new LoadBalancer(rule, "mockedServer"); - when(invocation.getLocalContext(LoadbalanceHandler.CONTEXT_KEY_SERVER_LIST)).thenReturn(allServers); - rule.setLoadBalancer(lb); - ServiceCombServer server = new ServiceCombServer(null, transport, new CacheEndpoint("rest:127.0.0.1:8890", instance1)); - Deencapsulation.setField(rule, "lastServer", server); - - new MockUp(rule) { - @Mock - private boolean isTimeOut() { - return false; - } - - @Mock - private boolean isErrorThresholdMet() { - return false; - } - }; - Server s = rule.choose(allServers, invocation); - Assert.assertEquals(mockedServer, s); - } -} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java index 0d980e8e32f..e3d20d2eea2 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/TestWeightedResponseTimeRuleExt.java @@ -17,27 +17,31 @@ package org.apache.servicecomb.loadbalance; -import org.apache.servicecomb.core.Invocation; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.servicecomb.core.Invocation; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import io.github.resilience4j.core.metrics.Metrics.Outcome; + public class TestWeightedResponseTimeRuleExt { @Test public void testRoundRobin() { WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt(); - LoadBalancer loadBalancer = new LoadBalancer(rule, "testService"); List servers = new ArrayList<>(); Invocation invocation = Mockito.mock(Invocation.class); for (int i = 0; i < 2; i++) { ServiceCombServer server = Mockito.mock(ServiceCombServer.class); + ServerMetrics serverMetrics = new ServerMetrics(); + Mockito.when(server.getServerMetrics()).thenReturn(serverMetrics); Mockito.when(server.toString()).thenReturn("server " + i); servers.add(server); - loadBalancer.getLoadBalancerStats().noteResponseTime(server, 1); + serverMetrics.record(1, TimeUnit.MILLISECONDS, Outcome.SUCCESS); } AtomicInteger server1 = new AtomicInteger(0); @@ -49,29 +53,34 @@ public void testRoundRobin() { server2.incrementAndGet(); } } - Assert.assertEquals(server1.get(), server2.get()); + Assertions.assertEquals(server1.get(), server2.get()); } @Test - public void testWeighed() throws InterruptedException { + public void testWeighed() { WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt(); - LoadBalancer loadBalancer = new LoadBalancer(rule, "testService"); List servers = new ArrayList<>(); Invocation invocation = Mockito.mock(Invocation.class); ServiceCombServer server1 = Mockito.mock(ServiceCombServer.class); Mockito.when(server1.toString()).thenReturn("server " + 0); servers.add(server1); + ServerMetrics serverMetrics1 = new ServerMetrics(); + Mockito.when(server1.getServerMetrics()).thenReturn(serverMetrics1); + ServiceCombServer server2 = Mockito.mock(ServiceCombServer.class); Mockito.when(server2.toString()).thenReturn("server " + 1); servers.add(server2); + ServerMetrics serverMetrics2 = new ServerMetrics(); + Mockito.when(server2.getServerMetrics()).thenReturn(serverMetrics2); AtomicInteger serverCounter1 = new AtomicInteger(0); AtomicInteger serverCounter2 = new AtomicInteger(0); + for (int i = 0; i < 100; i++) { + serverMetrics1.record(200, TimeUnit.MILLISECONDS, Outcome.SUCCESS); + serverMetrics2.record(400, TimeUnit.MILLISECONDS, Outcome.SUCCESS); + } for (int i = 0; i < 2000; i++) { - loadBalancer.getLoadBalancerStats().noteResponseTime(server1, 20); - loadBalancer.getLoadBalancerStats().noteResponseTime(server2, 400); - Thread.sleep(1); if (rule.choose(servers, invocation).toString().equals("server 0")) { serverCounter1.incrementAndGet(); } else { @@ -80,16 +89,15 @@ public void testWeighed() throws InterruptedException { } double percent = (double) serverCounter1.get() / (serverCounter2.get() + serverCounter1.get()); System.out.println("percent" + percent); - Assert.assertTrue(percent > 0.60d); - Assert.assertTrue(percent < 0.90d); + Assertions.assertEquals(0.67d, percent, 0.1); serverCounter1.set(0); serverCounter2.set(0); - Thread.sleep(1000); + for (int i = 0; i < 100; i++) { + serverMetrics1.record(20, TimeUnit.MILLISECONDS, Outcome.SUCCESS); + serverMetrics2.record(20, TimeUnit.MILLISECONDS, Outcome.SUCCESS); + } for (int i = 0; i < 2000; i++) { - loadBalancer.getLoadBalancerStats().noteResponseTime(server1, 20); - loadBalancer.getLoadBalancerStats().noteResponseTime(server2, 20); - Thread.sleep(1); if (rule.choose(servers, invocation).toString().equals("server 0")) { serverCounter1.incrementAndGet(); } else { @@ -98,7 +106,7 @@ public void testWeighed() throws InterruptedException { } percent = (double) serverCounter1.get() / (serverCounter2.get() + serverCounter1.get()); System.out.println("percent" + percent); - Assert.assertEquals(0.50d, percent, 0.2); + Assertions.assertEquals(0.50d, percent, 0.1); } @Test @@ -106,43 +114,45 @@ public void testBenchmark() { // 100 instances will taken less than 0.1ms. Because we use weighed rule when response time more than 10ms, // This only taken 1/1000 time. WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt(); - LoadBalancer loadBalancer = new LoadBalancer(rule, "testService"); List servers = new ArrayList<>(); Invocation invocation = Mockito.mock(Invocation.class); for (int i = 0; i < 100; i++) { ServiceCombServer server = Mockito.mock(ServiceCombServer.class); + ServerMetrics serverMetrics = new ServerMetrics(); Mockito.when(server.toString()).thenReturn("server " + i); + Mockito.when(server.getServerMetrics()).thenReturn(serverMetrics); servers.add(server); - loadBalancer.getLoadBalancerStats().noteResponseTime(server, i); + serverMetrics.record(i, TimeUnit.MILLISECONDS, Outcome.SUCCESS); } long begin = System.currentTimeMillis(); - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 100000; i++) { rule.choose(servers, invocation); } long taken = System.currentTimeMillis() - begin; System.out.println("taken " + taken); - Assert.assertEquals("actually taken: " + taken, taken < 1000 * 5, true); // 5 * times make slow machine happy + Assertions.assertTrue(taken < 1000 * 5, "actually taken: " + taken); // 5 * times make slow machine happy } @Test public void testBenchmarkRobin() { // 100 instances will taken less than 0.02ms. Not as good as RoundRobinRule, which taken less than 0.001ms WeightedResponseTimeRuleExt rule = new WeightedResponseTimeRuleExt(); - LoadBalancer loadBalancer = new LoadBalancer(rule, "testService"); List servers = new ArrayList<>(); Invocation invocation = Mockito.mock(Invocation.class); for (int i = 0; i < 100; i++) { ServiceCombServer server = Mockito.mock(ServiceCombServer.class); + ServerMetrics serverMetrics = new ServerMetrics(); Mockito.when(server.toString()).thenReturn("server " + i); + Mockito.when(server.getServerMetrics()).thenReturn(serverMetrics); servers.add(server); - loadBalancer.getLoadBalancerStats().noteResponseTime(server, 2); + serverMetrics.record(2, TimeUnit.MILLISECONDS, Outcome.SUCCESS); } long begin = System.currentTimeMillis(); - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 100000; i++) { rule.choose(servers, invocation); } long taken = System.currentTimeMillis() - begin; System.out.println("taken " + taken); - Assert.assertEquals("actually taken: " + taken, taken < 200 * 5, true); // 5 * times make slow machine happy + Assertions.assertTrue(taken < 200 * 5, "actually taken: " + taken); // 5 * times make slow machine happy } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/exception/TestLoadbalanceExceptionUtils.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/exception/TestLoadbalanceExceptionUtils.java index 390f6de07c5..71b929af53e 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/exception/TestLoadbalanceExceptionUtils.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/exception/TestLoadbalanceExceptionUtils.java @@ -17,25 +17,19 @@ package org.apache.servicecomb.loadbalance.exception; -import static org.junit.Assert.assertEquals; - import org.apache.servicecomb.core.exception.CseException; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -/** - * - * - */ public class TestLoadbalanceExceptionUtils { @Test public void testLoadbalanceExceptionUtils() { - assertEquals("servicecomb.handler.lb.wrong.rule", LoadbalanceExceptionUtils.CSE_HANDLER_LB_WRONG_RULE); + Assertions.assertEquals("servicecomb.handler.lb.wrong.rule", LoadbalanceExceptionUtils.CSE_HANDLER_LB_WRONG_RULE); CseException cseException = LoadbalanceExceptionUtils.createLoadbalanceException("servicecomb.handler.lb.wrong.rule", new Throwable(), "ARGS"); - Assert.assertNotNull(cseException); + Assertions.assertNotNull(cseException); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilterTest.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilterTest.java deleted file mode 100644 index f2ad8c60e9a..00000000000 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/IsolationDiscoveryFilterTest.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * 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.loadbalance.filter; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.loadbalance.Configuration; -import org.apache.servicecomb.loadbalance.ServiceCombLoadBalancerStats; -import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.loadbalance.ServiceCombServerStats; -import org.apache.servicecomb.loadbalance.TestServiceCombServerStats; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.CacheEndpoint; -import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import mockit.Deencapsulation; -import mockit.Mocked; - -public class IsolationDiscoveryFilterTest { - - private DiscoveryContext discoveryContext; - - private DiscoveryTreeNode discoveryTreeNode; - - private Map data; - - private IsolationDiscoveryFilter filter; - - @Mocked - private Transport transport = Mockito.mock(Transport.class); - - private Invocation invocation = new Invocation() { - @Override - public String getMicroserviceName() { - return "testMicroserviceName"; - } - }; - - @Before - public void before() { - discoveryContext = new DiscoveryContext(); - discoveryContext.setInputParameters(invocation); - discoveryTreeNode = new DiscoveryTreeNode(); - Mockito.doAnswer(a -> a.getArguments()[0]).when(transport).parseAddress(Mockito.anyString()); - data = new HashMap<>(); - for (int i = 0; i < 3; ++i) { - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("i" + i); - String endpoint = "rest://127.0.0.1:" + i; - instance.setEndpoints(Collections.singletonList(endpoint)); - data.put(instance.getInstanceId(), instance); - ServiceCombServer serviceCombServer = new ServiceCombServer(invocation.getMicroserviceName(), transport, - new CacheEndpoint(endpoint, instance)); - ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(serviceCombServer); - } - discoveryTreeNode.data(data); - - filter = new IsolationDiscoveryFilter(); - TestServiceCombServerStats.releaseTryingChance(); - } - - @After - public void after() { - Deencapsulation.invoke(ServiceCombLoadBalancerStats.INSTANCE, "init"); - TestServiceCombServerStats.releaseTryingChance(); - } - - @Test - public void discovery_no_instance_reach_error_threshold() { - DiscoveryTreeNode childNode = filter.discovery(discoveryContext, discoveryTreeNode); - - Map childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - } - - @Test - public void discovery_isolate_error_instance() { - ServiceCombServer server0 = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServer(data.get("i0")); - for (int i = 0; i < 4; ++i) { - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server0); - } - DiscoveryTreeNode childNode = filter.discovery(discoveryContext, discoveryTreeNode); - Map childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - - // by default 5 times continuous failure will cause isolation - ServiceCombLoadBalancerStats.INSTANCE.markFailure(server0); - Assert.assertFalse(ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server0).isIsolated()); - - childNode = filter.discovery(discoveryContext, discoveryTreeNode); - childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i1", "i2")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - Assert.assertTrue(ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server0).isIsolated()); - } - - @Test - public void discovery_try_isolated_instance_after_singleTestTime() { - ServiceCombServer server0 = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServer(data.get("i0")); - ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE - .getServiceCombServerStats(server0); - for (int i = 0; i < 5; ++i) { - serviceCombServerStats.markFailure(); - } - letIsolatedInstancePassSingleTestTime(serviceCombServerStats); - ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true); - - Assert.assertTrue(ServiceCombServerStats.isolatedServerCanTry()); - Assert.assertNull(TestServiceCombServerStats.getTryingIsolatedServerInvocation()); - DiscoveryTreeNode childNode = filter.discovery(discoveryContext, discoveryTreeNode); - Map childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - Assert.assertTrue(serviceCombServerStats.isIsolated()); - Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); - Assert.assertSame(invocation, TestServiceCombServerStats.getTryingIsolatedServerInvocation()); - } - - @Test - public void discovery_not_try_isolated_instance_concurrently() { - ServiceCombServer server0 = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServer(data.get("i0")); - ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE - .getServiceCombServerStats(server0); - for (int i = 0; i < 5; ++i) { - serviceCombServerStats.markFailure(); - } - ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true); - letIsolatedInstancePassSingleTestTime(serviceCombServerStats); - - Assert.assertTrue(ServiceCombServerStats.isolatedServerCanTry()); - - // The first invocation can occupy the trying chance - DiscoveryTreeNode childNode = filter.discovery(discoveryContext, discoveryTreeNode); - Map childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); - - // Other invocation cannot get trying chance concurrently - childNode = filter.discovery(discoveryContext, discoveryTreeNode); - childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i1", "i2")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - - ServiceCombServerStats - .checkAndReleaseTryingChance(invocation); // after the first invocation releases the trying chance - - // Other invocation can get the trying chance - childNode = filter.discovery(discoveryContext, discoveryTreeNode); - childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - Assert.assertFalse(ServiceCombServerStats.isolatedServerCanTry()); - } - - private ServiceCombServerStats letIsolatedInstancePassSingleTestTime(ServiceCombServerStats serviceCombServerStats) { - Deencapsulation.setField(serviceCombServerStats, "lastActiveTime", - System.currentTimeMillis() - 1 - Configuration.INSTANCE.getSingleTestTime(invocation.getMicroserviceName())); - Deencapsulation.setField(serviceCombServerStats, "lastVisitTime", - System.currentTimeMillis() - 1 - Configuration.INSTANCE.getSingleTestTime(invocation.getMicroserviceName())); - return serviceCombServerStats; - } - - @Test - public void discovery_keep_minIsolationTime() { - ServiceCombServer server0 = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServer(data.get("i0")); - ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server0); - - DiscoveryTreeNode childNode = filter.discovery(discoveryContext, discoveryTreeNode); - Map childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i1", "i2")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - - ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE - .getServiceCombServerStats(server0); - Deencapsulation.setField(serviceCombServerStats, "isolatedTime", - System.currentTimeMillis() - Configuration.INSTANCE.getMinIsolationTime(invocation.getMicroserviceName()) - 1); - childNode = filter.discovery(discoveryContext, discoveryTreeNode); - childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - } - - @Test - public void discovery_recover_instance() { - ServiceCombServer server0 = ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServer(data.get("i0")); - ServiceCombLoadBalancerStats.INSTANCE.markSuccess(server0); - ServiceCombServerStats serviceCombServerStats = ServiceCombLoadBalancerStats.INSTANCE - .getServiceCombServerStats(server0); - - ServiceCombLoadBalancerStats.INSTANCE.markIsolated(server0, true); - Deencapsulation.setField(serviceCombServerStats, "isolatedTime", - System.currentTimeMillis() - Configuration.INSTANCE.getMinIsolationTime(invocation.getMicroserviceName()) - 1); - - DiscoveryTreeNode childNode = filter.discovery(discoveryContext, discoveryTreeNode); - Map childNodeData = childNode.data(); - Assert.assertThat(childNodeData.keySet(), Matchers.containsInAnyOrder("i0", "i1", "i2")); - Assert.assertEquals(data.get("i0"), childNodeData.get("i0")); - Assert.assertEquals(data.get("i1"), childNodeData.get("i1")); - Assert.assertEquals(data.get("i2"), childNodeData.get("i2")); - Assert.assertFalse(ServiceCombLoadBalancerStats.INSTANCE.getServiceCombServerStats(server0).isIsolated()); - } -} \ No newline at end of file diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/PriorityInstancePropertyDiscoveryFilterTest.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/PriorityInstancePropertyDiscoveryFilterTest.java new file mode 100644 index 00000000000..7c78388dcdc --- /dev/null +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/PriorityInstancePropertyDiscoveryFilterTest.java @@ -0,0 +1,158 @@ +/* + * 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.loadbalance.filter; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.servicecomb.config.DynamicProperties; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.DiscoveryContext; +import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; + +import com.google.common.collect.Sets; + +/** + * Test for PriorityInstancePropertyDiscoveryFilter + */ +public class PriorityInstancePropertyDiscoveryFilterTest { + + public static final String PROPERTY_KEY = "environment"; + + private PriorityInstancePropertyDiscoveryFilter filter; + + private List instances; + + StatefulDiscoveryInstance instance1; + + ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class); + + EnumerablePropertySource propertySource; + + DynamicProperties dynamicProperties = Mockito.mock(DynamicProperties.class); + + @Before + public void setUp() { + propertySource = Mockito.mock(EnumerablePropertySource.class); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.service.properties." + PROPERTY_KEY + }); + + filter = new PriorityInstancePropertyDiscoveryFilter(); + filter.setEnvironment(environment); + filter.setDynamicProperties(dynamicProperties); + Mockito.when(dynamicProperties.getStringProperty(Mockito.eq("servicecomb.loadbalance.filter.priorityInstanceProperty.key"), + Mockito.any(), + Mockito.eq("environment"))).thenReturn("environment"); + instances = new ArrayList<>(); + filter.setEnvironment(environment); + DiscoveryInstance discoveryInstance1 = Mockito.mock(DiscoveryInstance.class); + instance1 = new StatefulDiscoveryInstance(discoveryInstance1); + Mockito.when(discoveryInstance1.getInstanceId()).thenReturn("instance.empty"); + + DiscoveryInstance discoveryInstance2 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance2 = new StatefulDiscoveryInstance(discoveryInstance2); + Mockito.when(discoveryInstance2.getInstanceId()).thenReturn("instance.local"); + Map properties = new HashMap<>(); + properties.put(PROPERTY_KEY, "local"); + Mockito.when(discoveryInstance2.getProperties()).thenReturn(properties); + + DiscoveryInstance discoveryInstance3 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance3 = new StatefulDiscoveryInstance(discoveryInstance3); + Mockito.when(discoveryInstance3.getInstanceId()).thenReturn("instance.local.feature1"); + Map properties3 = new HashMap<>(); + properties3.put(PROPERTY_KEY, "local.feature1"); + Mockito.when(discoveryInstance3.getProperties()).thenReturn(properties3); + + DiscoveryInstance discoveryInstance4 = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance4 = new StatefulDiscoveryInstance(discoveryInstance4); + Mockito.when(discoveryInstance4.getInstanceId()).thenReturn("instance.local.feature1.sprint1"); + Map properties4 = new HashMap<>(); + properties4.put(PROPERTY_KEY, "local.feature1.sprint1"); + Mockito.when(discoveryInstance4.getProperties()).thenReturn(properties4); + + instances.add(instance1); + instances.add(instance2); + instances.add(instance3); + instances.add(instance4); + } + + @After + public void cleanup() { + } + + @Test + public void testGetFilteredListOfServers() { + + //complete match + executeTest("", Sets.newHashSet("instance.empty")); + executeTest("local", Sets.newHashSet("instance.local")); + executeTest("local.feature1", Sets.newHashSet("instance.local.feature1")); + executeTest("local.feature1.sprint1", Sets.newHashSet("instance.local.feature1.sprint1")); + + //priority match + executeTest("test", Sets.newHashSet("instance.empty")); + executeTest("local.feature2", Sets.newHashSet("instance.local")); + executeTest("local.feature1.sprint2", Sets.newHashSet("instance.local.feature1")); + executeTest("local.feature2.sprint1", Sets.newHashSet("instance.local")); + executeTest("local.feature1.sprint2.temp", Sets.newHashSet("instance.local.feature1")); + + //none match + instances.remove(instance1); + executeTest("", Collections.emptySet()); + executeTest("foo", Collections.emptySet()); + instances.add(instance1); + } + + + private void executeTest(String selfProperty, Set expectedMatchedKeys) { + Mockito.when(environment.getProperty("servicecomb.service.properties." + PROPERTY_KEY)).thenReturn(selfProperty); + + Invocation invocation = new Invocation(); + DiscoveryContext discoveryContext = new DiscoveryContext(); + discoveryContext.setInputParameters(invocation); + + DiscoveryTreeNode parent = new DiscoveryTreeNode(); + parent.name("parent"); + parent.data(instances); + + DiscoveryTreeNode node = filter.discovery(discoveryContext, parent); + List filterInstance = node.data(); + assertThat(filterInstance.stream().map(instance -> instance.getInstanceId()).collect( + Collectors.toList())).containsAnyElementsOf(expectedMatchedKeys); + } +} diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestInstancePropertyDiscoveryFilter.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestInstancePropertyDiscoveryFilter.java index 17dfe99a513..0c498d25de2 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestInstancePropertyDiscoveryFilter.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestInstancePropertyDiscoveryFilter.java @@ -17,81 +17,93 @@ package org.apache.servicecomb.loadbalance.filter; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.commons.configuration.BaseConfiguration; import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.registry.api.DiscoveryInstance; import org.apache.servicecomb.registry.discovery.DiscoveryContext; import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Injectable; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; public class TestInstancePropertyDiscoveryFilter { private InstancePropertyDiscoveryFilter filter; - MicroserviceInstance instance = new MicroserviceInstance(); + StatefulDiscoveryInstance instance; - @BeforeClass - public static void beforeCls() { - AbstractConfiguration configuration = new BaseConfiguration(); - configuration.addProperty("servicecomb.loadbalance.test.flowsplitFilter.policy", - "org.apache.servicecomb.loadbalance.filter.SimpleFlowsplitFilter"); - configuration.addProperty("servicecomb.loadbalance.test.flowsplitFilter.options.tag0", "value0"); - } + ConfigurableEnvironment environment; + + EnumerablePropertySource propertySource; - @Before + @BeforeEach public void setUp() { + environment = Mockito.mock(ConfigurableEnvironment.class); + LegacyPropertyFactory.setEnvironment(environment); + propertySource = Mockito.mock(EnumerablePropertySource.class); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.loadbalance.test.flowsplitFilter.policy", + "servicecomb.loadbalance.test.flowsplitFilter.options.tag0" + }); + Mockito.when(environment.getProperty("servicecomb.loadbalance.test.flowsplitFilter.policy")) + .thenReturn("org.apache.servicecomb.loadbalance.filter.SimpleFlowsplitFilter"); + Mockito.when(environment.getProperty("servicecomb.loadbalance.test.flowsplitFilter.options.tag0")) + .thenReturn("value0"); + filter = new InstancePropertyDiscoveryFilter(); Map properties = new HashMap<>(); properties.put("tag0", "value0"); properties.put("tag1", "value1"); - instance.setInstanceId("instance111"); - instance.setProperties(properties); + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + instance = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("instance111"); + Mockito.when(discoveryInstance.getProperties()).thenReturn(properties); } @Test public void testAllowVisit() { Map filterOptions = new HashMap<>(); - Assert.assertTrue(filter.allowVisit(instance, filterOptions)); + Assertions.assertTrue(filter.allowVisit(instance, filterOptions)); filterOptions.put("tag0", "value0"); - Assert.assertTrue(filter.allowVisit(instance, filterOptions)); + Assertions.assertTrue(filter.allowVisit(instance, filterOptions)); filterOptions.put("tag2", "value2"); - Assert.assertFalse(filter.allowVisit(instance, filterOptions)); + Assertions.assertFalse(filter.allowVisit(instance, filterOptions)); filterOptions.clear(); filterOptions.put("tag0", "value1"); - Assert.assertFalse(filter.allowVisit(instance, filterOptions)); + Assertions.assertFalse(filter.allowVisit(instance, filterOptions)); } @Test @SuppressWarnings("unchecked") - public void testGetFilteredListOfServers(@Injectable DiscoveryContext context, @Injectable DiscoveryTreeNode parent, - @Injectable Invocation invocation) { - Map instances = new HashMap<>(); - instances.put(instance.getInstanceId(), instance); - new Expectations() { - { - context.getInputParameters(); - result = invocation; - parent.data(); - result = instances; - parent.name(); - result = "parent"; - } - }; + public void testGetFilteredListOfServers() { + DiscoveryContext context = new DiscoveryContext(); + DiscoveryTreeNode parent = new DiscoveryTreeNode(); + + Invocation invocation = Mockito.mock(Invocation.class); + context.setInputParameters(invocation); + + List instances = new ArrayList<>(); + instances.add(instance); + parent.data(instances); + parent.name("parent"); DiscoveryTreeNode node = filter.discovery(context, parent); - Assert.assertEquals(1, ((Map) node.data()).keySet().size()); + Assertions.assertEquals(1, ((List) node.data()).size()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java index e0370d01a00..a4aa3a5191a 100644 --- a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestServerDiscoveryFilter.java @@ -17,81 +17,57 @@ package org.apache.servicecomb.loadbalance.filter; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Const; +import static org.mockito.ArgumentMatchers.any; + +import org.apache.servicecomb.core.CoreConst; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.SCBEngine; import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; import org.apache.servicecomb.core.transport.TransportManager; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; +import org.apache.servicecomb.registry.api.DiscoveryInstance; import org.apache.servicecomb.registry.discovery.DiscoveryContext; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mocked; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class TestServerDiscoveryFilter { - static SCBEngine scbEngine; - - static TransportManager transportManager; - ServerDiscoveryFilter filter = new ServerDiscoveryFilter(); - @Mocked - Transport trasport; - - @BeforeClass - public static void setup() { - ConfigUtil.installDynamicConfig(); - scbEngine = SCBBootstrap.createSCBEngineForTest().run(); - transportManager = scbEngine.getTransportManager(); - } - - @AfterClass - public static void teardown() { - scbEngine.destroy(); - ArchaiusUtils.resetConfig(); - } - @Test public void createEndpoint_TransportNotExist() { - new Expectations(transportManager) { - { - transportManager.findTransport(anyString); - result = null; - } - }; - - ServiceCombServer server = (ServiceCombServer) filter.createEndpoint(null, Const.RESTFUL, null, null); - Assert.assertNull(server); + TransportManager transportManager = Mockito.mock(TransportManager.class); + Mockito.when(transportManager.findTransport(any(String.class))).thenReturn(null); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + filter.setScbEngine(scbEngine); + ServiceCombServer server = (ServiceCombServer) filter.createEndpoint(null, CoreConst.RESTFUL, null, null); + Assertions.assertNull(server); } @Test - public void createEndpointNormal(@Injectable DiscoveryContext context, @Injectable Invocation invocation) { - new Expectations(transportManager) { - { - transportManager.findTransport(anyString); - result = trasport; - context.getInputParameters(); - result = invocation; - invocation.getMicroserviceName(); - result = "test"; - } - }; - MicroserviceInstance instance = new MicroserviceInstance(); - instance.setInstanceId("0000001"); + public void createEndpointNormal() { + TransportManager transportManager = Mockito.mock(TransportManager.class); + SCBEngine scbEngine = Mockito.mock(SCBEngine.class); + Mockito.when(scbEngine.getTransportManager()).thenReturn(transportManager); + Transport transport = Mockito.mock(Transport.class); + Invocation invocation = Mockito.mock(Invocation.class); + Mockito.when(transportManager.findTransport(any(String.class))).thenReturn(transport); + Mockito.when(invocation.getConfigTransportName()).thenReturn(CoreConst.RESTFUL); + Mockito.when(invocation.getMicroserviceName()).thenReturn("test"); + DiscoveryContext context = new DiscoveryContext(); + context.setInputParameters(invocation); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance instance = new StatefulDiscoveryInstance(discoveryInstance); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("0000001"); + filter.setScbEngine(scbEngine); ServiceCombServer server = (ServiceCombServer) filter - .createEndpoint(context, Const.RESTFUL, "rest://localhost:8080", instance); - Assert.assertSame(instance, server.getInstance()); - Assert.assertSame(trasport, server.getEndpoint().getTransport()); - Assert.assertEquals("rest://localhost:8080", server.getEndpoint().getEndpoint()); + .createEndpoint(context, CoreConst.RESTFUL, "rest://localhost:8080", instance); + Assertions.assertSame(instance, server.getInstance()); + Assertions.assertSame(transport, server.getEndpoint().getTransport()); + Assertions.assertEquals("rest://localhost:8080", server.getEndpoint().getEndpoint()); } } diff --git a/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestZoneAwareDiscoveryFilter.java b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestZoneAwareDiscoveryFilter.java new file mode 100644 index 00000000000..05b6d5432ca --- /dev/null +++ b/handlers/handler-loadbalance/src/test/java/org/apache/servicecomb/loadbalance/filter/TestZoneAwareDiscoveryFilter.java @@ -0,0 +1,197 @@ +/* + * 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.loadbalance.filter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.servicecomb.config.DataCenterProperties; +import org.apache.servicecomb.config.DynamicProperties; +import org.apache.servicecomb.registry.api.DataCenterInfo; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.discovery.DiscoveryContext; +import org.apache.servicecomb.registry.discovery.DiscoveryTreeNode; +import org.apache.servicecomb.registry.discovery.StatefulDiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class TestZoneAwareDiscoveryFilter { + DynamicProperties dynamicProperties = Mockito.mock(DynamicProperties.class); + + @BeforeEach + public void setUp() { + + Mockito.when(dynamicProperties.getBooleanProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.enabled"), + Mockito.any(), + Mockito.eq(true))) + .thenReturn(true); + } + + @Test + public void test_not_enough_instance() { + + Mockito.when(dynamicProperties.getIntProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.ratio"), + Mockito.any(), + Mockito.eq(30))) + .thenReturn(50); + Mockito.when(dynamicProperties.getIntProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.ratioCeiling"), + Mockito.any(), + Mockito.eq(50))) + .thenReturn(70); + + ZoneAwareDiscoveryFilter filter = new ZoneAwareDiscoveryFilter(); + filter.setDynamicProperties(dynamicProperties); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test-Region"); + myself.setAvailableZone("test-zone"); + filter.setDataCenterProperties(myself); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance allmatchInstance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test-Region"); + info.setAvailableZone("test-zone"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:9090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance"); + + DiscoveryInstance regionMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance regionMatchInstance = new StatefulDiscoveryInstance(regionMatchDiscoveryInstance); + DataCenterInfo regionMatchInfo = new DataCenterInfo(); + regionMatchInfo.setName("test"); + regionMatchInfo.setRegion("test-Region"); + regionMatchInfo.setAvailableZone("test-zone2"); + List regionMatchEndpoint = new ArrayList<>(); + regionMatchEndpoint.add("rest://localhost:9091"); + Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint); + Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo); + Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance"); + + DiscoveryInstance noneMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance noneMatchInstance = new StatefulDiscoveryInstance(noneMatchDiscoveryInstance); + DataCenterInfo noneMatchInfo = new DataCenterInfo(); + noneMatchInfo.setName("test"); + noneMatchInfo.setRegion("test-Region2"); + noneMatchInfo.setAvailableZone("test-zone2"); + List noMatchEndpoint = new ArrayList<>(); + noMatchEndpoint.add("rest://localhost:9092"); + Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint); + Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo); + Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance"); + + // run test + List data = Arrays.asList(allmatchInstance, regionMatchInstance, noneMatchInstance); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + DiscoveryContext context = new DiscoveryContext(); + DiscoveryTreeNode result = filter.discovery(context, parent); + + // check result + Integer level = context.getContextParameter(filter.contextParameter()); + Integer groups = parent.attribute(filter.groupsSizeParameter()); + List resultData = result.data(); + Assertions.assertEquals(1, level); + Assertions.assertEquals(2, groups); + Assertions.assertEquals(2, resultData.size()); + Assertions.assertEquals("regionMatchInstance", resultData.get(0).getInstanceId()); + Assertions.assertEquals("allmatchInstance", resultData.get(1).getInstanceId()); + } + + @Test + public void test_not_enough_instance_both_ceiling_floor() { + + Mockito.when(dynamicProperties.getIntProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.ratio"), + Mockito.any(), + Mockito.eq(30))) + .thenReturn(40); + Mockito.when(dynamicProperties.getIntProperty(Mockito.eq("servicecomb.loadbalance.filter.zoneaware.ratioCeiling"), + Mockito.any(), + Mockito.eq(60))) + .thenReturn(60); + + ZoneAwareDiscoveryFilter filter = new ZoneAwareDiscoveryFilter(); + filter.setDynamicProperties(dynamicProperties); + + // set up data + DataCenterProperties myself = new DataCenterProperties(); + myself.setName("test"); + myself.setRegion("test-Region"); + myself.setAvailableZone("test-zone"); + filter.setDataCenterProperties(myself); + + DiscoveryInstance discoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance allmatchInstance = new StatefulDiscoveryInstance(discoveryInstance); + DataCenterInfo info = new DataCenterInfo(); + info.setName("test"); + info.setRegion("test-Region"); + info.setAvailableZone("test-zone"); + List allMatchEndpoint = new ArrayList<>(); + allMatchEndpoint.add("rest://localhost:9090"); + Mockito.when(discoveryInstance.getEndpoints()).thenReturn(allMatchEndpoint); + Mockito.when(discoveryInstance.getDataCenterInfo()).thenReturn(info); + Mockito.when(discoveryInstance.getInstanceId()).thenReturn("allmatchInstance"); + + DiscoveryInstance regionMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance regionMatchInstance = new StatefulDiscoveryInstance(regionMatchDiscoveryInstance); + DataCenterInfo regionMatchInfo = new DataCenterInfo(); + regionMatchInfo.setName("test"); + regionMatchInfo.setRegion("test-Region"); + regionMatchInfo.setAvailableZone("test-zone2"); + List regionMatchEndpoint = new ArrayList<>(); + regionMatchEndpoint.add("rest://localhost:9091"); + Mockito.when(regionMatchDiscoveryInstance.getEndpoints()).thenReturn(regionMatchEndpoint); + Mockito.when(regionMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(regionMatchInfo); + Mockito.when(regionMatchDiscoveryInstance.getInstanceId()).thenReturn("regionMatchInstance"); + + DiscoveryInstance noneMatchDiscoveryInstance = Mockito.mock(DiscoveryInstance.class); + StatefulDiscoveryInstance noneMatchInstance = new StatefulDiscoveryInstance(noneMatchDiscoveryInstance); + DataCenterInfo noneMatchInfo = new DataCenterInfo(); + noneMatchInfo.setName("test"); + noneMatchInfo.setRegion("test-Region2"); + noneMatchInfo.setAvailableZone("test-zone2"); + List noMatchEndpoint = new ArrayList<>(); + noMatchEndpoint.add("rest://localhost:9092"); + Mockito.when(noneMatchDiscoveryInstance.getEndpoints()).thenReturn(noMatchEndpoint); + Mockito.when(noneMatchDiscoveryInstance.getDataCenterInfo()).thenReturn(noneMatchInfo); + Mockito.when(noneMatchDiscoveryInstance.getInstanceId()).thenReturn("noneMatchInstance"); + + // run test + List data = Arrays.asList(allmatchInstance, regionMatchInstance, noneMatchInstance); + DiscoveryTreeNode parent = new DiscoveryTreeNode().name("parent").data(data); + DiscoveryContext context = new DiscoveryContext(); + DiscoveryTreeNode result = filter.discovery(context, parent); + + // check result + Integer level = context.getContextParameter(filter.contextParameter()); + Integer groups = parent.attribute(filter.groupsSizeParameter()); + List resultData = result.data(); + Assertions.assertEquals(null, level); + Assertions.assertEquals(1, groups); + Assertions.assertEquals(3, resultData.size()); + Assertions.assertEquals("noneMatchInstance", resultData.get(0).getInstanceId()); + Assertions.assertEquals("regionMatchInstance", resultData.get(1).getInstanceId()); + Assertions.assertEquals("allmatchInstance", resultData.get(2).getInstanceId()); + } +} diff --git a/handlers/handler-loadbalance/src/test/resources/log4j.properties b/handlers/handler-loadbalance/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/handlers/handler-loadbalance/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/handlers/handler-loadbalance/src/test/resources/microservice.yaml b/handlers/handler-loadbalance/src/test/resources/microservice.yaml index 4db1321ba99..5ff7ed9ae41 100644 --- a/handlers/handler-loadbalance/src/test/resources/microservice.yaml +++ b/handlers/handler-loadbalance/src/test/resources/microservice.yaml @@ -20,4 +20,4 @@ servicecomb: consumer: default: empty producer: - default: empty \ No newline at end of file + default: empty diff --git a/handlers/handler-publickey-auth/pom.xml b/handlers/handler-publickey-auth/pom.xml index 77179d986a7..9f13b26f232 100644 --- a/handlers/handler-publickey-auth/pom.xml +++ b/handlers/handler-publickey-auth/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb handlers - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT handler-publickey-auth @@ -42,13 +42,13 @@ test - org.slf4j - slf4j-log4j12 + org.apache.logging.log4j + log4j-slf4j-impl test - log4j - log4j + org.apache.logging.log4j + log4j-core test @@ -56,7 +56,11 @@ foundation-test-scaffolding test - + + org.mockito + mockito-inline + test + diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/AuthHandlerBoot.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/AuthHandlerBoot.java deleted file mode 100644 index 5eb06ced398..00000000000 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/AuthHandlerBoot.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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; - -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.foundation.common.utils.RSAKeyPairEntry; -import org.apache.servicecomb.foundation.common.utils.RSAUtils; -import org.apache.servicecomb.foundation.token.RSAKeypair4Auth; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.springframework.stereotype.Component; - -/** - * - * initialize public and private key pair when system boot before registry instance to service center - * - * - */ -@Component -public class AuthHandlerBoot implements BootListener { - - - @Override - public void onBootEvent(BootEvent event) { - if (!EventType.BEFORE_REGISTRY.equals(event.getEventType())) { - return; - } - RSAKeyPairEntry rsaKeyPairEntry = RSAUtils.generateRSAKeyPair(); - RSAKeypair4Auth.INSTANCE.setPrivateKey(rsaKeyPairEntry.getPrivateKey()); - RSAKeypair4Auth.INSTANCE.setPublicKey(rsaKeyPairEntry.getPublicKey()); - RSAKeypair4Auth.INSTANCE.setPublicKeyEncoded(rsaKeyPairEntry.getPublicKeyEncoded()); - RegistrationManager.INSTANCE.getMicroserviceInstance().getProperties().put(DefinitionConst.INSTANCE_PUBKEY_PRO, - rsaKeyPairEntry.getPublicKeyEncoded()); - } -} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/AuthenticationBootListener.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/AuthenticationBootListener.java new file mode 100644 index 00000000000..71fd4e500fb --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/AuthenticationBootListener.java @@ -0,0 +1,50 @@ +/* + * 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.authentication; + +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.foundation.common.utils.KeyPairEntry; +import org.apache.servicecomb.foundation.common.utils.KeyPairUtils; +import org.apache.servicecomb.foundation.token.Keypair4Auth; +import org.apache.servicecomb.registry.RegistrationManager; +import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * initialize public and private key pair when system boot before registry instance to service center + */ +public class AuthenticationBootListener implements BootListener { + private RegistrationManager registrationManager; + + @Autowired + public void setRegistrationManager(RegistrationManager registrationManager) { + this.registrationManager = registrationManager; + } + + @Override + public void onBootEvent(BootEvent event) { + if (!EventType.BEFORE_REGISTRY.equals(event.getEventType())) { + return; + } + KeyPairEntry rsaKeyPairEntry = KeyPairUtils.generateALGKeyPair(); + Keypair4Auth.INSTANCE.setPrivateKey(rsaKeyPairEntry.getPrivateKey()); + Keypair4Auth.INSTANCE.setPublicKey(rsaKeyPairEntry.getPublicKey()); + Keypair4Auth.INSTANCE.setPublicKeyEncoded(rsaKeyPairEntry.getPublicKeyEncoded()); + this.registrationManager.addProperty(DefinitionConst.INSTANCE_PUBKEY_PRO, + rsaKeyPairEntry.getPublicKeyEncoded()); + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java new file mode 100644 index 00000000000..a7f8ea308ee --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/AuthenticationConfiguration.java @@ -0,0 +1,66 @@ +/* + * 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.authentication; + +import org.apache.servicecomb.authentication.consumer.ConsumerAuthFilter; +import org.apache.servicecomb.authentication.consumer.ConsumerTokenManager; +import org.apache.servicecomb.authentication.provider.AccessController; +import org.apache.servicecomb.authentication.provider.ProviderAuthFilter; +import org.apache.servicecomb.authentication.provider.ProviderTokenManager; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +@ConditionalOnProperty(value = AuthenticationConfiguration.ACCESS_CONTROL_ENABLED, + havingValue = "true") +public class AuthenticationConfiguration { + public static final String ACCESS_CONTROL_PREFIX = "servicecomb.publicKey.accessControl"; + + public static final String ACCESS_CONTROL_ENABLED = ACCESS_CONTROL_PREFIX + ".enabled"; + + @Bean + public ConsumerAuthFilter scbConsumerAuthFilter() { + return new ConsumerAuthFilter(); + } + + @Bean + public ProviderAuthFilter scbProviderAuthFilter() { + return new ProviderAuthFilter(); + } + + @Bean + public AuthenticationBootListener scbAuthenticationBootListener() { + return new AuthenticationBootListener(); + } + + @Bean + public ConsumerTokenManager scbConsumerTokenManager() { + return new ConsumerTokenManager(); + } + + @Bean + public ProviderTokenManager scbProviderTokenManager() { + return new ProviderTokenManager(); + } + + @Bean + public AccessController scbAccessController(Environment environment) { + return new AccessController(environment); + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/RSAAuthenticationToken.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/RSAAuthenticationToken.java index 0a7385e1183..aa88091b70e 100644 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/RSAAuthenticationToken.java +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/RSAAuthenticationToken.java @@ -24,7 +24,7 @@ */ public class RSAAuthenticationToken { - public final static long TOKEN_ACTIVE_TIME = 24 * 60 * 60 * 1000; + public static final long TOKEN_ACTIVE_TIME = 24 * 60 * 60 * 1000; private final String instanceId; @@ -85,7 +85,7 @@ public static RSAAuthenticationToken fromStr(String token) { return null; } return new RSAAuthenticationToken(tokenArr[0], tokenArr[1], - Long.valueOf(tokenArr[2]), tokenArr[3], tokenArr[4]); + Long.parseLong(tokenArr[2]), tokenArr[3], tokenArr[4]); } public String getServiceId() { @@ -101,10 +101,7 @@ public boolean equals(Object obj) { if (!token.plainToken().equals(this.plainToken())) { return false; } - if (!token.getSign().equals(this.sign)) { - return false; - } - return true; + return token.getSign().equals(this.sign); } public int hashCode() { diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerAuthFilter.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerAuthFilter.java new file mode 100644 index 00000000000..e26f24d936a --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerAuthFilter.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.authentication.consumer; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.ConsumerFilter; +import org.apache.servicecomb.core.filter.EdgeFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.beans.factory.annotation.Autowired; + +import jakarta.ws.rs.core.Response.Status; + +public class ConsumerAuthFilter extends AbstractFilter implements ConsumerFilter, EdgeFilter { + private ConsumerTokenManager authenticationTokenManager; + + @Autowired + public void setConsumerTokenManager(ConsumerTokenManager consumerTokenManager) { + this.authenticationTokenManager = consumerTokenManager; + } + + @Override + public int getOrder() { + return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1010; + } + + @Override + public String getName() { + return "consumer-public-key"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + Optional token = Optional.ofNullable(authenticationTokenManager.getToken()); + if (!token.isPresent()) { + return CompletableFuture.failedFuture( + new InvocationException(Status.SERVICE_UNAVAILABLE, "auth token is not properly configured yet.")); + } + invocation.addContext(CoreConst.AUTH_TOKEN, token.get()); + return nextNode.onFilter(invocation); + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerAuthHandler.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerAuthHandler.java deleted file mode 100644 index ef5e60ab45e..00000000000 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerAuthHandler.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.authentication.consumer; - -import java.util.Optional; - -import javax.ws.rs.core.Response.Status; - -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -/** - * - * add token to context - * Provider will get token for authentication - * - */ -public class ConsumerAuthHandler implements Handler { - - private RSAConsumerTokenManager authenticationTokenManager = new RSAConsumerTokenManager(); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - - Optional token = Optional.ofNullable(authenticationTokenManager.getToken()); - if (!token.isPresent()) { - asyncResp.consumerFail( - new InvocationException(Status.SERVICE_UNAVAILABLE, "auth token is not properly configured yet.")); - return; - } - invocation.addContext(Const.AUTH_TOKEN, token.get()); - invocation.next(asyncResp); - } - - public void setAuthenticationTokenManager(RSAConsumerTokenManager authenticationTokenManager) { - this.authenticationTokenManager = authenticationTokenManager; - } -} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerTokenManager.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerTokenManager.java new file mode 100644 index 00000000000..8da889abc02 --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/ConsumerTokenManager.java @@ -0,0 +1,94 @@ +/* + * 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.authentication.consumer; + +import java.security.PrivateKey; + +import org.apache.servicecomb.authentication.RSAAuthenticationToken; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.foundation.common.utils.KeyPairUtils; +import org.apache.servicecomb.foundation.token.Keypair4Auth; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +public class ConsumerTokenManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConsumerTokenManager.class); + + private final Object lock = new Object(); + + private RSAAuthenticationToken token; + + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + public String getToken() { + + if (isExpired(token)) { + synchronized (lock) { + if (isExpired(token)) { + return createToken(); + } + } + } + return token.format(); + } + + public String createToken() { + PrivateKey privateKey = Keypair4Auth.INSTANCE.getPrivateKey(); + String instanceId = BootStrapProperties.readServiceName(environment); + String serviceId = BootStrapProperties.readApplication(environment); + + if (instanceId == null || serviceId == null) { + LOGGER.error("service not ready when create token."); + return null; + } + + @SuppressWarnings("deprecation") + String randomCode = org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric(128); + long generateTime = System.currentTimeMillis(); + try { + String plain = String.format("%s@%s@%s@%s", instanceId, serviceId, generateTime, randomCode); + String sign = KeyPairUtils.sign(plain, privateKey); + token = RSAAuthenticationToken.fromStr(String.format("%s@%s", plain, sign)); + } catch (Exception e) { + LOGGER.error("create token error", e); + return null; + } + return token.format(); + } + + /** + * the TTL of Token is 24 hours + * client token will expired 15 minutes early + */ + public boolean isExpired(RSAAuthenticationToken token) { + if (null == token) { + return true; + } + long generateTime = token.getGenerateTime(); + long expiredDate = generateTime + RSAAuthenticationToken.TOKEN_ACTIVE_TIME - 15 * 60 * 1000; + long now = System.currentTimeMillis(); + return now > expiredDate; + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java deleted file mode 100644 index b824c0b1505..00000000000 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/consumer/RSAConsumerTokenManager.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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.authentication.consumer; - -import java.security.PrivateKey; - -import org.apache.servicecomb.authentication.RSAAuthenticationToken; -import org.apache.servicecomb.foundation.common.utils.RSAUtils; -import org.apache.servicecomb.foundation.token.RSAKeypair4Auth; -import org.apache.servicecomb.registry.RegistrationManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RSAConsumerTokenManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(RSAConsumerTokenManager.class); - - private Object lock = new Object(); - - private RSAAuthenticationToken token; - - public String getToken() { - - if (isExpired(token)) { - synchronized (lock) { - if (isExpired(token)) { - return createToken(); - } - } - } - return token.format(); - } - - public String createToken() { - PrivateKey privateKey = RSAKeypair4Auth.INSTANCE.getPrivateKey(); - String instanceId = RegistrationManager.INSTANCE.getMicroserviceInstance().getInstanceId(); - String serviceId = RegistrationManager.INSTANCE.getMicroservice().getServiceId(); - - if (instanceId == null || serviceId == null) { - LOGGER.error("service not ready when create token."); - return null; - } - - @SuppressWarnings("deprecation") - String randomCode = org.apache.commons.lang3.RandomStringUtils.randomAlphanumeric(128); - long generateTime = System.currentTimeMillis(); - try { - String plain = String.format("%s@%s@%s@%s", instanceId, serviceId, generateTime, randomCode); - String sign = RSAUtils.sign(plain, privateKey); - token = RSAAuthenticationToken.fromStr(String.format("%s@%s", plain, sign)); - } catch (Exception e) { - LOGGER.error("create token error", e); - return null; - } - return token.format(); - } - - /** - * the TTL of Token is 24 hours - * client token will expired 15 minutes early - */ - public boolean isExpired(RSAAuthenticationToken token) { - if (null == token) { - return true; - } - long generateTime = token.getGenerateTime(); - long expiredDate = generateTime + RSAAuthenticationToken.TOKEN_ACTIVE_TIME - 15 * 60 * 1000; - long now = System.currentTimeMillis(); - return now > expiredDate; - } -} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java index 561d8230429..b923b2939d7 100644 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/AccessController.java @@ -16,25 +16,28 @@ */ package org.apache.servicecomb.authentication.provider; -import java.beans.PropertyDescriptor; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; +import java.util.Set; import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.registry.api.registry.Microservice; +import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.registry.api.DiscoveryInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; -import com.netflix.config.ConcurrentCompositeConfiguration; -import com.netflix.config.DynamicPropertyFactory; +import com.google.common.eventbus.Subscribe; /** * Add black / white list control to service access */ public class AccessController { - class ConfigurationItem { + static class ConfigurationItem { static final String CATEGORY_PROPERTY = "property"; String category; @@ -56,66 +59,71 @@ class ConfigurationItem { private static final String KEY_RULE_POSTFIX = ".rule"; + private final Environment environment; + private Map whiteList = new HashMap<>(); private Map blackList = new HashMap<>(); - public AccessController() { + public AccessController(Environment environment) { + this.environment = environment; loadConfigurations(KEY_BLACK_LIST_PREFIX); loadConfigurations(KEY_WHITE_LIST_PREFIX); + EventManager.register(this); } - public boolean isAllowed(Microservice microservice) { + public boolean isAllowed(DiscoveryInstance microservice) { return whiteAllowed(microservice) && !blackDenied(microservice); } - private boolean whiteAllowed(Microservice microservice) { - if(whiteList.isEmpty()) { + private boolean whiteAllowed(DiscoveryInstance microservice) { + if (whiteList.isEmpty()) { return true; } return matchFound(microservice, whiteList); } - private boolean blackDenied(Microservice microservice) { - if(blackList.isEmpty()) { + private boolean blackDenied(DiscoveryInstance microservice) { + if (blackList.isEmpty()) { return false; } return matchFound(microservice, blackList); } - private boolean matchFound(Microservice microservice, Map ruleList) { + private boolean matchFound(DiscoveryInstance microservice, Map ruleList) { boolean matched = false; for (ConfigurationItem item : ruleList.values()) { if (ConfigurationItem.CATEGORY_PROPERTY.equals(item.category)) { // we support to configure properties, e.g. serviceName, appId, environment, alias, version and so on, also support key in properties. - if (matchMicroserviceField(microservice, item) || matchMicroserviceProperties(microservice, item)) + if (matchMicroserviceField(microservice, item) || matchMicroserviceProperties(microservice, item)) { return true; + } } } return matched; } - private boolean matchMicroserviceProperties(Microservice microservice, ConfigurationItem item) { + private boolean matchMicroserviceProperties(DiscoveryInstance microservice, ConfigurationItem item) { Map properties = microservice.getProperties(); for (Entry entry : properties.entrySet()) { - if (!entry.getKey().equals(item.propertyName)) + if (!entry.getKey().equals(item.propertyName)) { continue; + } return isPatternMatch(entry.getValue(), item.rule); } return false; } - private boolean matchMicroserviceField(Microservice microservice, ConfigurationItem item) { - Object fieldValue = null; - try { - fieldValue = new PropertyDescriptor(item.propertyName, Microservice.class).getReadMethod().invoke(microservice); - } catch (Exception e) { - LOG.warn("can't find propertyname: {} in microservice field, will search in microservice properties.", item.propertyName); - return false; + private boolean matchMicroserviceField(DiscoveryInstance microservice, ConfigurationItem item) { + String fieldValue; + if ("version".equals(item.propertyName)) { + fieldValue = microservice.getVersion(); + } else if ("serviceName".equals(item.propertyName)) { + fieldValue = microservice.getServiceName(); + } else { + fieldValue = microservice.getProperties().get(item.propertyName); } - if (fieldValue.getClass().getName().equals(String.class.getName())) - return isPatternMatch((String) fieldValue, item.rule); - return false; + return isPatternMatch(fieldValue, item.rule); } private boolean isPatternMatch(String value, String pattern) { @@ -128,40 +136,40 @@ private boolean isPatternMatch(String value, String pattern) { return value.equals(pattern); } - private void loadConfigurations(String prefix) { - ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory - .getBackingConfigurationSource(); - loadConfigurations(config, prefix); - config.addConfigurationListener(event -> { - if (event.getPropertyName().startsWith(prefix)) { - LOG.info("Access rule have been changed. Reload configurations. Event=" + event.getType()); - loadConfigurations(config, prefix); + @Subscribe + public void onConfigurationChangedEvent(ConfigurationChangedEvent event) { + for (String changed : event.getChanged()) { + if (changed.startsWith(KEY_WHITE_LIST_PREFIX)) { + loadConfigurations(KEY_WHITE_LIST_PREFIX); + break; + } + } + for (String changed : event.getChanged()) { + if (changed.startsWith(KEY_BLACK_LIST_PREFIX)) { + loadConfigurations(KEY_BLACK_LIST_PREFIX); + break; } - }); + } } - private void loadConfigurations(ConcurrentCompositeConfiguration config, String prefix) { + private void loadConfigurations(String prefix) { Map configurations = new HashMap<>(); - Iterator configsItems = config.getKeys(prefix); - while (configsItems.hasNext()) { - String pathKey = configsItems.next(); + Set configsItems = ConfigUtil.propertiesWithPrefix((ConfigurableEnvironment) environment, prefix); + for (String pathKey : configsItems) { if (pathKey.endsWith(KEY_RULE_POSTFIX)) { ConfigurationItem configurationItem = new ConfigurationItem(); - String rule = DynamicPropertyFactory.getInstance() - .getStringProperty(pathKey, null).get(); + String rule = environment.getProperty(pathKey); if (StringUtils.isEmpty(rule)) { continue; } configurationItem.rule = rule; String pathKeyItem = pathKey .substring(prefix.length() + 1, pathKey.length() - KEY_RULE_POSTFIX.length()); - configurationItem.propertyName = DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(KEY_PROPERTY_NAME, prefix, pathKeyItem), null).get(); + configurationItem.propertyName = environment.getProperty(String.format(KEY_PROPERTY_NAME, prefix, pathKeyItem)); if (StringUtils.isEmpty(configurationItem.propertyName)) { continue; } - configurationItem.category = DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(KEY_CATEGORY, prefix, pathKeyItem), null).get(); + configurationItem.category = environment.getProperty(String.format(KEY_CATEGORY, prefix, pathKeyItem)); if (StringUtils.isEmpty(configurationItem.category)) { continue; } @@ -179,12 +187,9 @@ private void loadConfigurations(ConcurrentCompositeConfiguration config, String } private void logConfigurations(Map configurations, boolean isWhite) { - configurations.entrySet().forEach(stringConfigurationItemEntry -> { - ConfigurationItem item = stringConfigurationItemEntry.getValue(); - LOG.info((isWhite ? "White list " : "Black list ") + "config item: key=" + stringConfigurationItemEntry.getKey() - + ";category=" + item.category - + ";propertyName=" + item.propertyName - + ";rule=" + item.rule); - }); + configurations.forEach((key, item) -> LOG.info((isWhite ? "White list " : "Black list ") + "config item: key=" + key + + ";category=" + item.category + + ";propertyName=" + item.propertyName + + ";rule=" + item.rule)); } } diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/PathCheckUtils.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/PathCheckUtils.java new file mode 100644 index 00000000000..c587195d238 --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/PathCheckUtils.java @@ -0,0 +1,92 @@ +/* + * 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.authentication.provider; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.core.env.Environment; + +public class PathCheckUtils { + private static final String KEY_INCLUDE_PATH = "servicecomb.publicKey.accessControl.includePathPatterns"; + + private static final String KEY_EXCLUDE_PATH = "servicecomb.publicKey.accessControl.excludePathPatterns"; + + /** + * first determine configured non-authentication path is matched requestPath, if match not needed auth. + * second determine whether of configured authentication path, if not configured, default all path need auth; + * if configured, then check whether of matched requestPath, if match needed auth, otherwise not needed auth. + * + * @param requestPath path + * @param env environment + * @return notRequiredAuth + */ + public static boolean isNotRequiredAuth(String requestPath, Environment env) { + if (excludePathMatchPath(requestPath, env)) { + return true; + } + return includePathMatchPath(requestPath, env); + } + + private static boolean excludePathMatchPath(String requestPath, Environment env) { + String excludePathPattern = env.getProperty(KEY_EXCLUDE_PATH, ""); + if (StringUtils.isEmpty(excludePathPattern)) { + return false; + } + return isPathMather(requestPath, excludePathPattern); + } + + private static boolean includePathMatchPath(String requestPath, Environment env) { + String includePathPattern = env.getProperty(KEY_INCLUDE_PATH, ""); + if (StringUtils.isEmpty(includePathPattern)) { + return false; + } + return !isPathMather(requestPath, includePathPattern); + } + + private static boolean isPathMather(String requestPath, String pathPattern) { + for (String pattern : pathPattern.split(",")) { + if (!pattern.isEmpty() && isPatternMatch(requestPath, pattern)) { + return true; + } + } + return false; + } + + public static boolean isPatternMatch(String value, String pattern) { + if (pattern.startsWith("*") || pattern.startsWith("/*")) { + int index = 0; + for (int i = 0; i < pattern.length(); i++) { + if (pattern.charAt(i) != '*' && pattern.charAt(i) != '/') { + break; + } + index++; + } + return value.endsWith(pattern.substring(index)); + } + if (pattern.endsWith("*")) { + int index = pattern.length() - 1; + for (int i = pattern.length() - 1; i >= 0; i--) { + if (pattern.charAt(i) != '*' && pattern.charAt(i) != '/') { + break; + } + index--; + } + return value.startsWith(pattern.substring(0, index + 1)); + } + return value.equals(pattern); + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderAuthFilter.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderAuthFilter.java new file mode 100644 index 00000000000..f525ae88cf8 --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderAuthFilter.java @@ -0,0 +1,70 @@ +/* + * 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.authentication.provider; + +import java.util.concurrent.CompletableFuture; + +import org.apache.servicecomb.core.CoreConst; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.filter.AbstractFilter; +import org.apache.servicecomb.core.filter.Filter; +import org.apache.servicecomb.core.filter.FilterNode; +import org.apache.servicecomb.core.filter.ProviderFilter; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +import jakarta.ws.rs.core.Response.Status; + +public class ProviderAuthFilter extends AbstractFilter implements ProviderFilter { + private ProviderTokenManager authenticationTokenManager; + + private Environment env; + + @Autowired + public void setProviderTokenManager(ProviderTokenManager providerTokenManager, Environment env) { + this.authenticationTokenManager = providerTokenManager; + this.env = env; + } + + @Override + public int getOrder() { + return Filter.PROVIDER_SCHEDULE_FILTER_ORDER + 1010; + } + + @Override + public String getName() { + return "provider-public-key"; + } + + @Override + public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { + String requestFullPath = SwaggerUtils.concatAbsolutePath(invocation.getSchemaMeta().getSwagger(), + invocation.getOperationMeta().getOperationPath()); + if (PathCheckUtils.isNotRequiredAuth(requestFullPath, env)) { + return nextNode.onFilter(invocation); + } + String token = invocation.getContext(CoreConst.AUTH_TOKEN); + if (null != token && authenticationTokenManager.valid(token)) { + return nextNode.onFilter(invocation); + } + return CompletableFuture.failedFuture( + new InvocationException(Status.UNAUTHORIZED, "public key authorization failed.")); + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderAuthHanlder.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderAuthHanlder.java deleted file mode 100644 index a871ece33cf..00000000000 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderAuthHanlder.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.authentication.provider; - -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.context.HttpStatus; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; - -public class ProviderAuthHanlder implements Handler { - - private RSAProviderTokenManager authenticationTokenManager = new RSAProviderTokenManager(); - - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - - String token = invocation.getContext(Const.AUTH_TOKEN); - if (null != token && authenticationTokenManager.valid(token)) { - invocation.next(asyncResp); - } else { - asyncResp.producerFail(new InvocationException(new HttpStatus(401, "UNAUTHORIZED"), "UNAUTHORIZED")); - } - } -} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderTokenManager.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderTokenManager.java new file mode 100644 index 00000000000..ebedacb7bf2 --- /dev/null +++ b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/ProviderTokenManager.java @@ -0,0 +1,122 @@ +/* + * 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.authentication.provider; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SignatureException; +import java.security.spec.InvalidKeySpecException; +import java.util.concurrent.TimeUnit; + +import org.apache.servicecomb.authentication.RSAAuthenticationToken; +import org.apache.servicecomb.foundation.common.utils.KeyPairUtils; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.apache.servicecomb.registry.discovery.MicroserviceInstanceCache; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +public class ProviderTokenManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(ProviderTokenManager.class); + + private final Cache validatedToken = CacheBuilder.newBuilder() + .expireAfterAccess(getExpiredTime(), TimeUnit.MILLISECONDS) + .build(); + + private AccessController accessController; + + private MicroserviceInstanceCache microserviceInstanceCache; + + @Autowired + public void setMicroserviceInstanceCache(MicroserviceInstanceCache microserviceInstanceCache) { + this.microserviceInstanceCache = microserviceInstanceCache; + } + + @Autowired + public void setAccessController(AccessController accessController) { + this.accessController = accessController; + } + + public boolean valid(String token) { + try { + RSAAuthenticationToken rsaToken = RSAAuthenticationToken.fromStr(token); + if (null == rsaToken) { + LOGGER.error("token format is error, perhaps you need to set auth handler at consumer"); + return false; + } + if (tokenExpired(rsaToken)) { + LOGGER.error("token is expired"); + return false; + } + + if (validatedToken.asMap().containsKey(rsaToken)) { + return accessController.isAllowed(microserviceInstanceCache.getOrCreate( + rsaToken.getServiceId(), rsaToken.getInstanceId())); + } + + if (isValidToken(rsaToken) && !tokenExpired(rsaToken)) { + validatedToken.put(rsaToken, true); + return accessController.isAllowed(microserviceInstanceCache.getOrCreate( + rsaToken.getServiceId(), rsaToken.getInstanceId())); + } + return false; + } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | SignatureException e) { + LOGGER.error("verify error", e); + return false; + } + } + + public boolean isValidToken(RSAAuthenticationToken rsaToken) + throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { + String sign = rsaToken.getSign(); + String content = rsaToken.plainToken(); + String publicKey = getPublicKeyFromInstance(rsaToken.getInstanceId(), rsaToken.getServiceId()); + return KeyPairUtils.verify(publicKey, sign, content); + } + + protected int getExpiredTime() { + return 60 * 60 * 1000; + } + + private boolean tokenExpired(RSAAuthenticationToken rsaToken) { + long generateTime = rsaToken.getGenerateTime(); + long expired = generateTime + RSAAuthenticationToken.TOKEN_ACTIVE_TIME + 15 * 60 * 1000; + long now = System.currentTimeMillis(); + return now > expired; + } + + private String getPublicKeyFromInstance(String instanceId, String serviceId) { + DiscoveryInstance instances = microserviceInstanceCache.getOrCreate(serviceId, instanceId); + if (instances != null) { + return instances.getProperties().get(DefinitionConst.INSTANCE_PUBKEY_PRO); + } else { + LOGGER.error("not instance found {}-{}, maybe attack", instanceId, serviceId); + return ""; + } + } + + @VisibleForTesting + Cache getValidatedToken() { + return validatedToken; + } +} diff --git a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java b/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java deleted file mode 100644 index f6e2ee5866a..00000000000 --- a/handlers/handler-publickey-auth/src/main/java/org/apache/servicecomb/authentication/provider/RSAProviderTokenManager.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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.authentication.provider; - -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.SignatureException; -import java.security.spec.InvalidKeySpecException; -import java.util.concurrent.TimeUnit; - -import org.apache.servicecomb.authentication.RSAAuthenticationToken; -import org.apache.servicecomb.foundation.common.utils.RSAUtils; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.MicroserviceInstanceCache; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; - -public class RSAProviderTokenManager { - - private final static Logger LOGGER = LoggerFactory.getLogger(RSAProviderTokenManager.class); - - private Cache validatedToken = CacheBuilder.newBuilder() - .expireAfterAccess(getExpiredTime(), TimeUnit.MILLISECONDS) - .build(); - - private AccessController accessController = new AccessController(); - - public boolean valid(String token) { - try { - RSAAuthenticationToken rsaToken = RSAAuthenticationToken.fromStr(token); - if (null == rsaToken) { - LOGGER.error("token format is error, perhaps you need to set auth handler at consumer"); - return false; - } - if (tokenExpired(rsaToken)) { - LOGGER.error("token is expired"); - return false; - } - - if (validatedToken.asMap().containsKey(rsaToken)) { - return accessController.isAllowed(MicroserviceInstanceCache.getOrCreate(rsaToken.getServiceId())); - } - - if (isValidToken(rsaToken) && !tokenExpired(rsaToken)) { - validatedToken.put(rsaToken, true); - return accessController.isAllowed(MicroserviceInstanceCache.getOrCreate(rsaToken.getServiceId())); - } - return false; - } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | SignatureException e) { - LOGGER.error("verify error", e); - return false; - } - } - - public boolean isValidToken(RSAAuthenticationToken rsaToken) - throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, SignatureException { - String sign = rsaToken.getSign(); - String content = rsaToken.plainToken(); - String publicKey = getPublicKeyFromInstance(rsaToken.getInstanceId(), rsaToken.getServiceId()); - return RSAUtils.verify(publicKey, sign, content); - } - - protected int getExpiredTime() { - return 60 * 60 * 1000; - } - - private boolean tokenExpired(RSAAuthenticationToken rsaToken) { - long generateTime = rsaToken.getGenerateTime(); - long expired = generateTime + RSAAuthenticationToken.TOKEN_ACTIVE_TIME + 15 * 60 * 1000; - long now = System.currentTimeMillis(); - return now > expired; - } - - private String getPublicKeyFromInstance(String instanceId, String serviceId) { - MicroserviceInstance instances = MicroserviceInstanceCache.getOrCreate(serviceId, instanceId); - if (instances != null) { - return instances.getProperties().get(DefinitionConst.INSTANCE_PUBKEY_PRO); - } else { - LOGGER.error("not instance found {}-{}, maybe attack", instanceId, serviceId); - return ""; - } - } - - @VisibleForTesting - Cache getValidatedToken() { - return validatedToken; - } -} diff --git a/handlers/handler-publickey-auth/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-publickey-auth/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..23589733acf --- /dev/null +++ b/handlers/handler-publickey-auth/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.servicecomb.authentication.AuthenticationConfiguration diff --git a/handlers/handler-publickey-auth/src/main/resources/config/cse.handler.xml b/handlers/handler-publickey-auth/src/main/resources/config/cse.handler.xml deleted file mode 100644 index 4ca3eecacf1..00000000000 --- a/handlers/handler-publickey-auth/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java index ff41134fecc..0c6c6afd346 100644 --- a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java +++ b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAccessController.java @@ -20,145 +20,260 @@ import java.util.Map; import org.apache.servicecomb.authentication.provider.AccessController; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.junit.After; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.config.ConfigurationChangedEvent; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.EnumerablePropertySource; +import org.springframework.core.env.MutablePropertySources; public class TestAccessController { - @After + ConfigurableEnvironment environment; + + EnumerablePropertySource propertySource; + + @BeforeEach public void tearDown() { - ArchaiusUtils.resetConfig(); + environment = Mockito.mock(ConfigurableEnvironment.class); + propertySource = Mockito.mock(EnumerablePropertySource.class); } @Test public void testIsValidOfWhiteByServiceName() { - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.propertyName", "serviceName"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule", "trust*"); - AccessController controller = new AccessController(); - Microservice service = new Microservice(); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.publicKey.accessControl.white.list1.propertyName", + "servicecomb.publicKey.accessControl.white.list1.category", + "servicecomb.publicKey.accessControl.white.list1.rule" + }); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.propertyName")) + .thenReturn("serviceName"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.rule")) + .thenReturn("trust*"); + + AccessController controller = new AccessController(environment); + DiscoveryInstance service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trustCustomer"); + Assertions.assertTrue(controller.isAllowed(service)); - service.setServiceName("trustCustomer"); - Assert.assertTrue(controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("nottrustCustomer"); + Assertions.assertFalse(controller.isAllowed(service)); - service.setServiceName("nottrustCustomer"); - Assert.assertTrue(!controller.isAllowed(service)); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.rule")) + .thenReturn("*trust"); + Map latest = new HashMap<>(); + latest.put("servicecomb.publicKey.accessControl.white.list1.rule", "*trust"); + controller.onConfigurationChangedEvent(ConfigurationChangedEvent.createIncremental(latest, new HashMap<>())); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("Customer_trust"); + Assertions.assertTrue(controller.isAllowed(service)); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule", "*trust"); - service.setServiceName("Customer_trust"); - Assert.assertTrue(controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("Customer_trust_not"); + Assertions.assertFalse(controller.isAllowed(service)); - service.setServiceName("Customer_trust_not"); - Assert.assertTrue(!controller.isAllowed(service)); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.rule")) + .thenReturn("trust"); + latest.put("servicecomb.publicKey.accessControl.white.list1.rule", "trust"); + controller.onConfigurationChangedEvent(ConfigurationChangedEvent.createIncremental(latest, new HashMap<>())); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule", "trust"); - service.setServiceName("trust"); - Assert.assertTrue(controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trust"); + Assertions.assertTrue(controller.isAllowed(service)); - service.setServiceName("Customer_trust"); - Assert.assertTrue(!controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("Customer_trust"); + Assertions.assertFalse(controller.isAllowed(service)); } @Test public void testIsValidOfBlackByServiceName() { - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.propertyName", "serviceName"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule", "trust*"); - AccessController controller = new AccessController(); - Microservice service = new Microservice(); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.publicKey.accessControl.black.list1.propertyName", + "servicecomb.publicKey.accessControl.black.list1.category", + "servicecomb.publicKey.accessControl.black.list1.rule" + }); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.propertyName")) + .thenReturn("serviceName"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.rule")) + .thenReturn("trust*"); - service.setServiceName("trustCustomer"); - Assert.assertTrue(!controller.isAllowed(service)); + AccessController controller = new AccessController(environment); - service.setServiceName("nottrustCustomer"); - Assert.assertTrue(controller.isAllowed(service)); + DiscoveryInstance service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trustCustomer"); + Assertions.assertFalse(controller.isAllowed(service)); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule", "*trust"); - service.setServiceName("Customer_trust"); - Assert.assertTrue(!controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("nottrustCustomer"); + Assertions.assertTrue(controller.isAllowed(service)); - service.setServiceName("Customer_trust_not"); - Assert.assertTrue(controller.isAllowed(service)); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.rule")) + .thenReturn("*trust"); + Map latest = new HashMap<>(); + latest.put("servicecomb.publicKey.accessControl.black.list1.rule", "*trust"); + controller.onConfigurationChangedEvent(ConfigurationChangedEvent.createIncremental(latest, new HashMap<>())); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("Customer_trust"); + Assertions.assertFalse(controller.isAllowed(service)); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule", "trust"); - service.setServiceName("trust"); - Assert.assertTrue(!controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("Customer_trust_not"); + Assertions.assertTrue(controller.isAllowed(service)); - service.setServiceName("Customer_trust"); - Assert.assertTrue(controller.isAllowed(service)); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.rule")) + .thenReturn("trust"); + latest = new HashMap<>(); + latest.put("servicecomb.publicKey.accessControl.black.list1.rule", "trust"); + controller.onConfigurationChangedEvent(ConfigurationChangedEvent.createIncremental(latest, new HashMap<>())); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trust"); + Assertions.assertFalse(controller.isAllowed(service)); + + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("Customer_trust"); + Assertions.assertTrue(controller.isAllowed(service)); } @Test public void testIsValidOfBlackAndWhiteByServiceName() { - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.propertyName", "serviceName"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule", "trust*"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.propertyName", "serviceName"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule", "*hacker"); - - AccessController controller = new AccessController(); - Microservice service = new Microservice(); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.publicKey.accessControl.black.list1.propertyName", + "servicecomb.publicKey.accessControl.black.list1.category", + "servicecomb.publicKey.accessControl.black.list1.rule", + "servicecomb.publicKey.accessControl.white.list1.propertyName", + "servicecomb.publicKey.accessControl.white.list1.category", + "servicecomb.publicKey.accessControl.white.list1.rule" + }); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.propertyName")) + .thenReturn("serviceName"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.rule")) + .thenReturn("trust*"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.propertyName")) + .thenReturn("serviceName"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.rule")) + .thenReturn("*hacker"); - service.setServiceName("trustCustomer"); - Assert.assertTrue(controller.isAllowed(service)); + AccessController controller = new AccessController(environment); + DiscoveryInstance service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trustCustomer"); + Assertions.assertTrue(controller.isAllowed(service)); - service.setServiceName("trustCustomerhacker"); - Assert.assertTrue(!controller.isAllowed(service)); + service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trustCustomerhacker"); + Assertions.assertFalse(controller.isAllowed(service)); } @Test public void testIsValidOfBlackByProperties() { - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.propertyName", "tag"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule", "test"); - AccessController controller = new AccessController(); - Microservice service = new Microservice(); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.publicKey.accessControl.black.list1.propertyName", + "servicecomb.publicKey.accessControl.black.list1.category", + "servicecomb.publicKey.accessControl.black.list1.rule", + }); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.propertyName")) + .thenReturn("tag"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.rule")) + .thenReturn("test"); + + AccessController controller = new AccessController(environment); + DiscoveryInstance service = Mockito.mock(DiscoveryInstance.class); Map map = new HashMap<>(); map.put("tag", "test"); + Mockito.when(service.getProperties()).thenReturn(map); - service.setProperties(map); - Assert.assertTrue(!controller.isAllowed(service)); + Assertions.assertFalse(controller.isAllowed(service)); map.put("tag", "testa"); - service.setProperties(map); - Assert.assertTrue(controller.isAllowed(service)); + Mockito.when(service.getProperties()).thenReturn(map); + Assertions.assertTrue(controller.isAllowed(service)); } @Test public void testIsValidOfWhiteByProperties() { - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.propertyName", "tag"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule", "test"); - AccessController controller = new AccessController(); - Microservice service = new Microservice(); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.publicKey.accessControl.white.list1.propertyName", + "servicecomb.publicKey.accessControl.white.list1.category", + "servicecomb.publicKey.accessControl.white.list1.rule", + }); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.propertyName")) + .thenReturn("tag"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.rule")) + .thenReturn("test"); + + AccessController controller = new AccessController(environment); + DiscoveryInstance service = Mockito.mock(DiscoveryInstance.class); Map map = new HashMap<>(); map.put("tag", "test"); - - service.setProperties(map); - Assert.assertTrue(controller.isAllowed(service)); + Mockito.when(service.getProperties()).thenReturn(map); + Assertions.assertTrue(controller.isAllowed(service)); map.put("tag", "testa"); - service.setProperties(map); - Assert.assertTrue(!controller.isAllowed(service)); + Mockito.when(service.getProperties()).thenReturn(map); + Assertions.assertFalse(controller.isAllowed(service)); } @Test public void testIsValidOfBlackAndWhiteByServiceNameAndVersion() { - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.propertyName", "serviceName"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.white.list1.rule", "trust*"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.propertyName", "version"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.category", "property"); - ArchaiusUtils.setProperty("servicecomb.publicKey.accessControl.black.list1.rule", "0.0.1"); - - AccessController controller = new AccessController(); - Microservice service = new Microservice(); - service.setServiceName("trustCustomer"); - service.setVersion("0.0.1"); - - Assert.assertTrue(!controller.isAllowed(service)); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + mutablePropertySources.addLast(propertySource); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + Mockito.when(propertySource.getPropertyNames()).thenReturn(new String[] { + "servicecomb.publicKey.accessControl.black.list1.propertyName", + "servicecomb.publicKey.accessControl.black.list1.category", + "servicecomb.publicKey.accessControl.black.list1.rule", + "servicecomb.publicKey.accessControl.white.list1.propertyName", + "servicecomb.publicKey.accessControl.white.list1.category", + "servicecomb.publicKey.accessControl.white.list1.rule" + }); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.propertyName")) + .thenReturn("serviceName"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.white.list1.rule")) + .thenReturn("trust*"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.propertyName")) + .thenReturn("version"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.category")) + .thenReturn("property"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.black.list1.rule")) + .thenReturn("0.0.1"); + + AccessController controller = new AccessController(environment); + DiscoveryInstance service = Mockito.mock(DiscoveryInstance.class); + Mockito.when(service.getServiceName()).thenReturn("trustCustomer"); + Mockito.when(service.getVersion()).thenReturn("0.0.1"); + + Assertions.assertFalse(controller.isAllowed(service)); } } diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAuthHandlerBoot.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAuthHandlerBoot.java deleted file mode 100644 index 829269cdeba..00000000000 --- a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAuthHandlerBoot.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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.authentication; - -import org.apache.servicecomb.AuthHandlerBoot; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.core.BootListener.BootEvent; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.bootstrap.SCBBootstrap; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.token.RSAKeypair4Auth; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class TestAuthHandlerBoot { - private SCBEngine engine; - - @Before - public void setUp() { - ConfigUtil.installDynamicConfig(); - engine = SCBBootstrap.createSCBEngineForTest().run(); - } - - @After - public void teardown() { - engine.destroy(); - ArchaiusUtils.resetConfig(); - } - - @Test - public void testGenerateRSAKey() { - MicroserviceInstance microserviceInstance = new MicroserviceInstance(); - Microservice microservice = new Microservice(); - microservice.setInstance(microserviceInstance); - - AuthHandlerBoot authHandlerBoot = new AuthHandlerBoot(); - BootEvent bootEvent = new BootEvent(); - bootEvent.setEventType(BootListener.EventType.BEFORE_REGISTRY); - authHandlerBoot.onBootEvent(bootEvent); - Assert.assertNotNull(RSAKeypair4Auth.INSTANCE.getPrivateKey()); - Assert.assertNotNull(RSAKeypair4Auth.INSTANCE.getPublicKey()); - } - - @Test - public void testMicroserviceInstancePublicKey() { - AuthHandlerBoot authHandlerBoot = new AuthHandlerBoot(); - BootEvent bootEvent = new BootEvent(); - bootEvent.setEventType(BootListener.EventType.BEFORE_REGISTRY); - authHandlerBoot.onBootEvent(bootEvent); - String publicKey = RegistrationManager.INSTANCE.getMicroserviceInstance(). - getProperties().get(DefinitionConst.INSTANCE_PUBKEY_PRO); - Assert.assertNotNull(publicKey); - } -} diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAuthenticationBootListener.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAuthenticationBootListener.java new file mode 100644 index 00000000000..28cb8d48d2d --- /dev/null +++ b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestAuthenticationBootListener.java @@ -0,0 +1,99 @@ +/* + * 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.authentication; + +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.times; + +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.core.BootListener; +import org.apache.servicecomb.core.BootListener.BootEvent; +import org.apache.servicecomb.core.SCBEngine; +import org.apache.servicecomb.core.bootstrap.SCBBootstrap; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.token.Keypair4Auth; +import org.apache.servicecomb.registry.RegistrationManager; +import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +public class TestAuthenticationBootListener { + private SCBEngine engine; + + private Environment environment; + + @BeforeEach + public void setUp() { + environment = Mockito.mock(Environment.class); + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keyGeneratorAlgorithm", "RSA")) + .thenReturn("RSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.signAlgorithm", "SHA256withRSA")) + .thenReturn("SHA256withRSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keySize", int.class, 2048)) + .thenReturn(2048); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)) + .thenReturn(BootStrapProperties.DEFAULT_APPLICATION); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_NAME); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_ENVIRONMENT)) + .thenReturn(BootStrapProperties.DEFAULT_MICROSERVICE_ENVIRONMENT); + + engine = SCBBootstrap.createSCBEngineForTest(environment); + engine.run(); + } + + @AfterEach + public void teardown() { + engine.destroy(); + } + + @Test + public void testGenerateRSAKey() { + RegistrationManager registrationManager = Mockito.mock(RegistrationManager.class); + AuthenticationBootListener authenticationBootListener = new AuthenticationBootListener(); + authenticationBootListener.setRegistrationManager(registrationManager); + BootEvent bootEvent = new BootEvent(); + bootEvent.setEventType(BootListener.EventType.BEFORE_REGISTRY); + authenticationBootListener.onBootEvent(bootEvent); + Assertions.assertNotNull(Keypair4Auth.INSTANCE.getPrivateKey()); + Assertions.assertNotNull(Keypair4Auth.INSTANCE.getPublicKey()); + } + + @Test + public void testMicroserviceInstancePublicKey() { + RegistrationManager registrationManager = Mockito.mock(RegistrationManager.class); + AuthenticationBootListener authenticationBootListener = new AuthenticationBootListener(); + authenticationBootListener.setRegistrationManager(registrationManager); + BootEvent bootEvent = new BootEvent(); + bootEvent.setEventType(BootListener.EventType.BEFORE_REGISTRY); + + authenticationBootListener.onBootEvent(bootEvent); + + Mockito.verify(registrationManager, times(1)) + .addProperty(eq(DefinitionConst.INSTANCE_PUBKEY_PRO), any(String.class)); + } +} diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestConsumerAuthHandler.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestConsumerAuthHandler.java deleted file mode 100644 index 9855e8e9c7d..00000000000 --- a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestConsumerAuthHandler.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.authentication; - -import org.apache.servicecomb.authentication.consumer.ConsumerAuthHandler; -import org.apache.servicecomb.authentication.consumer.RSAConsumerTokenManager; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -public class TestConsumerAuthHandler { - - Invocation invocation = null; - - AsyncResponse asyncResp = null; - - RSAConsumerTokenManager tokenManager = null; - - @Test - public void testHandler() throws Exception { - tokenManager = Mockito.mock(RSAConsumerTokenManager.class); - Mockito.when(tokenManager.getToken()).thenReturn("testtoken"); - ConsumerAuthHandler consumerAuthHandler = new ConsumerAuthHandler(); - consumerAuthHandler.setAuthenticationTokenManager(tokenManager); - consumerAuthHandler.handle(invocation, asyncResp); - Assert.assertTrue(true); - } - - - @Test - public void testHandlerException() throws Exception { - tokenManager = Mockito.mock(RSAConsumerTokenManager.class); - Mockito.when(tokenManager.getToken()).thenReturn(null); - ConsumerAuthHandler consumerAuthHandler = new ConsumerAuthHandler(); - consumerAuthHandler.setAuthenticationTokenManager(tokenManager); - consumerAuthHandler.handle(invocation, asyncResp); - } - - @Before - public void setUp() throws Exception { - invocation = Mockito.mock(Invocation.class); - asyncResp = Mockito.mock(AsyncResponse.class); - } -} diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java deleted file mode 100644 index 27b496a8cc8..00000000000 --- a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestProviderAuthHanlder.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.authentication; - -import org.apache.servicecomb.authentication.provider.ProviderAuthHanlder; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -public class TestProviderAuthHanlder { - Invocation invocation = null; - - AsyncResponse asyncResp = null; - - @Before - public void setUp() throws Exception { - ConfigUtil.installDynamicConfig(); - invocation = Mockito.mock(Invocation.class); - asyncResp = Mockito.mock(AsyncResponse.class); - Mockito.when(invocation.getContext(Const.AUTH_TOKEN)).thenReturn("testtoken"); - } - @After - public void tearDown() { - ArchaiusUtils.resetConfig(); - } - @Test - public void testHandle() throws Exception { - ProviderAuthHanlder providerAuthHanlder = new ProviderAuthHanlder(); - providerAuthHanlder.handle(invocation, asyncResp); - Assert.assertTrue(true); - } -} diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAAuthenticationToken.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAAuthenticationToken.java index 58ee7a3aca7..e9ec7e2b2a9 100644 --- a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAAuthenticationToken.java +++ b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/TestRSAAuthenticationToken.java @@ -16,18 +16,38 @@ */ package org.apache.servicecomb.authentication; +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; + import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; -import org.apache.servicecomb.foundation.common.utils.RSAUtils; -import org.junit.Assert; -import org.junit.Test; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.common.utils.KeyPairUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; public class TestRSAAuthenticationToken { + static Environment environment = Mockito.mock(Environment.class); + @BeforeAll + public static void setUpClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keyGeneratorAlgorithm", "RSA")) + .thenReturn("RSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.signAlgorithm", "SHA256withRSA")) + .thenReturn("SHA256withRSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keySize", int.class, 2048)) + .thenReturn(2048); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + } @Test public void testRSAAuthenticationToken() @@ -36,16 +56,16 @@ public void testRSAAuthenticationToken() "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; RSAAuthenticationToken token = RSAAuthenticationToken.fromStr(tokenstr); String contents = token.plainToken(); - Assert.assertEquals( + Assertions.assertEquals( "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ", contents); String sign = token.getSign(); - Assert.assertEquals( + Assertions.assertEquals( "WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk=", sign); String pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxKl5TNUTec7fL2degQcCk6vKf3c0wsfNK5V6elKzjWxm0MwbRj/UeR20VSnicBmVIOWrBS9LiERPPvjmmWUOSS2vxwr5XfhBhZ07gCAUNxBOTzgMo5nE45DhhZu5Jzt5qSV6o10Kq7+fCCBlDZ1UoWxZceHkUt5AxcrhEDulFjQIDAQAB"; - Assert.assertTrue(RSAUtils.verify(pubKey, sign, contents)); + Assertions.assertTrue(KeyPairUtils.verify(pubKey, sign, contents)); } @@ -54,7 +74,7 @@ public void testRSAAuthenticationTokenError() { String tokenstr = "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; RSAAuthenticationToken token = RSAAuthenticationToken.fromStr(tokenstr); - Assert.assertNull(token); + Assertions.assertNull(token); } @@ -63,17 +83,17 @@ public void testEqual() { String tokenstr = "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; RSAAuthenticationToken token = RSAAuthenticationToken.fromStr(tokenstr); - Assert.assertNotEquals(token, null); + Assertions.assertNotEquals(token, null); RSAAuthenticationToken token2 = RSAAuthenticationToken.fromStr( "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk"); - Assert.assertNotEquals(token2, token); + Assertions.assertNotEquals(token2, token); RSAAuthenticationToken token3 = RSAAuthenticationToken.fromStr( "e8a0a4b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk"); - Assert.assertNotEquals(token3, token); + Assertions.assertNotEquals(token3, token); RSAAuthenticationToken token4 = RSAAuthenticationToken.fromStr( "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="); - Assert.assertEquals(token4, token); + Assertions.assertEquals(token4, token); } } diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestPathCheckUtils.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestPathCheckUtils.java new file mode 100644 index 00000000000..b8ff4623081 --- /dev/null +++ b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestPathCheckUtils.java @@ -0,0 +1,161 @@ +/* + * 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.authentication.provider; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.mockito.Mockito.when; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.servers.Server; +import org.apache.servicecomb.swagger.SwaggerUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.core.env.Environment; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class TestPathCheckUtils { + private static final String KEY_INCLUDE_PATH = "servicecomb.publicKey.accessControl.includePathPatterns"; + + private static final String KEY_EXCLUDE_PATH = "servicecomb.publicKey.accessControl.excludePathPatterns"; + + private static final String BASE_PATH = "/api/v1"; + + private Environment environment; + + private OpenAPI swagger; + + @BeforeEach + public void setUp() { + environment = Mockito.mock(Environment.class); + swagger = new OpenAPI(); + swagger.setServers(new ArrayList<>()); + swagger.getServers().add(new Server().url(BASE_PATH)); + } + + @Test + public void testExcludePathWithBasePathAndExactMatch() { + String operationPath = "/public"; + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(BASE_PATH + operationPath); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, operationPath); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for excluded path with exact match"); + } + + @Test + public void testExcludePathWithBasePathAndWildcard() { + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(BASE_PATH + "/public/*"); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/public/test"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for excluded path with wildcard"); + + fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/public/nested/path"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for excluded nested path with wildcard"); + } + + @Test + public void testIncludePathWithBasePath() { + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(""); + when(environment.getProperty(KEY_INCLUDE_PATH, "")).thenReturn(BASE_PATH + "/private/*"); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/private/resource"); + assertFalse(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should require auth for included path"); + + fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/public/resource"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for non-included path"); + } + + @Test + public void testExcludeOverrideIncludePath() { + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(BASE_PATH + "/resource"); + when(environment.getProperty(KEY_INCLUDE_PATH, "")).thenReturn(BASE_PATH + "/*"); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/resource"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Exclude patterns should override include patterns"); + } + + @Test + public void testMultipleExcludePaths() { + List operationPaths = List.of("/public", "/health", "/metrics/*"); + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(concatPath(BASE_PATH, operationPaths)); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/public"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for first exclude path"); + + fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/health"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for second exclude path"); + + fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/metrics/jvm"); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth for wildcard exclude path"); + } + + @Test + public void testDifferentBasePath() { + String basePath = "/different/base"; + String publicOperationPath = "/public"; + String privateOperationPath = "/private"; + swagger.getServers().clear(); + swagger.getServers().add(new Server().url(basePath)); + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(basePath + publicOperationPath); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, publicOperationPath); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth with different base path"); + + fullPath = SwaggerUtils.concatAbsolutePath(swagger, privateOperationPath); + assertFalse(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should require auth for non-excluded path with different base path"); + } + + @Test + public void testNoBasePath() { + String operationPath = "/public"; + swagger.setServers(null); + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(operationPath); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, operationPath); + assertTrue(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should not require auth when no base path is set"); + } + + @Test + public void testEmptyConfiguration() { + when(environment.getProperty(KEY_EXCLUDE_PATH, "")).thenReturn(""); + when(environment.getProperty(KEY_INCLUDE_PATH, "")).thenReturn(""); + + String fullPath = SwaggerUtils.concatAbsolutePath(swagger, "/any/path"); + assertFalse(PathCheckUtils.isNotRequiredAuth(fullPath, environment), + "Should require auth by default when no patterns are configured"); + } + + private String concatPath(String basePath, List paths) { + return paths.stream().map(path -> basePath + path).collect(Collectors.joining(",")); + } +} diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestProviderTokenManager.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestProviderTokenManager.java new file mode 100644 index 00000000000..801f91e697d --- /dev/null +++ b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestProviderTokenManager.java @@ -0,0 +1,165 @@ +/* + * 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.authentication.provider; + +import static org.apache.servicecomb.core.SCBEngine.CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC; +import static org.apache.servicecomb.core.SCBEngine.DEFAULT_TURN_DOWN_STATUS_WAIT_SEC; +import static org.mockito.ArgumentMatchers.any; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.authentication.RSAAuthenticationToken; +import org.apache.servicecomb.authentication.consumer.ConsumerTokenManager; +import org.apache.servicecomb.config.BootStrapProperties; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; +import org.apache.servicecomb.foundation.common.utils.KeyPairEntry; +import org.apache.servicecomb.foundation.common.utils.KeyPairUtils; +import org.apache.servicecomb.foundation.token.Keypair4Auth; +import org.apache.servicecomb.registry.api.DiscoveryInstance; +import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.apache.servicecomb.registry.discovery.MicroserviceInstanceCache; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.Environment; +import org.springframework.core.env.MutablePropertySources; + +import com.google.common.cache.Cache; + +public class TestProviderTokenManager { + static Environment environment = Mockito.mock(Environment.class); + + @BeforeAll + public static void setUpClass() { + LegacyPropertyFactory.setEnvironment(environment); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keyGeneratorAlgorithm", "RSA")) + .thenReturn("RSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.signAlgorithm", "SHA256withRSA")) + .thenReturn("SHA256withRSA"); + Mockito.when(environment.getProperty("servicecomb.publicKey.accessControl.keySize", int.class, 2048)) + .thenReturn(2048); + Mockito.when(environment.getProperty(CFG_KEY_TURN_DOWN_STATUS_WAIT_SEC, + long.class, DEFAULT_TURN_DOWN_STATUS_WAIT_SEC)).thenReturn(DEFAULT_TURN_DOWN_STATUS_WAIT_SEC); + } + + @BeforeEach + public void setUp() { + } + + @AfterEach + public void teardown() { + } + + @Test + public void testTokenExpired() { + String tokenStr = + "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; + ProviderTokenManager tokenManager = new ProviderTokenManager(); + DiscoveryInstance microserviceInstance = Mockito.mock(DiscoveryInstance.class); + Map properties = new HashMap<>(); + Mockito.when(microserviceInstance.getProperties()).thenReturn(properties); + properties.put(DefinitionConst.INSTANCE_PUBKEY_PRO, + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxKl5TNUTec7fL2degQcCk6vKf3c0wsfNK5V6elKzjWxm0MwbRj/UeR20VSnicBmVIOWrBS9LiERPPvjmmWUOSS2vxwr5XfhBhZ07gCAUNxBOTzgMo5nE45DhhZu5Jzt5qSV6o10Kq7+fCCBlDZ1UoWxZceHkUt5AxcrhEDulFjQIDAQAB"); + Assertions.assertFalse(tokenManager.valid(tokenStr)); + } + + @Test + @SuppressWarnings("unchecked") + public void testTokenExpiredRemoveInstance() throws Exception { + + String tokenStr = + "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; + RSAAuthenticationToken token = Mockito.spy(RSAAuthenticationToken.fromStr(tokenStr)); + ProviderTokenManager tokenManager = Mockito.spy(new ProviderTokenManager() { + @Override + protected int getExpiredTime() { + return 500; + } + }); + ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class); + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + tokenManager.setAccessController(new AccessController(environment)); + MicroserviceInstanceCache microserviceInstanceCache = Mockito.mock(MicroserviceInstanceCache.class); + DiscoveryInstance microserviceInstance = Mockito.mock(DiscoveryInstance.class); + Mockito.when(microserviceInstance.getInstanceId()).thenReturn(""); + Map properties = new HashMap<>(); + Mockito.when(microserviceInstance.getProperties()).thenReturn(properties); + Mockito.when(microserviceInstanceCache.getOrCreate(any(String.class), any(String.class))) + .thenReturn(microserviceInstance); + tokenManager.setMicroserviceInstanceCache(microserviceInstanceCache); + try (MockedStatic rsaAuthenticationTokenMockedStatic = Mockito.mockStatic( + RSAAuthenticationToken.class)) { + rsaAuthenticationTokenMockedStatic.when(() -> RSAAuthenticationToken.fromStr(tokenStr)).thenReturn(token); + Mockito.when(token.getGenerateTime()).thenReturn(System.currentTimeMillis()); + Mockito.doReturn(true).when(tokenManager).isValidToken(token); + Assertions.assertTrue(tokenManager.valid(tokenStr)); + + Cache cache = tokenManager + .getValidatedToken(); + Assertions.assertTrue(cache.asMap().containsKey(token)); + + Thread.sleep(1000); + Assertions.assertFalse(cache.asMap().containsKey(token)); + } + } + + @Test + public void testTokenFromValidatePool() { + KeyPairEntry keyPairEntry = KeyPairUtils.generateALGKeyPair(); + Keypair4Auth.INSTANCE.setPrivateKey(keyPairEntry.getPrivateKey()); + Keypair4Auth.INSTANCE.setPublicKey(keyPairEntry.getPublicKey()); + Keypair4Auth.INSTANCE.setPublicKeyEncoded(keyPairEntry.getPublicKeyEncoded()); + String serviceId = "test"; + String instanceId = "test"; + ConsumerTokenManager consumerTokenManager = new ConsumerTokenManager(); + + ConfigurableEnvironment environment = Mockito.mock(ConfigurableEnvironment.class); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_NAME)).thenReturn("test"); + Mockito.when(environment.getProperty(BootStrapProperties.CONFIG_SERVICE_APPLICATION)).thenReturn("test"); + consumerTokenManager.setEnvironment(environment); + DiscoveryInstance microserviceInstance = Mockito.mock(DiscoveryInstance.class); + Mockito.when(microserviceInstance.getInstanceId()).thenReturn(instanceId); + Map properties = new HashMap<>(); + Mockito.when(microserviceInstance.getProperties()).thenReturn(properties); + properties.put(DefinitionConst.INSTANCE_PUBKEY_PRO, keyPairEntry.getPublicKeyEncoded()); + MicroserviceInstanceCache microserviceInstanceCache = Mockito.mock(MicroserviceInstanceCache.class); + Mockito.when(microserviceInstanceCache.getOrCreate(serviceId, instanceId)).thenReturn(microserviceInstance); + //Test Consumer first create token + String token = consumerTokenManager.getToken(); + Assertions.assertNotNull(token); + // use cache token + Assertions.assertEquals(token, consumerTokenManager.getToken()); + ProviderTokenManager rsaProviderTokenManager = new ProviderTokenManager(); + + MutablePropertySources mutablePropertySources = new MutablePropertySources(); + Mockito.when(environment.getPropertySources()).thenReturn(mutablePropertySources); + rsaProviderTokenManager.setAccessController(new AccessController(environment)); + + rsaProviderTokenManager.setMicroserviceInstanceCache(microserviceInstanceCache); + //first validate need to verify use RSA + Assertions.assertTrue(rsaProviderTokenManager.valid(token)); + // second validate use validated pool + Assertions.assertTrue(rsaProviderTokenManager.valid(token)); + } +} diff --git a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestRSAProviderTokenManager.java b/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestRSAProviderTokenManager.java deleted file mode 100644 index 5581143e15d..00000000000 --- a/handlers/handler-publickey-auth/src/test/java/org/apache/servicecomb/authentication/provider/TestRSAProviderTokenManager.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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.authentication.provider; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.authentication.RSAAuthenticationToken; -import org.apache.servicecomb.authentication.consumer.RSAConsumerTokenManager; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.foundation.common.utils.RSAKeyPairEntry; -import org.apache.servicecomb.foundation.common.utils.RSAUtils; -import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; -import org.apache.servicecomb.foundation.token.RSAKeypair4Auth; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.registry.cache.MicroserviceInstanceCache; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import com.google.common.cache.Cache; - -import mockit.Expectations; - -public class TestRSAProviderTokenManager { - - - @Before - public void setUp() { - ConfigUtil.installDynamicConfig(); - } - - @After - public void teardown() { - ArchaiusUtils.resetConfig(); - } - - @Test - public void testTokenExpired() { - String tokenStr = - "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; - RSAProviderTokenManager tokenManager = new RSAProviderTokenManager(); - MicroserviceInstance microserviceInstance = new MicroserviceInstance(); - Map properties = new HashMap<>(); - microserviceInstance.setProperties(properties); - properties.put(DefinitionConst.INSTANCE_PUBKEY_PRO, - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxKl5TNUTec7fL2degQcCk6vKf3c0wsfNK5V6elKzjWxm0MwbRj/UeR20VSnicBmVIOWrBS9LiERPPvjmmWUOSS2vxwr5XfhBhZ07gCAUNxBOTzgMo5nE45DhhZu5Jzt5qSV6o10Kq7+fCCBlDZ1UoWxZceHkUt5AxcrhEDulFjQIDAQAB"); - Assert.assertFalse(tokenManager.valid(tokenStr)); - } - - @Test - @SuppressWarnings("unchecked") - public void testTokenExpiredRemoveInstance() throws Exception { - - String tokenStr = - "e8a04b54cf2711e7b701286ed488fc20@c8636e5acf1f11e7b701286ed488fc20@1511315597475@9t0tp8ce80SUM5ts6iRGjFJMvCdQ7uvhpyh0RM7smKm3p4wYOrojr4oT1Pnwx7xwgcgEFbQdwPJxIMfivpQ1rHGqiLp67cjACvJ3Ke39pmeAVhybsLADfid6oSjscFaJ@WBYouF6hXYrXzBA31HC3VX8Bw9PNgJUtVqOPAaeW9ye3q/D7WWb0M+XMouBIWxWY6v9Un1dGu5Rkjlx6gZbnlHkb2VO8qFR3Y6lppooWCirzpvEBRjlJQu8LPBur0BCfYGq8XYrEZA2NU6sg2zXieqCSiX6BnMnBHNn4cR9iZpk="; - RSAAuthenticationToken token = RSAAuthenticationToken.fromStr(tokenStr); - RSAProviderTokenManager tokenManager = new RSAProviderTokenManager() { - @Override - protected int getExpiredTime() { - return 500; - } - }; - - new Expectations(RSAProviderTokenManager.class, RSAAuthenticationToken.class) { - { - token.getGenerateTime(); - result = System.currentTimeMillis(); - - tokenManager.isValidToken(token); - result = true; - } - }; - - Assert.assertTrue(tokenManager.valid(tokenStr)); - - Cache cache = tokenManager - .getValidatedToken(); - Assert.assertTrue(cache.asMap().containsKey(token)); - - Thread.sleep(1000); - Assert.assertFalse(cache.asMap().containsKey(token)); - } - - @Test - public void testTokenFromValidatePool() { - RSAKeyPairEntry rsaKeyPairEntry = RSAUtils.generateRSAKeyPair(); - RSAKeypair4Auth.INSTANCE.setPrivateKey(rsaKeyPairEntry.getPrivateKey()); - RSAKeypair4Auth.INSTANCE.setPublicKey(rsaKeyPairEntry.getPublicKey()); - RSAKeypair4Auth.INSTANCE.setPublicKeyEncoded(rsaKeyPairEntry.getPublicKeyEncoded()); - String serviceId = "c8636e5acf1f11e7b701286ed488fc20"; - String instanceId = "e8a04b54cf2711e7b701286ed488fc20"; - RSAConsumerTokenManager rsaConsumerTokenManager = new RSAConsumerTokenManager(); - MicroserviceInstance microserviceInstance = new MicroserviceInstance(); - microserviceInstance.setInstanceId(instanceId); - Map properties = new HashMap<>(); - microserviceInstance.setProperties(properties); - properties.put(DefinitionConst.INSTANCE_PUBKEY_PRO, rsaKeyPairEntry.getPublicKeyEncoded()); - Microservice microservice = new Microservice(); - microservice.setServiceId(serviceId); - new Expectations(RegistrationManager.INSTANCE) { - { - RegistrationManager.INSTANCE.getMicroservice(); - result = microservice; - RegistrationManager.INSTANCE.getMicroserviceInstance(); - result = microserviceInstance; - } - }; - //Test Consumer first create token - String token = rsaConsumerTokenManager.getToken(); - Assert.assertNotNull(token); - // use cache token - Assert.assertEquals(token, rsaConsumerTokenManager.getToken()); - new Expectations(MicroserviceInstanceCache.class) { - { - MicroserviceInstanceCache.getOrCreate(serviceId, instanceId); - result = microserviceInstance; - MicroserviceInstanceCache.getOrCreate(serviceId); - result = microservice; - } - }; - RSAProviderTokenManager rsaProviderTokenManager = new RSAProviderTokenManager(); - //first validate need to verify use RSA - Assert.assertTrue(rsaProviderTokenManager.valid(token)); - // second validate use validated pool - Assert.assertTrue(rsaProviderTokenManager.valid(token)); - } -} diff --git a/handlers/handler-publickey-auth/src/test/resources/log4j.properties b/handlers/handler-publickey-auth/src/test/resources/log4j.properties deleted file mode 100644 index fbea91e7afd..00000000000 --- a/handlers/handler-publickey-auth/src/test/resources/log4j.properties +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -log4j.rootLogger=INFO, out, stdout - -# CONSOLE appender not used by default -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n - -# File appender -log4j.appender.out=org.apache.log4j.FileAppender -log4j.appender.out.layout=org.apache.log4j.PatternLayout -log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n -log4j.appender.out.file=target/test.log -log4j.appender.out.append=true diff --git a/handlers/handler-publickey-auth/src/test/resources/microservice.yaml b/handlers/handler-publickey-auth/src/test/resources/microservice.yaml index 4db1321ba99..5ff7ed9ae41 100644 --- a/handlers/handler-publickey-auth/src/test/resources/microservice.yaml +++ b/handlers/handler-publickey-auth/src/test/resources/microservice.yaml @@ -20,4 +20,4 @@ servicecomb: consumer: default: empty producer: - default: empty \ No newline at end of file + default: empty diff --git a/handlers/handler-router/pom.xml b/handlers/handler-router/pom.xml index 1ea801a9afa..0068002eb7d 100644 --- a/handlers/handler-router/pom.xml +++ b/handlers/handler-router/pom.xml @@ -22,7 +22,7 @@ handlers org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -30,10 +30,6 @@ Java Chassis::Handlers::Router - - com.netflix.ribbon - ribbon-loadbalancer - org.springframework spring-core @@ -63,4 +59,4 @@ handler-loadbalance - \ No newline at end of file + diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/MicroserviceCache.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/MicroserviceCache.java deleted file mode 100644 index 6e4ec24df39..00000000000 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/MicroserviceCache.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.router.custom; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.Microservice; - -public final class MicroserviceCache { - - private static MicroserviceCache instance = new MicroserviceCache(); - - private Map services = new HashMap<>(); - - private MicroserviceCache() { - } - - public static MicroserviceCache getInstance() { - return instance; - } - - public Microservice getService(String serviceId) { - return services.computeIfAbsent(serviceId, (k) -> - DiscoveryManager.INSTANCE.getMicroservice(serviceId) - ); - } -} diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java deleted file mode 100644 index 7951850f54a..00000000000 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterHeaderFilterExt.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.router.custom; - -import java.util.Map; - -/** - * allow users to filter not necessary headers in request. - **/ -public interface RouterHeaderFilterExt { - - default int getOrder() { - return 0; - } - - default boolean enabled() { - return true; - } - - Map doFilter(Map invokeHeader); -} diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java deleted file mode 100644 index b40bf543dc8..00000000000 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterInvokeFilter.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.router.custom; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.common.rest.filter.HttpServerFilter; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.CollectionUtils; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.DynamicStringProperty; - -public class RouterInvokeFilter implements HttpServerFilter { - - private static final Logger LOGGER = LoggerFactory.getLogger(RouterInvokeFilter.class); - - private static final String SERVICECOMB_ROUTER_HEADER = "servicecomb.router.header"; - - private static List allHeader = new ArrayList<>(); - - - @Override - public int getOrder() { - return -90; - } - - @Override - public boolean enabled() { - return true; - } - - @Override - public Response afterReceiveRequest(Invocation invocation, - HttpServletRequestEx httpServletRequestEx) { - if (!StringUtils.isEmpty(invocation.getContext(RouterServerListFilter.ROUTER_HEADER))) { - return null; - } - - if (!isHaveHeadersRule()) { - return null; - } - if (loadHeaders()) { - Map headerMap = getHeaderMap(httpServletRequestEx); - try { - invocation - .addContext(RouterServerListFilter.ROUTER_HEADER, JsonUtils.OBJ_MAPPER.writeValueAsString(headerMap)); - } catch (JsonProcessingException e) { - LOGGER.error("canary context serialization failed"); - } - } - return null; - } - - /** - * read config and get Header - */ - private boolean loadHeaders() { - if (!CollectionUtils.isEmpty(allHeader)) { - return true; - } - DynamicStringProperty headerStr = DynamicPropertyFactory.getInstance() - .getStringProperty(SERVICECOMB_ROUTER_HEADER, null, () -> { - DynamicStringProperty temHeader = DynamicPropertyFactory.getInstance() - .getStringProperty(SERVICECOMB_ROUTER_HEADER, null); - if (!addAllHeaders(temHeader.get())) { - allHeader = new ArrayList<>(); - } - }); - return addAllHeaders(headerStr.get()); - } - - /** - * if don't have headers rule , avoid registered too many callback - */ - private boolean isHaveHeadersRule() { - DynamicStringProperty headerStr = DynamicPropertyFactory.getInstance() - .getStringProperty(SERVICECOMB_ROUTER_HEADER, null); - return StringUtils.isNotEmpty(headerStr.get()); - } - - private boolean addAllHeaders(String str) { - if (StringUtils.isEmpty(str)) { - return false; - } - try { - if (CollectionUtils.isEmpty(allHeader)) { - allHeader = Arrays.asList(str.split(",")); - } - } catch (Exception e) { - LOGGER.error("route management Serialization failed: {}", e.getMessage()); - return false; - } - return true; - } - - private Map getHeaderMap(HttpServletRequestEx httpServletRequestEx) { - Map headerMap = new HashMap<>(); - allHeader.forEach(headerKey -> { - String val = httpServletRequestEx.getHeader(headerKey); - if (!StringUtils.isEmpty(val)) { - headerMap.put(headerKey, httpServletRequestEx.getHeader(headerKey)); - } - }); - return headerMap; - } -} diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java index 2776c0133d7..fdae82e1445 100644 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/RouterServerListFilter.java @@ -16,45 +16,32 @@ */ package org.apache.servicecomb.router.custom; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.governance.MatchType; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.foundation.common.utils.BeanUtils; -import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.loadbalance.ServerListFilterExt; import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.registry.api.registry.Microservice; import org.apache.servicecomb.router.RouterFilter; import org.apache.servicecomb.router.distribute.RouterDistributor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.netflix.config.DynamicPropertyFactory; public class RouterServerListFilter implements ServerListFilterExt { - private static final Logger LOGGER = LoggerFactory.getLogger(RouterServerListFilter.class); - private static final String ENABLE = "servicecomb.router.type"; private static final String TYPE_ROUTER = "router"; - public static final String ROUTER_HEADER = "X-RouterContext"; - @SuppressWarnings("unchecked") - private RouterDistributor routerDistributor = BeanUtils + private final RouterDistributor routerDistributor = BeanUtils .getBean(RouterDistributor.class); - private RouterFilter routerFilter = BeanUtils.getBean(RouterFilter.class); + private final RouterFilter routerFilter = BeanUtils.getBean(RouterFilter.class); @Override public boolean enabled() { - return DynamicPropertyFactory.getInstance().getStringProperty(ENABLE, "").get() + return LegacyPropertyFactory.getStringProperty(ENABLE, "") .equals(TYPE_ROUTER); } @@ -62,42 +49,7 @@ public boolean enabled() { public List getFilteredListOfServers(List list, Invocation invocation) { String targetServiceName = invocation.getMicroserviceName(); - Map headers = addHeaders(invocation); - headers = filterHeaders(headers); - return routerFilter - .getFilteredListOfServers(list, targetServiceName, headers, - routerDistributor); - } - - private Map filterHeaders(Map headers) { - List filters = SPIServiceUtils - .getOrLoadSortedService(RouterHeaderFilterExt.class); - for (RouterHeaderFilterExt filterExt : filters) { - if (filterExt.enabled()) { - headers = filterExt.doFilter(headers); - } - } - return headers; - } - - private Map addHeaders(Invocation invocation) { - Map headers = new HashMap<>(); - if (invocation.getContext(ROUTER_HEADER) != null) { - Map canaryContext = null; - try { - canaryContext = JsonUtils.OBJ_MAPPER - .readValue(invocation.getContext(ROUTER_HEADER), - new TypeReference>() { - }); - } catch (JsonProcessingException e) { - LOGGER.error("canary context serialization failed"); - } - if (canaryContext != null) { - headers.putAll(canaryContext); - } - } - invocation.getInvocationArguments().forEach((k, v) -> headers.put(k, v == null ? null : v.toString())); - headers.putAll(invocation.getContext()); - return headers; + return routerFilter.getFilteredListOfServers(list, targetServiceName, + MatchType.createGovHttpRequest(invocation), routerDistributor); } } diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java deleted file mode 100644 index 1bde97588ad..00000000000 --- a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombCanaryDistributer.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.router.custom; - -import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.router.distribute.AbstractRouterDistributor; -import org.springframework.stereotype.Component; - -@Component -public class ServiceCombCanaryDistributer extends - AbstractRouterDistributor { - - public ServiceCombCanaryDistributer() { - init(server -> MicroserviceCache.getInstance() - .getService(server.getInstance().getServiceId()), - Microservice::getVersion, - Microservice::getServiceName, - Microservice::getProperties); - } -} diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombRouterConfiguration.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombRouterConfiguration.java new file mode 100644 index 00000000000..ff6952d24c8 --- /dev/null +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombRouterConfiguration.java @@ -0,0 +1,35 @@ +/* + * 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.router.custom; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(value = ServiceCombRouterConfiguration.ROUTER_ENABLED, + havingValue = "true", matchIfMissing = true) +public class ServiceCombRouterConfiguration { + public static final String ROUTER_PREFIX = "servicecomb.router"; + + public static final String ROUTER_ENABLED = ROUTER_PREFIX + ".enabled"; + + @Bean + public ServiceCombRouterDistributor scbServiceCombRouterDistributor() { + return new ServiceCombRouterDistributor(); + } +} diff --git a/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombRouterDistributor.java b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombRouterDistributor.java new file mode 100644 index 00000000000..709e4598bd8 --- /dev/null +++ b/handlers/handler-router/src/main/java/org/apache/servicecomb/router/custom/ServiceCombRouterDistributor.java @@ -0,0 +1,38 @@ +/* + * 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.router.custom; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.loadbalance.ServiceCombServer; +import org.apache.servicecomb.router.distribute.AbstractRouterDistributor; + +public class ServiceCombRouterDistributor extends + AbstractRouterDistributor { + + public ServiceCombRouterDistributor() { + init( + instance -> instance.getInstance().getVersion(), + instance -> instance.getInstance().getServiceName(), + instance -> { + Map properties = new HashMap<>(); + properties.putAll(instance.getInstance().getProperties()); + return properties; + }); + } +} diff --git a/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter deleted file mode 100644 index 02a728b1987..00000000000 --- a/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.router.custom.RouterInvokeFilter \ No newline at end of file diff --git a/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt b/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt index f5a6ffa008e..0e6f5d9a65b 100644 --- a/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt +++ b/handlers/handler-router/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.router.custom.RouterServerListFilter \ No newline at end of file +org.apache.servicecomb.router.custom.RouterServerListFilter diff --git a/handlers/handler-router/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-router/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..8bbbb93c1f5 --- /dev/null +++ b/handlers/handler-router/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.servicecomb.router.custom.ServiceCombRouterConfiguration diff --git a/handlers/handler-tracing-zipkin/pom.xml b/handlers/handler-tracing-zipkin/pom.xml index 2edc2265804..3644d209bab 100644 --- a/handlers/handler-tracing-zipkin/pom.xml +++ b/handlers/handler-tracing-zipkin/pom.xml @@ -22,7 +22,7 @@ handlers org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -50,10 +50,6 @@ io.zipkin.brave brave - - io.zipkin.reporter2 - zipkin-sender-okhttp3 - io.zipkin.brave brave-context-slf4j @@ -61,7 +57,14 @@ io.zipkin.zipkin2 zipkin - compile + + + io.zipkin.reporter2 + zipkin-sender-okhttp3 + + + io.zipkin.reporter2 + zipkin-reporter-brave diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ConsumerInvocationAdapter.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ConsumerInvocationAdapter.java deleted file mode 100644 index 1428fa8f815..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ConsumerInvocationAdapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.tracing.zipkin; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -import brave.http.HttpClientAdapter; -import zipkin2.internal.Nullable; - -class ConsumerInvocationAdapter extends HttpClientAdapter { - - @Nullable - @Override - public String method(@Nonnull Invocation invocation) { - return invocation.getOperationMeta().getHttpMethod(); - } - - @Nullable - @Override - public String url(@Nonnull Invocation invocation) { - return invocation.getEndpoint().getEndpoint(); - } - - @Nullable - @Override - public String path(@Nonnull Invocation request) { - return request.getOperationMeta().getOperationPath(); - } - - @Nullable - @Override - public String requestHeader(@Nonnull Invocation invocation, @Nonnull String key) { - return invocation.getContext().get(key); - } - - @Nullable - @Override - public Integer statusCode(@Nonnull Response response) { - return response.getStatusCode(); - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/CustomHttpRequestParser.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/CustomHttpRequestParser.java new file mode 100644 index 00000000000..32fb8752028 --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/CustomHttpRequestParser.java @@ -0,0 +1,38 @@ +/* + * 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.tracing.zipkin; + +import org.apache.servicecomb.core.Invocation; + +import brave.SpanCustomizer; +import brave.http.HttpRequest; +import brave.http.HttpRequestParser; +import brave.http.HttpTags; +import brave.propagation.TraceContext; + +public record CustomHttpRequestParser() implements HttpRequestParser { + @Override + public void parse(HttpRequest req, TraceContext context, SpanCustomizer span) { + Invocation invocation = ((InvocationAware) req).getInvocation(); + span.name(invocation.getInvocationQualifiedName()); + HttpTags.METHOD.tag(req, context, span); + HttpTags.PATH.tag(req, context, span); + if (!invocation.isConsumer()) { // server or edge + HttpTags.ROUTE.tag(req, context, span); + } + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/CustomHttpResponseParser.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/CustomHttpResponseParser.java new file mode 100644 index 00000000000..bb59f7e9371 --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/CustomHttpResponseParser.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.tracing.zipkin; + +import org.apache.servicecomb.core.Invocation; + +import brave.SpanCustomizer; +import brave.Tags; +import brave.http.HttpResponse; +import brave.http.HttpResponseParser; +import brave.http.HttpTags; +import brave.propagation.TraceContext; + +public record CustomHttpResponseParser() implements HttpResponseParser { + @Override + public void parse(HttpResponse response, TraceContext context, SpanCustomizer span) { + Invocation invocation = ((InvocationAware) response).getInvocation(); + HttpTags.STATUS_CODE.tag(response, context, span); + if (response.error() != null) { + span.tag(Tags.ERROR.key(), response.error().getMessage()); + } + if (!invocation.isProducer()) { // client or edge + span.tag(HttpTags.ROUTE.key(), response.route()); + } + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpClientRequestWrapper.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpClientRequestWrapper.java new file mode 100644 index 00000000000..cc758d68a27 --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpClientRequestWrapper.java @@ -0,0 +1,70 @@ +/* + * 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.tracing.zipkin; + +import org.apache.servicecomb.core.Invocation; + +import brave.http.HttpClientRequest; + +class HttpClientRequestWrapper extends HttpClientRequest implements InvocationAware { + private final Invocation invocation; + + HttpClientRequestWrapper(Invocation invocation) { + this.invocation = invocation; + } + + @Override + public void header(String name, String value) { + invocation.addContext(name, value); + } + + @Override + public String method() { + return invocation.getOperationMeta().getHttpMethod(); + } + + @Override + public String route() { + return invocation.getEndpoint().getEndpoint(); + } + + @Override + public String path() { + return TracingConfiguration.createRequestPath(invocation); + } + + @Override + public String url() { + return invocation.getInvocationQualifiedName(); + } + + @Override + public String header(String name) { + return invocation.getContext(name); + } + + @Override + public Object unwrap() { + return invocation; + } + + @Override + public Invocation getInvocation() { + return invocation; + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpClientResponseWrapper.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpClientResponseWrapper.java new file mode 100644 index 00000000000..b939efaa610 --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpClientResponseWrapper.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.tracing.zipkin; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.swagger.invocation.Response; + +import brave.http.HttpClientRequest; +import brave.http.HttpClientResponse; + +class HttpClientResponseWrapper extends HttpClientResponse implements InvocationAware { + final HttpClientRequest request; + + final Response response; + + final Invocation invocation; + + HttpClientResponseWrapper(Invocation invocation, Response response, HttpClientRequestWrapper request) { + this.response = response; + this.request = request; + this.invocation = invocation; + } + + @Override + public int statusCode() { + return response.getStatusCode(); + } + + @Override + public Object unwrap() { + return response; + } + + @Override + public HttpClientRequest request() { + return request; + } + + @Override + public Throwable error() { + return response.isFailed() ? response.getResult() : null; + } + + @Override + public Invocation getInvocation() { + return invocation; + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpServeRequestWrapper.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpServeRequestWrapper.java new file mode 100644 index 00000000000..45725539b46 --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpServeRequestWrapper.java @@ -0,0 +1,70 @@ +/* + * 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.tracing.zipkin; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.core.Invocation; + +import brave.http.HttpServerRequest; + +class HttpServeRequestWrapper extends HttpServerRequest implements InvocationAware { + private final Invocation invocation; + + HttpServeRequestWrapper(Invocation invocation) { + this.invocation = invocation; + } + + @Override + public String method() { + return invocation.getOperationMeta().getHttpMethod(); + } + + @Override + public String path() { + return TracingConfiguration.createRequestPath(invocation); + } + + @Override + public String url() { + return invocation.getInvocationQualifiedName(); + } + + @Override + public String route() { + return invocation.getRequestEx() != null ? invocation.getRequestEx().getRemoteAddr() : null; + } + + @Override + public String header(String name) { + String result = invocation.getContext(name); + if (StringUtils.isEmpty(result) && invocation.getRequestEx() != null) { + result = invocation.getRequestEx().getHeader(name); + } + return result; + } + + @Override + public Object unwrap() { + return invocation; + } + + @Override + public Invocation getInvocation() { + return invocation; + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpServerResponseWrapper.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpServerResponseWrapper.java new file mode 100644 index 00000000000..9f384bdfffd --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/HttpServerResponseWrapper.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.tracing.zipkin; + +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.swagger.invocation.Response; + +import brave.http.HttpServerRequest; +import brave.http.HttpServerResponse; + +class HttpServerResponseWrapper extends HttpServerResponse implements InvocationAware { + private final Response response; + + private final HttpServerRequest request; + + private final Invocation invocation; + + HttpServerResponseWrapper(Invocation invocation, Response response, HttpServeRequestWrapper request) { + this.response = response; + this.request = request; + this.invocation = invocation; + } + + @Override + public int statusCode() { + return response.getStatusCode(); + } + + @Override + public Object unwrap() { + return response; + } + + @Override + public HttpServerRequest request() { + return request; + } + + @Override + public Throwable error() { + return response.isFailed() ? response.getResult() : null; + } + + @Override + public Invocation getInvocation() { + return invocation; + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/InvocationAware.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/InvocationAware.java new file mode 100644 index 00000000000..ddb4e8365ae --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/InvocationAware.java @@ -0,0 +1,23 @@ +/* + * 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.tracing.zipkin; + +import org.apache.servicecomb.core.Invocation; + +public interface InvocationAware { + Invocation getInvocation(); +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/LogSpanHandler.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/LogSpanHandler.java new file mode 100644 index 00000000000..93499ec9209 --- /dev/null +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/LogSpanHandler.java @@ -0,0 +1,42 @@ +/* + * 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.tracing.zipkin; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brave.handler.MutableSpan; +import brave.handler.SpanHandler; +import brave.propagation.TraceContext; + +public class LogSpanHandler extends SpanHandler { + private static final Logger LOGGER = LoggerFactory.getLogger("scb-trace"); + + public boolean end(TraceContext context, MutableSpan span, Cause cause) { + if (!LOGGER.isInfoEnabled()) { + return false; + } else { + LOGGER.info(span.toString()); + return true; + } + } + + public String toString() { + return "LogSpanHandler{name=scb-trace}"; + } +} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ProviderInvocationAdapter.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ProviderInvocationAdapter.java deleted file mode 100644 index da12ab62c5f..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ProviderInvocationAdapter.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.tracing.zipkin; - -import javax.annotation.Nonnull; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -import brave.http.HttpServerAdapter; -import zipkin2.internal.Nullable; - -class ProviderInvocationAdapter extends HttpServerAdapter { - - @Nullable - @Override - public String method(@Nonnull Invocation invocation) { - return invocation.getOperationMeta().getHttpMethod(); - } - - @Nullable - @Override - public String url(@Nonnull Invocation invocation) { - return invocation.getEndpoint().getEndpoint(); - } - - @Nullable - @Override - public String path(@Nonnull Invocation request) { - return request.getOperationMeta().getOperationPath(); - } - - @Nullable - @Override - public String requestHeader(@Nonnull Invocation invocation, @Nonnull String key) { - return invocation.getContext().get(key); - } - - @Nullable - @Override - public Integer statusCode(@Nonnull Response response) { - return response.getStatusCode(); - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/TracingConfiguration.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/TracingConfiguration.java index 9f0c1a8a8b6..79dbc2857b6 100644 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/TracingConfiguration.java +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/TracingConfiguration.java @@ -26,10 +26,19 @@ import java.text.MessageFormat; +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.common.rest.RestConst; +import org.apache.servicecomb.common.rest.definition.RestOperationMeta; import org.apache.servicecomb.config.BootStrapProperties; import org.apache.servicecomb.config.DynamicProperties; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.net.URIEndpointObject; +import org.apache.servicecomb.registry.definition.DefinitionConst; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import brave.Tracing; import brave.context.slf4j.MDCScopeDecorator; @@ -37,62 +46,114 @@ import brave.propagation.CurrentTraceContext; import brave.propagation.ThreadLocalCurrentTraceContext; import zipkin2.Span; -import zipkin2.codec.SpanBytesEncoder; import zipkin2.reporter.AsyncReporter; +import zipkin2.reporter.BytesMessageSender; import zipkin2.reporter.Reporter; import zipkin2.reporter.Sender; +import zipkin2.reporter.SpanBytesEncoder; +import zipkin2.reporter.brave.AsyncZipkinSpanHandler; import zipkin2.reporter.okhttp3.OkHttpSender; @Configuration -class TracingConfiguration { - private String apiVersion = CONFIG_TRACING_COLLECTOR_API_V2; +@ConditionalOnProperty(value = TracingConfiguration.TRACING_ENABLED, + havingValue = "true", matchIfMissing = true) +public class TracingConfiguration { + public static final String TRACING_PREFIX = "servicecomb.tracing"; - @Bean - Sender sender(DynamicProperties dynamicProperties) { - apiVersion = dynamicProperties.getStringProperty(CONFIG_TRACING_COLLECTOR_API_VERSION, - CONFIG_TRACING_COLLECTOR_API_V2).toLowerCase(); - // use default value if the user set value is invalid - if (apiVersion.compareTo(CONFIG_TRACING_COLLECTOR_API_V1) != 0) { - apiVersion = CONFIG_TRACING_COLLECTOR_API_V2; - } + public static final String TRACING_ENABLED = TRACING_PREFIX + ".enabled"; - String path = MessageFormat.format(CONFIG_TRACING_COLLECTOR_PATH, apiVersion); - return OkHttpSender.create( - dynamicProperties.getStringProperty( - CONFIG_TRACING_COLLECTOR_ADDRESS, - DEFAULT_TRACING_COLLECTOR_ADDRESS) - .trim() - .replaceAll("/+$", "") - .concat(path)); - } + public static final String TRACING_REPORTER_LOG_ENABLED = TRACING_PREFIX + ".reporter.log.enabled"; - @Bean - Reporter zipkinReporter(Sender sender) { - if (apiVersion.compareTo(CONFIG_TRACING_COLLECTOR_API_V1) == 0) { - return AsyncReporter.builder(sender).build(SpanBytesEncoder.JSON_V1); + public static final String TRACING_REPORTER_ZIPKIN_ENABLED = TRACING_PREFIX + ".reporter.zipkin.enabled"; + + @Configuration + @ConditionalOnProperty(value = TracingConfiguration.TRACING_REPORTER_ZIPKIN_ENABLED, + havingValue = "true") + static class ZipkinReporterConfiguration { + @Bean + BytesMessageSender scbOkHttpSender(DynamicProperties dynamicProperties) { + String apiVersion = dynamicProperties.getStringProperty(CONFIG_TRACING_COLLECTOR_API_VERSION, + CONFIG_TRACING_COLLECTOR_API_V2).toLowerCase(); + // use default value if the user set value is invalid + if (apiVersion.compareTo(CONFIG_TRACING_COLLECTOR_API_V1) != 0) { + apiVersion = CONFIG_TRACING_COLLECTOR_API_V2; + } + + String path = MessageFormat.format(CONFIG_TRACING_COLLECTOR_PATH, apiVersion); + return OkHttpSender.create( + dynamicProperties.getStringProperty( + CONFIG_TRACING_COLLECTOR_ADDRESS, + DEFAULT_TRACING_COLLECTOR_ADDRESS) + .trim() + .replaceAll("/+$", "") + .concat(path)); } - return AsyncReporter.builder(sender).build(); - } + @Bean + Reporter scbZipkinReporter(DynamicProperties dynamicProperties, BytesMessageSender sender) { + String apiVersion = dynamicProperties.getStringProperty(CONFIG_TRACING_COLLECTOR_API_VERSION, + CONFIG_TRACING_COLLECTOR_API_V2).toLowerCase(); + if (apiVersion.compareTo(CONFIG_TRACING_COLLECTOR_API_V1) == 0) { + return AsyncReporter.builder(sender).build(SpanBytesEncoder.JSON_V1); + } + return AsyncReporter.builder(sender).build(); + } + } @Bean - Tracing tracing(Reporter reporter, DynamicProperties dynamicProperties, - CurrentTraceContext currentTraceContext) { - return Tracing.newBuilder() - .localServiceName(BootStrapProperties.readServiceName()) - .currentTraceContext(currentTraceContext) // puts trace IDs into logs - .spanReporter(reporter) + CurrentTraceContext scbCurrentTraceContext() { + return ThreadLocalCurrentTraceContext.newBuilder() + .addScopeDecorator(MDCScopeDecorator.newBuilder().build()) .build(); } @Bean - CurrentTraceContext currentTraceContext() { - return ThreadLocalCurrentTraceContext.newBuilder().addScopeDecorator(MDCScopeDecorator.create()).build(); + Tracing scbTracing(@Autowired(required = false) Sender sender, + CurrentTraceContext currentTraceContext, Environment environment, DynamicProperties dynamicProperties) { + Tracing.Builder builder = Tracing.newBuilder() + .localServiceName(BootStrapProperties.readServiceName(environment)) + .currentTraceContext(currentTraceContext); // puts trace IDs into logs + if (dynamicProperties.getBooleanProperty(TRACING_REPORTER_LOG_ENABLED, true)) { + builder.addSpanHandler(new LogSpanHandler()); + } + if (dynamicProperties.getBooleanProperty(TRACING_REPORTER_ZIPKIN_ENABLED, false)) { + builder.addSpanHandler(AsyncZipkinSpanHandler.create(sender)); + } + return builder.build(); + } + + @Bean + HttpTracing scbHttpTracing(Tracing tracing) { + return HttpTracing.newBuilder(tracing) + .clientRequestParser(new CustomHttpRequestParser()) + .clientResponseParser(new CustomHttpResponseParser()) + .serverRequestParser(new CustomHttpRequestParser()) + .serverResponseParser(new CustomHttpResponseParser()).build(); } @Bean - HttpTracing httpTracing(Tracing tracing) { - return HttpTracing.create(tracing); + ZipkinTracingFilter scbZipkinTracingFilter() { + return new ZipkinTracingFilter(); + } + + public static String createRequestPath(Invocation invocation) { + URIEndpointObject address = (URIEndpointObject) invocation.getEndpoint().getAddress(); + String urlPrefix = address.getFirst(DefinitionConst.URL_PREFIX); + RestOperationMeta swaggerRestOperation = invocation.getOperationMeta().getExtData(RestConst.SWAGGER_REST_OPERATION); + String path = (String) invocation.getHandlerContext().get(RestConst.REST_CLIENT_REQUEST_PATH); + if (path == null) { + try { + path = swaggerRestOperation.getPathBuilder().createRequestPath(invocation.getSwaggerArguments()); + } catch (Exception e) { + path = invocation.getOperationMeta().getOperationPath(); + } + } + + if (StringUtils.isEmpty(urlPrefix) || path.startsWith(urlPrefix)) { + return path; + } + + return urlPrefix + path; } } diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinConsumerDelegate.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinConsumerDelegate.java deleted file mode 100644 index 13ca8feabf6..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinConsumerDelegate.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.tracing.zipkin; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -import brave.Span; -import brave.Tracing; -import brave.http.HttpClientHandler; -import brave.http.HttpTracing; -import brave.propagation.Propagation.Setter; -import brave.propagation.TraceContext.Injector; - -class ZipkinConsumerDelegate implements ZipkinTracingDelegate { - - private final HttpClientHandler handler; - - private final HttpTracing httpTracing; - - private final Injector injector; - - @SuppressWarnings("unchecked") - ZipkinConsumerDelegate(HttpTracing httpTracing) { - this.httpTracing = httpTracing; - this.injector = httpTracing.tracing().propagation().injector(injector()); - this.handler = HttpClientHandler.create(httpTracing, new ConsumerInvocationAdapter()); - } - - @Override - public Span createSpan(Invocation invocation) { - return handler.handleSend(injector, invocation); - } - - @Override - public void onResponse(Span span, Response response, Throwable error) { - handler.handleReceive(response, error, span); - } - - @Override - public String name() { - return "Zipkin consumer"; - } - - @Override - public Tracing tracer() { - return httpTracing.tracing(); - } - - private Setter injector() { - return (invocation, key, value) -> invocation.getContext().put(key, value); - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinConsumerTracingHandler.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinConsumerTracingHandler.java deleted file mode 100644 index 7883134131a..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinConsumerTracingHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.tracing.zipkin; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; - -import brave.http.HttpTracing; - -public class ZipkinConsumerTracingHandler extends ZipkinTracingHandler { - - public ZipkinConsumerTracingHandler() { - this(new ZipkinConsumerDelegate(BeanUtils.getContext().getBean(HttpTracing.class))); - } - - private ZipkinConsumerTracingHandler(ZipkinTracingDelegate tracingHandler) { - super(tracingHandler); - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderDelegate.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderDelegate.java deleted file mode 100644 index 60b83bf859c..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderDelegate.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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.tracing.zipkin; - -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.StringUtils; - -import brave.Span; -import brave.Tracing; -import brave.http.HttpServerHandler; -import brave.http.HttpTracing; -import brave.propagation.Propagation.Getter; -import brave.propagation.TraceContext.Extractor; - -class ZipkinProviderDelegate implements ZipkinTracingDelegate { - private static final Logger LOG = LoggerFactory.getLogger(ZipkinProviderDelegate.class); - - private final HttpServerHandler handler; - - private final HttpTracing httpTracing; - - private final Extractor extractor; - - public static final String SPAN_ID_HEADER_NAME = "X-B3-SpanId"; - - public static final String TRACE_ID_HEADER_NAME = Const.TRACE_ID_NAME; - - private static final Getter INVOCATION_STRING_GETTER = (invocation, key) -> { - String extracted = invocation.getContext().get(key); - if (StringUtils.isEmpty(extracted) && SPAN_ID_HEADER_NAME.equals(key)) { - // use traceId as spanId to avoid brave's recreating traceId - extracted = invocation.getContext().get(TRACE_ID_HEADER_NAME); - LOG.debug("try to extract X-B3-SpanId, but the value is empty, replace with TraceId = [{}]", extracted); - } - return extracted; - }; - - @SuppressWarnings("unchecked") - ZipkinProviderDelegate(HttpTracing httpTracing) { - this.httpTracing = httpTracing; - this.extractor = httpTracing.tracing().propagation().extractor(extractor()); - this.handler = HttpServerHandler.create(httpTracing, new ProviderInvocationAdapter()); - } - - @Override - public Tracing tracer() { - return httpTracing.tracing(); - } - - @Override - public Span createSpan(Invocation invocation) { - return handler.handleReceive(extractor, invocation); - } - - @Override - public void onResponse(Span span, Response response, Throwable error) { - handler.handleSend(response, error, span); - } - - @Override - public String name() { - return "Zipkin provider"; - } - - private Getter extractor() { - return INVOCATION_STRING_GETTER; - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderTracingHandler.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderTracingHandler.java deleted file mode 100644 index abec4f33004..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderTracingHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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.tracing.zipkin; - -import org.apache.servicecomb.foundation.common.utils.BeanUtils; - -import brave.http.HttpTracing; - -public class ZipkinProviderTracingHandler extends ZipkinTracingHandler { - - public ZipkinProviderTracingHandler() { - this(new ZipkinProviderDelegate(BeanUtils.getContext().getBean(HttpTracing.class))); - } - - private ZipkinProviderTracingHandler(ZipkinProviderDelegate tracingHandler) { - super(tracingHandler); - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingDelegate.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingDelegate.java deleted file mode 100644 index 3761a8d8454..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingDelegate.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.tracing.zipkin; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.Response; - -import brave.Span; -import brave.Tracing; - -interface ZipkinTracingDelegate { - - Tracing tracer(); - - Span createSpan(Invocation invocation); - - void onResponse(Span span, Response response, Throwable error); - - String name(); -} diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingFilter.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingFilter.java index f896004ebad..f88532adf5e 100644 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingFilter.java +++ b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingFilter.java @@ -17,61 +17,113 @@ package org.apache.servicecomb.tracing.zipkin; -import static org.apache.servicecomb.swagger.invocation.InvocationType.PRODUCER; - -import java.util.concurrent.CompletableFuture; - -import javax.annotation.Nonnull; - import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.exception.Exceptions; -import org.apache.servicecomb.core.filter.Filter; -import org.apache.servicecomb.core.filter.FilterNode; -import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.core.event.InvocationFinishEvent; +import org.apache.servicecomb.core.event.InvocationStartEvent; +import org.apache.servicecomb.foundation.common.event.EventManager; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; + +import com.google.common.eventbus.Subscribe; import brave.Span; -import brave.Tracer.SpanInScope; +import brave.http.HttpClientHandler; +import brave.http.HttpClientRequest; +import brave.http.HttpClientResponse; +import brave.http.HttpServerHandler; +import brave.http.HttpServerRequest; +import brave.http.HttpServerResponse; import brave.http.HttpTracing; -@Component -public class ZipkinTracingFilter implements Filter { - public static final String NAME = "zipkin"; +public class ZipkinTracingFilter { + public static final String CONTEXT_TRACE_REQUEST = "x-trace-request"; + + public static final String CONTEXT_TRACE_HANDLER = "x-trace-handler"; - private ZipkinConsumerDelegate consumer; + public static final String CONTEXT_TRACE_SPAN = "x-trace-span"; - private ZipkinProviderDelegate producer; + public static final String CONTEXT_TRACE_EDGE_REQUEST = "x-trace-edge-request"; - @Nonnull - @Override - public String getName() { - return NAME; + public static final String CONTEXT_TRACE_EDGE_HANDLER = "x-trace-edge-handler"; + + public static final String CONTEXT_TRACE_EDGE_SPAN = "x-trace-edge-span"; + + private HttpTracing httpTracing; + + public ZipkinTracingFilter() { + EventManager.register(this); } @Autowired public void setHttpTracing(HttpTracing httpTracing) { - this.consumer = new ZipkinConsumerDelegate(httpTracing); - this.producer = new ZipkinProviderDelegate(httpTracing); + this.httpTracing = httpTracing; } - @SuppressWarnings({"try", "unused"}) - @Override - public CompletableFuture onFilter(Invocation invocation, FilterNode nextNode) { - ZipkinTracingDelegate tracing = collectTracing(invocation); + @Subscribe + public void onInvocationStartEvent(InvocationStartEvent event) { + Invocation invocation = event.getInvocation(); - Span span = tracing.createSpan(invocation); - try (SpanInScope scope = tracing.tracer().tracer().withSpanInScope(span)) { - return nextNode.onFilter(invocation) - .whenComplete((response, exception) -> tracing.onResponse(span, response, Exceptions.unwrap(exception))); + if (invocation.isProducer()) { + HttpServerHandler handler = HttpServerHandler.create(httpTracing); + HttpServeRequestWrapper request = new HttpServeRequestWrapper(invocation); + Span span = handler.handleReceive(request); + invocation.addLocalContext(CONTEXT_TRACE_SPAN, span); + invocation.addLocalContext(CONTEXT_TRACE_HANDLER, handler); + invocation.addLocalContext(CONTEXT_TRACE_REQUEST, request); + } else if (invocation.isConsumer()) { + Span parentSpan = invocation.getLocalContext(CONTEXT_TRACE_SPAN); + HttpClientHandler handler = HttpClientHandler.create(httpTracing); + HttpClientRequestWrapper request = new HttpClientRequestWrapper(invocation); + Span span = handler.handleSendWithParent(request, parentSpan == null ? null : parentSpan.context()); + invocation.addLocalContext(CONTEXT_TRACE_HANDLER, handler); + invocation.addLocalContext(CONTEXT_TRACE_REQUEST, request); + invocation.addLocalContext(CONTEXT_TRACE_SPAN, span); + } else { + // edge as server + HttpServerHandler serverHandler = HttpServerHandler.create(httpTracing); + HttpServeRequestWrapper serverRequest = new HttpServeRequestWrapper(invocation); + Span serverSpan = serverHandler.handleReceive(serverRequest); + invocation.addLocalContext(CONTEXT_TRACE_EDGE_SPAN, serverSpan); + invocation.addLocalContext(CONTEXT_TRACE_EDGE_HANDLER, serverHandler); + invocation.addLocalContext(CONTEXT_TRACE_EDGE_REQUEST, serverRequest); + + // edge as client + HttpClientHandler clientHandler = HttpClientHandler.create(httpTracing); + HttpClientRequestWrapper clientRequest = new HttpClientRequestWrapper(invocation); + Span clientSpan = clientHandler.handleSendWithParent(clientRequest, serverSpan.context()); + invocation.addLocalContext(CONTEXT_TRACE_HANDLER, clientHandler); + invocation.addLocalContext(CONTEXT_TRACE_REQUEST, clientRequest); + invocation.addLocalContext(CONTEXT_TRACE_SPAN, clientSpan); } } - private ZipkinTracingDelegate collectTracing(Invocation invocation) { - if (PRODUCER.equals(invocation.getInvocationType())) { - return producer; + @Subscribe + public void onInvocationFinishEvent(InvocationFinishEvent event) { + Invocation invocation = event.getInvocation(); + if (invocation.isProducer()) { + HttpServerHandler handler + = invocation.getLocalContext(CONTEXT_TRACE_HANDLER); + Span span = invocation.getLocalContext(CONTEXT_TRACE_SPAN); + handler.handleSend(new HttpServerResponseWrapper(invocation, event.getResponse(), + invocation.getLocalContext(CONTEXT_TRACE_REQUEST)), span); + } else if (invocation.isConsumer()) { + HttpClientHandler handler + = invocation.getLocalContext(CONTEXT_TRACE_HANDLER); + Span span = invocation.getLocalContext(CONTEXT_TRACE_SPAN); + handler.handleReceive(new HttpClientResponseWrapper(invocation, event.getResponse(), + invocation.getLocalContext(CONTEXT_TRACE_REQUEST)), span); + } else { + // edge as client + HttpClientHandler clientHandler + = invocation.getLocalContext(CONTEXT_TRACE_HANDLER); + Span clientSpan = invocation.getLocalContext(CONTEXT_TRACE_SPAN); + clientHandler.handleReceive(new HttpClientResponseWrapper(invocation, event.getResponse(), + invocation.getLocalContext(CONTEXT_TRACE_REQUEST)), clientSpan); + // edge as server + HttpServerHandler serverHandler + = invocation.getLocalContext(CONTEXT_TRACE_EDGE_HANDLER); + Span serverSpan = invocation.getLocalContext(CONTEXT_TRACE_EDGE_SPAN); + serverHandler.handleSend(new HttpServerResponseWrapper(invocation, event.getResponse(), + invocation.getLocalContext(CONTEXT_TRACE_EDGE_REQUEST)), serverSpan); } - - return consumer; } } diff --git a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingHandler.java b/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingHandler.java deleted file mode 100644 index 7990d0dfa28..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingHandler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.tracing.zipkin; - -import org.apache.servicecomb.core.Handler; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import brave.Span; -import brave.Tracer.SpanInScope; -import brave.Tracing; - -class ZipkinTracingHandler implements Handler { - - private static final Logger LOGGER = LoggerFactory.getLogger(ZipkinTracingHandler.class); - - private final Tracing tracer; - - private final ZipkinTracingDelegate tracingDelegate; - - ZipkinTracingHandler(ZipkinTracingDelegate tracingDelegate) { - this.tracer = tracingDelegate.tracer(); - this.tracingDelegate = tracingDelegate; - } - - @SuppressWarnings({"try", "unused"}) - @Override - public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception { - Span span = tracingDelegate.createSpan(invocation); - try (SpanInScope scope = tracer.tracer().withSpanInScope(span)) { - LOGGER.debug("{}: Generated tracing span for {}", - tracingDelegate.name(), - invocation.getOperationName()); - - invocation.next(onResponse(invocation, asyncResp, span)); - } catch (Exception e) { - LOGGER.debug("{}: Failed invocation on {}", - tracingDelegate.name(), - invocation.getOperationName(), - e); - - tracingDelegate.onResponse(span, null, e); - throw e; - } - } - - private AsyncResponse onResponse(Invocation invocation, AsyncResponse asyncResp, Span span) { - return response -> { - Throwable error = response.isFailed() ? response.getResult() : null; - tracingDelegate.onResponse(span, response, error); - - LOGGER.debug("{}: Completed invocation on {}", - tracingDelegate.name(), - invocation.getOperationName(), - error); - - asyncResp.handle(response); - }; - } -} diff --git a/handlers/handler-tracing-zipkin/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider b/handlers/handler-tracing-zipkin/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider deleted file mode 100644 index 400b61ec790..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/resources/META-INF/services/org.apache.servicecomb.core.filter.FilterProvider +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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.servicecomb.tracing.zipkin.ZipkinFilterProvider \ No newline at end of file diff --git a/handlers/handler-tracing-zipkin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/handlers/handler-tracing-zipkin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..f7edf1bb134 --- /dev/null +++ b/handlers/handler-tracing-zipkin/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.servicecomb.tracing.zipkin.TracingConfiguration diff --git a/handlers/handler-tracing-zipkin/src/main/resources/config/cse.handler.xml b/handlers/handler-tracing-zipkin/src/main/resources/config/cse.handler.xml deleted file mode 100644 index 713ce08f65d..00000000000 --- a/handlers/handler-tracing-zipkin/src/main/resources/config/cse.handler.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - diff --git a/handlers/handler-tracing-zipkin/src/test/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderDelegateTest.java b/handlers/handler-tracing-zipkin/src/test/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderDelegateTest.java deleted file mode 100644 index 1ff3f9866ba..00000000000 --- a/handlers/handler-tracing-zipkin/src/test/java/org/apache/servicecomb/tracing/zipkin/ZipkinProviderDelegateTest.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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.tracing.zipkin; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.core.Invocation; -import org.junit.Assert; -import org.junit.Test; -import org.mockito.Mockito; - -import brave.propagation.Propagation.Getter; -import mockit.Deencapsulation; - -public class ZipkinProviderDelegateTest { - @Test - public void testGetterOnGetSpanId() { - Getter getter = Deencapsulation - .getField(ZipkinProviderDelegate.class, "INVOCATION_STRING_GETTER"); - - Invocation invocation = Mockito.mock(Invocation.class); - Map context = new HashMap<>(); - - Mockito.when(invocation.getContext()).thenReturn(context); - - // if there is no spanId or traceId, then result is null - String spanId = getter.get(invocation, ZipkinProviderDelegate.SPAN_ID_HEADER_NAME); - Assert.assertNull(spanId); - - // if there is no spanId but traceId, then traceId will be returned as result - final String testTraceId = "testTraceId"; - context.put(ZipkinProviderDelegate.TRACE_ID_HEADER_NAME, testTraceId); - spanId = getter.get(invocation, ZipkinProviderDelegate.SPAN_ID_HEADER_NAME); - Assert.assertEquals(testTraceId, spanId); - - // if there is spanId, then spanId will be returned - final String testSpanId = "testSpanId"; - context.put(ZipkinProviderDelegate.SPAN_ID_HEADER_NAME, testSpanId); - spanId = getter.get(invocation, ZipkinProviderDelegate.SPAN_ID_HEADER_NAME); - Assert.assertEquals(testSpanId, spanId); - } - - @Test - public void testGetterOnGetOtherContent() { - Getter getter = Deencapsulation - .getField(ZipkinProviderDelegate.class, "INVOCATION_STRING_GETTER"); - - Invocation invocation = Mockito.mock(Invocation.class); - Map context = new HashMap<>(); - - Mockito.when(invocation.getContext()).thenReturn(context); - - final String key = "key"; - String value = getter.get(invocation, key); - Assert.assertNull(value); - - final String expectedValue = "value"; - context.put(key, expectedValue); - value = getter.get(invocation, key); - Assert.assertEquals(expectedValue, value); - } -} diff --git a/handlers/handler-tracing-zipkin/src/test/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingHandlerTest.java b/handlers/handler-tracing-zipkin/src/test/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingHandlerTest.java deleted file mode 100644 index ffe27ce5820..00000000000 --- a/handlers/handler-tracing-zipkin/src/test/java/org/apache/servicecomb/tracing/zipkin/ZipkinTracingHandlerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.tracing.zipkin; - -import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.swagger.invocation.Response; -import org.junit.Before; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Mockito; - -import brave.Span; -import brave.Tracing; - -public class ZipkinTracingHandlerTest { - - private final Invocation invocation = Mockito.mock(Invocation.class); - - private final Response response = Mockito.mock(Response.class); - - private final AsyncResponse asyncResponse = Mockito.mock(AsyncResponse.class); - - private final ZipkinTracingDelegate delegate = Mockito.mock(ZipkinTracingDelegate.class); - - private final Tracing tracing = Tracing.newBuilder().build(); - - private final Span span = Mockito.mock(Span.class); - - private final RuntimeException exception = new RuntimeException("oops"); - - private ZipkinTracingHandler tracingHandler; - - @Before - public void setUp() throws Exception { - when(delegate.tracer()).thenReturn(tracing); - when(delegate.createSpan(invocation)).thenReturn(span); - when(delegate.name()).thenReturn("delegate"); - - tracingHandler = new ZipkinTracingHandler(delegate); - } - - @Test - public void delegatesResponseAndHandleResponse() throws Exception { - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(AsyncResponse.class); - - tracingHandler.handle(invocation, asyncResponse); - - verify(invocation).next(argumentCaptor.capture()); - - argumentCaptor.getValue().handle(response); - - verify(asyncResponse).handle(response); - verify(delegate).onResponse(span, response, null); - } - - @Test - public void delegatesErrorResponseAndHandleResponse() throws Exception { - when(response.isFailed()).thenReturn(true); - when(response.getResult()).thenReturn(exception); - - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(AsyncResponse.class); - - tracingHandler.handle(invocation, asyncResponse); - - verify(invocation).next(argumentCaptor.capture()); - - argumentCaptor.getValue().handle(response); - - verify(asyncResponse).handle(response); - verify(delegate).onResponse(span, response, exception); - } - - @Test - public void delegatesErrorOnInvocationFailure() throws Exception { - doThrow(exception).when(invocation).next(any(AsyncResponse.class)); - - try { - tracingHandler.handle(invocation, asyncResponse); - expectFailing(RuntimeException.class); - } catch (Exception e) { - assertThat(e, is(exception)); - } - - verify(delegate).onResponse(span, null, exception); - } -} diff --git a/handlers/pom.xml b/handlers/pom.xml index b1652677e43..e74e2c95134 100644 --- a/handlers/pom.xml +++ b/handlers/pom.xml @@ -22,7 +22,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default 4.0.0 @@ -33,7 +33,6 @@ handler-tracing-zipkin - handler-bizkeeper handler-flowcontrol-qps handler-loadbalance handler-fault-injection diff --git a/huawei-cloud/darklaunch/pom.xml b/huawei-cloud/darklaunch/pom.xml index b300190c12f..b4396f87a64 100644 --- a/huawei-cloud/darklaunch/pom.xml +++ b/huawei-cloud/darklaunch/pom.xml @@ -21,7 +21,7 @@ huawei-cloud org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRule.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRule.java index 1ee8b0c18c8..988cd9e401f 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRule.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRule.java @@ -17,7 +17,7 @@ package org.apache.servicecomb.darklaunch; -import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -38,7 +38,7 @@ public class DarklaunchRule { private PolicyType policyType; - private List ruleItems = new ArrayList<>(); + private final List ruleItems = new ArrayList<>(); public static DarklaunchRule parse(String ruleStr) { if (StringUtils.isEmpty(ruleStr)) { @@ -47,7 +47,7 @@ public static DarklaunchRule parse(String ruleStr) { try { DarklaunchRuleJson ruleJson = JsonUtils - .readValue(ruleStr.getBytes(Charset.forName("UTF-8")), DarklaunchRuleJson.class); + .readValue(ruleStr.getBytes(StandardCharsets.UTF_8), DarklaunchRuleJson.class); DarklaunchRule rule = new DarklaunchRule(ruleJson.getPolicyType()); for (DarklaunchRuleItemJson itemJson : ruleJson.getRuleItems()) { DarklaunchRuleItem item = new DarklaunchRuleItem(itemJson.getGroupName()); @@ -89,4 +89,3 @@ public void addRuleItem(DarklaunchRuleItem ruleItem) { this.ruleItems.add(ruleItem); } } - diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRuleItem.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRuleItem.java index 21aec923770..a6ad1e8ccb1 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRuleItem.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchRuleItem.java @@ -30,7 +30,7 @@ public class DarklaunchRuleItem { private Condition policyCondition; - private List servers = new ArrayList(); + private final List servers = new ArrayList<>(); public DarklaunchRuleItem(String groupName) { this.groupName = groupName; diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchServerListFilter.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchServerListFilter.java index 8d9aea4c41e..d380a8f254c 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchServerListFilter.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/DarklaunchServerListFilter.java @@ -22,21 +22,17 @@ import java.util.Random; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; import org.apache.servicecomb.loadbalance.ServerListFilterExt; import org.apache.servicecomb.loadbalance.ServiceCombServer; -import org.apache.servicecomb.registry.api.registry.Microservice; - -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.DynamicStringProperty; public class DarklaunchServerListFilter implements ServerListFilterExt { - private static final String POLICY_CSE = "cse.darklaunch.policy.%s"; private static final String POLICY_SERVICE_COMB = "servicecomb.darklaunch.policy.%s"; private static final int HUNDRED = 100; - private Random random = new Random(); + private final Random random = new Random(); public DarklaunchServerListFilter() { } @@ -53,14 +49,8 @@ public boolean enabled() { @Override public List getFilteredListOfServers(List serverList, Invocation invocation) { - DynamicStringProperty ruleStr = DynamicPropertyFactory.getInstance().getStringProperty( - String.format(POLICY_SERVICE_COMB, invocation.getMicroserviceName()), null - ); - if (ruleStr == null) { - ruleStr = DynamicPropertyFactory.getInstance().getStringProperty( - String.format(POLICY_CSE, invocation.getMicroserviceName()), null); - } - DarklaunchRule rule = DarklaunchRule.parse(ruleStr.get()); + DarklaunchRule rule = DarklaunchRule.parse(LegacyPropertyFactory + .getStringProperty(String.format(POLICY_SERVICE_COMB, invocation.getMicroserviceName()))); if (rule == null) { return serverList; } @@ -110,8 +100,8 @@ private void divideServerGroup(List serverList, DarklaunchRul for (ServiceCombServer server : serverList) { boolean hasGroup = false; for (DarklaunchRuleItem item : rule.getRuleItems()) { - Microservice microservice = MicroserviceCache.getInstance().getService(server.getInstance().getServiceId()); - item.getGroupCondition().setActual(DarklaunchRule.PROP_VERSION, microservice.getVersion()); + item.getGroupCondition() + .setActual(DarklaunchRule.PROP_VERSION, server.getInstance().getVersion()); if (item.getGroupCondition().match()) { item.addServer(server); hasGroup = true; diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/MicroserviceCache.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/MicroserviceCache.java deleted file mode 100644 index cd29fde9848..00000000000 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/MicroserviceCache.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.darklaunch; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.serviceregistry.RegistryUtils; - -public final class MicroserviceCache { - private static MicroserviceCache instance = new MicroserviceCache(); - - private Map services = new HashMap<>(); - - private MicroserviceCache() { - } - - public static MicroserviceCache getInstance() { - return instance; - } - - public Microservice getService(String serviceId) { - Microservice microservice = services.computeIfAbsent(serviceId, (k) -> { - return RegistryUtils.getMicroservice(serviceId); - }); - return microservice; - } -} diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AbstractCondition.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AbstractCondition.java index c0c1f15e817..e257aa76333 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AbstractCondition.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AbstractCondition.java @@ -18,9 +18,9 @@ package org.apache.servicecomb.darklaunch.oper; public abstract class AbstractCondition implements Condition { - private String key; + private final String key; - private String expected; + private final String expected; private Object actual; @@ -67,16 +67,16 @@ protected void assertValueNotNull(String key, Object value) { public static int compareNum(Object num, String anotherNum) { try { if (num instanceof Integer) { - return ((Integer) num).compareTo(Integer.valueOf(anotherNum)); + return Integer.compare((Integer) num, Integer.parseInt(anotherNum)); } if (num instanceof Long) { - return ((Long) num).compareTo(Long.valueOf(anotherNum)); + return Long.compare((Long) num, Long.parseLong(anotherNum)); } if (num instanceof Double) { - return ((Double) num).compareTo(Double.valueOf(anotherNum)); + return Double.compare((Double) num, Double.parseDouble(anotherNum)); } if (num instanceof Float) { - return ((Float) num).compareTo(Float.valueOf(anotherNum)); + return Float.compare((Float) num, Float.parseFloat(anotherNum)); } } catch (NumberFormatException e) { return 1; diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AndCondition.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AndCondition.java index 4c0df0d0a7b..ccb033ef422 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AndCondition.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/AndCondition.java @@ -18,7 +18,7 @@ package org.apache.servicecomb.darklaunch.oper; public class AndCondition extends AbstractCondition { - private Condition[] conditions; + private final Condition[] conditions; public AndCondition(Condition... conditions) { super("and", "and"); diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/CaseInsensitiveCondition.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/CaseInsensitiveCondition.java index 81c9edfcea2..e47e17241bf 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/CaseInsensitiveCondition.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/CaseInsensitiveCondition.java @@ -18,7 +18,7 @@ package org.apache.servicecomb.darklaunch.oper; public class CaseInsensitiveCondition extends AbstractCondition { - private Condition condition; + private final Condition condition; public CaseInsensitiveCondition(Condition condition) { super(condition.key(), condition.expected()); diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/ConditionFactory.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/ConditionFactory.java index 2b18ac9f124..d7b410c35b8 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/ConditionFactory.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/ConditionFactory.java @@ -18,7 +18,6 @@ package org.apache.servicecomb.darklaunch.oper; import java.util.Arrays; -import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.servicecomb.darklaunch.DarklaunchRule; @@ -47,9 +46,7 @@ private static String[] split2Part(String str, String sep) { private static String[] split(String str, String sep) { return Arrays.stream(str.split(sep)) - .filter(s -> !StringUtils.isEmpty(s)) - .collect(Collectors.toList()) - .toArray(new String[0]); + .filter(s -> !StringUtils.isEmpty(s)).toArray(String[]::new); } public static Condition buildRateCondition(String strCondition) { diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/LikeCondition.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/LikeCondition.java index 08584eb4460..790ba9a57ad 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/LikeCondition.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/LikeCondition.java @@ -20,7 +20,7 @@ import java.util.regex.Pattern; public class LikeCondition extends AbstractCondition { - private Pattern pattern; + private final Pattern pattern; public LikeCondition(String key, String expected) { super(key, expected); @@ -46,9 +46,9 @@ public LikeCondition(String key, String expected) { @Override public boolean match() { SupportedType type = this.getType(); - if(type == SupportedType.STRING) { + if (type == SupportedType.STRING) { return this.pattern.matcher((String) this.getActual()).matches(); - } else{ + } else { return false; } } diff --git a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/OrCondition.java b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/OrCondition.java index 69073e60407..8c1374f8cc9 100644 --- a/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/OrCondition.java +++ b/huawei-cloud/darklaunch/src/main/java/org/apache/servicecomb/darklaunch/oper/OrCondition.java @@ -18,7 +18,7 @@ package org.apache.servicecomb.darklaunch.oper; public class OrCondition extends AbstractCondition { - private Condition[] conditions; + private final Condition[] conditions; public OrCondition(Condition... conditions) { super("or", "or"); diff --git a/huawei-cloud/darklaunch/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt b/huawei-cloud/darklaunch/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt index 6b7ea02f089..1104043c1cc 100644 --- a/huawei-cloud/darklaunch/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt +++ b/huawei-cloud/darklaunch/src/main/resources/META-INF/services/org.apache.servicecomb.loadbalance.ServerListFilterExt @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.darklaunch.DarklaunchServerListFilter \ No newline at end of file +org.apache.servicecomb.darklaunch.DarklaunchServerListFilter diff --git a/huawei-cloud/dashboard/pom.xml b/huawei-cloud/dashboard/pom.xml index cef408940d4..015a43a240a 100644 --- a/huawei-cloud/dashboard/pom.xml +++ b/huawei-cloud/dashboard/pom.xml @@ -21,7 +21,7 @@ huawei-cloud org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 @@ -33,19 +33,23 @@ org.apache.servicecomb - deployment + java-chassis-core org.apache.servicecomb - java-chassis-core + registry-service-center org.apache.servicecomb - registry-service-center + dashboard-client + + - com.netflix.hystrix - hystrix-core + org.apache.servicecomb + metrics-core + provided + - \ No newline at end of file + diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java deleted file mode 100644 index 99eadcf91da..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/AddressManager.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor; - - -import java.util.ArrayList; -import java.util.List; - -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.serviceregistry.RegistryUtils; - - -public class AddressManager { - private static final String MONITOR_SERVICE_NAME = "CseMonitoring"; - - private static final String MONITOR_APPLICATION = "default"; - - private static final String MONITOR_VERSION = "latest"; - - private final List addresses = new ArrayList<>(); - - private int index = 0; - - AddressManager() { - updateAddresses(); - updateServersFromSC(); - EventManager.register(this); - } - - private void updateAddresses() { - SystemBootstrapInfo info = Deployment.getSystemBootStrapInfo( - MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE); - if (info != null && info.getAccessURL() != null) { - addresses.addAll(info.getAccessURL()); - } - } - - String nextServer() { - if (addresses.size() == 0) { - return null; - } - synchronized (this) { - this.index++; - if (this.index >= addresses.size()) { - this.index = 0; - } - return addresses.get(index); - } - } - - private void updateServersFromSC() { - List servers = RegistryUtils.findServiceInstance(MONITOR_APPLICATION, - MONITOR_SERVICE_NAME, - MONITOR_VERSION); - if (servers != null) { - for (MicroserviceInstance server : servers) { - for (String endpoint : server.getEndpoints()) { - if (!addresses.contains(endpoint)) { - addresses.add(endpoint); - } - } - } - } - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/ConsoleMonitorDataPublisher.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/ConsoleMonitorDataPublisher.java deleted file mode 100644 index 324f23d977c..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/ConsoleMonitorDataPublisher.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor; - -import io.vertx.core.json.Json; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.event.ConsoleMonitorDataEvent; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDaraProvider; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ConsoleMonitorDataPublisher implements MonitorDataPublisher { - private static final int END_INDEX = 100; - - private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleMonitorDataPublisher.class); - - @Override - public void publish(MonitorDaraProvider provider) { - Object data = provider.getData(); - if (data == null) { - return; - } - String reqString = Json.encode(data); - LOGGER.info(reqString.length() > END_INDEX ? reqString.substring(0, END_INDEX) : reqString); - EventManager.post(new ConsoleMonitorDataEvent(reqString)); - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DashboardConfiguration.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DashboardConfiguration.java new file mode 100644 index 00000000000..328b6bf6e02 --- /dev/null +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DashboardConfiguration.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.huaweicloud.dashboard.monitor; + +import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; + +@Configuration +public class DashboardConfiguration { + @Bean + public MonitorInformationCollector scbMonitorInformationCollector() { + return new MonitorInformationCollector(); + } + + @Bean + public MonitorConstant scbMonitorConstant(Environment environment) { + return new MonitorConstant(environment); + } + + @Bean + public MonitorBootListener scbMonitorBootListener() { + return new MonitorBootListener(); + } + + @Bean + public DataFactory scbDataFactory() { + return new DataFactory(); + } + + @Bean + public MetricsMonitorDataProvider scbMetricsMonitorDataProvider() { + return new MetricsMonitorDataProvider(); + } + + @Bean + public DefaultMonitorDataPublisher scbDefaultMonitorDataPublisher() { + return new DefaultMonitorDataPublisher(); + } +} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DataFactory.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DataFactory.java index a2c857825a4..4889683c131 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DataFactory.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DataFactory.java @@ -17,20 +17,21 @@ package org.apache.servicecomb.huaweicloud.dashboard.monitor; -import io.netty.util.concurrent.DefaultThreadFactory; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDaraProvider; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.inject.Inject; import java.util.List; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataProvider; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataPublisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; + +import io.netty.util.concurrent.DefaultThreadFactory; + public class DataFactory { private static final Logger LOGGER = LoggerFactory.getLogger(DataFactory.class); @@ -38,12 +39,15 @@ public class DataFactory { private boolean hasStart = false; - @Inject - private List dataProviders; + @Autowired + private List dataProviders; - @Inject + @Autowired private MonitorDataPublisher publisher; + @Autowired + private MonitorConstant monitorConstant; + private ScheduledExecutorService executorService = null; @@ -52,7 +56,7 @@ public DataFactory() { executorService = Executors.newScheduledThreadPool(CORE_SIZE, threadFactory); } - public void setMonitorDataProviders(List dataProviders) { + public void setMonitorDataProviders(List dataProviders) { this.dataProviders = dataProviders; } @@ -66,7 +70,7 @@ void start() { StringBuilder sb = new StringBuilder(); sb.append("Monitor data sender started. Configured data providers is {"); - for (MonitorDaraProvider provider : dataProviders) { + for (MonitorDataProvider provider : dataProviders) { sb.append(provider.getClass().getName()); sb.append(","); } @@ -79,19 +83,16 @@ void start() { } catch (Throwable e) { LOGGER.error("send monitor data error.", e); } - }, MonitorConstant.getInterval(), MonitorConstant.getInterval(), TimeUnit.MILLISECONDS); + }, monitorConstant.getInterval(), monitorConstant.getInterval(), TimeUnit.MILLISECONDS); hasStart = true; } } void sendData() { - if (!MonitorConstant.isMonitorEnabled()) { - return; - } - - for (MonitorDaraProvider provider : this.dataProviders) { - this.publisher.publish(provider); + for (MonitorDataProvider provider : this.dataProviders) { + if (provider.enabled()) { + this.publisher.publish(provider); + } } } - } diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java index 18ff61a2be8..1209d9d8532 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/DefaultMonitorDataPublisher.java @@ -18,158 +18,119 @@ package org.apache.servicecomb.huaweicloud.dashboard.monitor; import java.util.HashMap; - -import org.apache.commons.io.IOUtils; -import org.apache.servicecomb.foundation.auth.SignRequest; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.servicecomb.config.ConfigUtil; +import org.apache.servicecomb.dashboard.client.DashboardAddressManager; +import org.apache.servicecomb.dashboard.client.DashboardClient; +import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.foundation.common.net.IpPort; -import org.apache.servicecomb.foundation.common.net.NetUtils; -import org.apache.servicecomb.foundation.ssl.SSLCustom; -import org.apache.servicecomb.foundation.ssl.SSLOption; -import org.apache.servicecomb.foundation.ssl.SSLOptionFactory; -import org.apache.servicecomb.foundation.vertx.AddressResolverConfig; -import org.apache.servicecomb.foundation.vertx.VertxTLSBuilder; -import org.apache.servicecomb.foundation.vertx.VertxUtils; -import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager; -import org.apache.servicecomb.foundation.vertx.client.ClientVerticle; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClientPoolFactory; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.http.client.auth.RequestAuthHeaderProvider; +import org.apache.servicecomb.http.client.common.HttpTransport; +import org.apache.servicecomb.http.client.common.HttpTransportFactory; import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.event.MonitorFailEvent; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.event.MonitorSuccEvent; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDaraProvider; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataProvider; import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataPublisher; -import org.apache.servicecomb.serviceregistry.RegistryUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import io.netty.handler.codec.http.HttpResponseStatus; -import io.vertx.core.DeploymentOptions; -import io.vertx.core.Future; -import io.vertx.core.Vertx; -import io.vertx.core.VertxOptions; -import io.vertx.core.http.HttpClientOptions; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.Json; -import io.vertx.core.net.ProxyOptions; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; public class DefaultMonitorDataPublisher implements MonitorDataPublisher { - private static final Logger LOGGER = LoggerFactory.getLogger(DefaultMonitorDataPublisher.class); - private static final String SSL_KEY = "mc.consumer"; - private static final int MAX_WAIT_QUEUE_SIZE = 50; + private DashboardClient dashboardClient; - private static ClientPoolManager clientMgr; + private MonitorConstant monitorConstant; - private AddressManager addressManager; + private Environment environment; - @Override - public void init() { - try { - addressManager = new AddressManager(); - deployMonitorClient(); - } catch (Exception e) { - LOGGER.warn("Deploy monitor data publisher failed will not send monitor data."); - } + @Autowired + public void setMonitorConstant(MonitorConstant monitorConstant) { + this.monitorConstant = monitorConstant; + } + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; } @Override - public void publish(MonitorDaraProvider provider) { - Object data = provider.getData(); - if (data == null) { - return; - } - String endpoint = addressManager.nextServer(); - if (endpoint == null) { - return; - } + public void init() { + DashboardAddressManager addressManager = createDashboardAddressManager(); - String jasonData = Json.encode(data); - String url = provider.getURL(); - IpPort host = NetUtils.parseIpPortFromURI(endpoint); + RequestConfig.Builder requestBuilder = HttpTransportFactory.defaultRequestConfig(); + requestBuilder.setConnectionRequestTimeout(1000); + requestBuilder.setSocketTimeout(10000); - doSend(endpoint, jasonData, url, host, 0); - } + HttpTransport httpTransport = createHttpTransport(addressManager, requestBuilder.build(), + environment); - private void doSend(String endpoint, String jsonData, String url, IpPort host, int times) { - clientMgr.findThreadBindClientPool().runOnContext(client -> { - client.request(HttpMethod.POST, host.getPort(), host.getHostOrIp(), url).compose(request -> { - request.headers().add("environment", RegistryUtils.getMicroservice().getEnvironment()); - request.setTimeout(MonitorConstant.getInterval() / MonitorConstant.MAX_RETRY_TIMES); - try { - SignRequest signReq = SignUtil.createSignRequest(request.getMethod().toString(), - endpoint + url, - new HashMap<>(), - IOUtils.toInputStream(jsonData, "UTF-8")); - SignUtil.getAuthHeaderProviders().forEach(authHeaderProvider -> { - request.headers().addAll(authHeaderProvider.getSignAuthHeaders(signReq)); - }); - } catch (Exception e) { - LOGGER.error("sign request error!", e); - } - return request.send(jsonData).compose(rsp -> { - if (rsp.statusCode() != HttpResponseStatus.OK.code()) { - if (times < MonitorConstant.MAX_RETRY_TIMES - && rsp.statusCode() == HttpResponseStatus.BAD_GATEWAY.code()) { - doSend(endpoint, jsonData, url, host, times + 1); - return Future.succeededFuture(); - } - return rsp.body().compose(buffer -> { - LOGGER.warn("Send data to url {} failed and status line is {}", - url, - rsp.statusCode()); - LOGGER.warn("message: {}", buffer); - return Future.succeededFuture(); - }); - } else { - EventManager.post(new MonitorSuccEvent()); - } - return Future.succeededFuture(); - }).onFailure(failure -> { - EventManager.post(new MonitorFailEvent("send monitor data fail.")); - LOGGER.warn("Send monitor data to {} failed , {}", endpoint, failure); - }); - }); - }); + dashboardClient = new DashboardClient(addressManager, httpTransport); } - private void deployMonitorClient() throws InterruptedException { - VertxOptions vertxOptions = new VertxOptions(); - vertxOptions.setAddressResolverOptions(AddressResolverConfig.getAddressResover(SSL_KEY)); - Vertx vertx = VertxUtils.getOrCreateVertxByName("monitor-center", vertxOptions); + @SuppressWarnings("unchecked") + private DashboardAddressManager createDashboardAddressManager() { + List addresses = ConfigUtil.parseArrayValue( + environment.getProperty(MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE, "")); - HttpClientOptions httpClientOptions = createHttpClientOptions(); - httpClientOptions.setMaxWaitQueueSize(MAX_WAIT_QUEUE_SIZE); - clientMgr = new ClientPoolManager<>(vertx, new HttpClientPoolFactory(httpClientOptions)); + if (addresses.isEmpty()) { + throw new IllegalStateException("dashboard address is not configured."); + } + String region = environment.getProperty("servicecomb.datacenter.region"); + String availableZone = environment.getProperty("servicecomb.datacenter.availableZone"); - DeploymentOptions deploymentOptions = VertxUtils.createClientDeployOptions(clientMgr, 1); - VertxUtils.blockDeploy(vertx, ClientVerticle.class, deploymentOptions); + return new DashboardAddressManager(addresses, EventManager.getEventBus(), region, availableZone); } - private HttpClientOptions createHttpClientOptions() { - HttpClientOptions httpClientOptions = new HttpClientOptions(); - if (MonitorConstant.isProxyEnable()) { - ProxyOptions proxy = new ProxyOptions(); - proxy.setHost(MonitorConstant.getProxyHost()); - proxy.setPort(MonitorConstant.getProxyPort()); - proxy.setUsername(MonitorConstant.getProxyUsername()); - proxy.setPassword(MonitorConstant.getProxyPasswd()); - httpClientOptions.setProxyOptions(proxy); + private HttpTransport createHttpTransport(DashboardAddressManager addressManager, RequestConfig requestConfig, + Environment environment) { + List authHeaderProviders = SPIServiceUtils.getOrLoadSortedService(AuthHeaderProvider.class); + + if (monitorConstant.isProxyEnable()) { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(). + setDefaultRequestConfig(requestConfig); + HttpHost proxy = new HttpHost(monitorConstant.getProxyHost(), + monitorConstant.getProxyPort(), "http"); // now only support http proxy + httpClientBuilder.setProxy(proxy); + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(proxy), + new UsernamePasswordCredentials(monitorConstant.getProxyUsername(), + monitorConstant.getProxyPasswd())); + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + + return HttpTransportFactory + .createHttpTransport( + TransportUtils + .createSSLProperties(addressManager.sslEnabled(), environment, SSL_KEY), + getRequestAuthHeaderProvider(authHeaderProviders), httpClientBuilder); } - httpClientOptions.setConnectTimeout(MonitorConstant.getConnectionTimeout()); - if (MonitorConstant.sslEnabled()) { - SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory(SSL_KEY, null); - SSLOption sslOption; - if (factory == null) { - sslOption = SSLOption.buildFromYaml(SSL_KEY); - } else { - sslOption = factory.createSSLOption(); - } - SSLCustom sslCustom = SSLCustom.createSSLCustom(sslOption.getSslCustomClass()); - VertxTLSBuilder.buildHttpClientOptions(sslOption, sslCustom, httpClientOptions); - } - return httpClientOptions; + return HttpTransportFactory + .createHttpTransport( + TransportUtils + .createSSLProperties(monitorConstant.sslEnabled(), environment, SSL_KEY), + getRequestAuthHeaderProvider(authHeaderProviders), requestConfig); + } + + private static RequestAuthHeaderProvider getRequestAuthHeaderProvider(List authHeaderProviders) { + return signRequest -> { + String host = signRequest != null && signRequest.getEndpoint() != null ? signRequest.getEndpoint().getHost() : ""; + Map headers = new HashMap<>(); + authHeaderProviders.forEach(provider -> headers.putAll(provider.authHeaders(host))); + return headers; + }; + } + + @Override + public void publish(MonitorDataProvider provider) { + dashboardClient.sendData(provider.getURL(), provider.getData()); } } diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/HealthMonitorDataProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/HealthMonitorDataProvider.java deleted file mode 100644 index 7fa7f98623e..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/HealthMonitorDataProvider.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor; - -import com.google.common.eventbus.Subscribe; -import com.netflix.hystrix.HystrixCommandMetrics; -import org.apache.servicecomb.foundation.common.event.EventManager; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.CPUMonitorCalc; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.Diagnosis; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorData; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDaraProvider; -import org.apache.servicecomb.registry.DiscoveryManager; -import org.apache.servicecomb.registry.api.registry.Microservice; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.apache.servicecomb.serviceregistry.RegistryUtils; -import org.apache.servicecomb.serviceregistry.diagnosis.instance.InstanceCacheChecker; -import org.apache.servicecomb.serviceregistry.diagnosis.instance.InstanceCacheSummary; - -import javax.annotation.PostConstruct; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryMXBean; -import java.lang.management.MemoryUsage; -import java.lang.management.OperatingSystemMXBean; -import java.lang.management.RuntimeMXBean; -import java.lang.management.ThreadMXBean; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class HealthMonitorDataProvider implements MonitorDaraProvider { - - private InstanceCacheSummary instanceCacheSummary; - - private Object lock = new Object(); - - @Override - public String getURL() { - return String.format(MonitorConstant.MONITORS_URI, RegistryUtils.getMicroservice().getServiceName()); - } - - @Override - public Object getData() { - return getMonitorData(); - } - - @PostConstruct - public void init() { - EventManager.register(this); - } - - @Subscribe - public void subCacheCheck(InstanceCacheSummary instanceCacheSummary) { - synchronized (lock) { - this.instanceCacheSummary = instanceCacheSummary; - } - } - - private MonitorData getMonitorData() { - Collection instances = HystrixCommandMetrics.getInstances(); - MonitorData monitorData = new MonitorData(); - Microservice microservice = RegistryUtils.getMicroservice(); - MicroserviceInstance microserviceInstance = RegistryUtils.getMicroserviceInstance(); - monitorData.setAppId(microservice.getAppId()); - monitorData.setName(microservice.getServiceName()); - monitorData.setVersion(microservice.getVersion()); - monitorData.setServiceId(microservice.getServiceId()); - monitorData.setInstance(microserviceInstance.getHostName()); - monitorData.setInstanceId(microserviceInstance.getInstanceId()); - - if (MonitorConstant.insCacheEnabled()) { - InstanceCacheChecker checker = new InstanceCacheChecker(DiscoveryManager.INSTANCE.getAppManager()); - monitorData.setProvidersCache(checker.check().getProducers()); - } - exactProcessInfo(monitorData); - synchronized (lock) { - if (this.instanceCacheSummary != null) { - Diagnosis diagnosis = new Diagnosis(); - diagnosis.setInstanceCache(instanceCacheSummary); - monitorData.setDiagnosis(diagnosis); - this.instanceCacheSummary = null; - } - } - - if (instances.isEmpty()) { - return monitorData; - } - for (HystrixCommandMetrics instance : instances) { - monitorData.appendInterfaceInfo(instance); - } - return monitorData; - } - - private void exactProcessInfo(MonitorData monitorData) { - MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); - MemoryUsage memoryHeapUsage = memoryMXBean.getHeapMemoryUsage(); - MemoryUsage memoryNonHeapUsage = memoryMXBean.getNonHeapMemoryUsage(); - ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); - RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); - int threadCount = threadMXBean.getThreadCount(); - OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); - - double cpu = operatingSystemMXBean.getSystemLoadAverage(); - monitorData.setCpu(CPUMonitorCalc.getInstance().getProcessCpu()); - monitorData.setLoadAverage(cpu); - monitorData.setThreadCount(threadCount); - monitorData.setUptime(runtimeMXBean.getUptime()); - - Map memoryInfo = new HashMap<>(); - memoryInfo.put("heapInit", memoryHeapUsage.getInit()); - memoryInfo.put("headMax", memoryHeapUsage.getMax()); - memoryInfo.put("heapCommit", memoryHeapUsage.getCommitted()); - memoryInfo.put("heapUsed", memoryHeapUsage.getUsed()); - memoryInfo.put("nonHeapInit", memoryNonHeapUsage.getInit()); - memoryInfo.put("nonHeapCommit", memoryNonHeapUsage.getCommitted()); - memoryInfo.put("nonHeapUsed", memoryNonHeapUsage.getUsed()); - monitorData.setMemory(memoryInfo); - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java new file mode 100644 index 00000000000..ed54eef341e --- /dev/null +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProvider.java @@ -0,0 +1,242 @@ +/* + * 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.huaweicloud.dashboard.monitor; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.servicecomb.core.invocation.InvocationStageTrace; +import org.apache.servicecomb.dashboard.client.model.InterfaceInfo; +import org.apache.servicecomb.dashboard.client.model.MonitorData; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.metrics.PolledEvent; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.model.MonitorDataProvider; +import org.apache.servicecomb.metrics.core.publish.PublishModelFactory; +import org.apache.servicecomb.metrics.core.publish.model.DefaultPublishModel; +import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerf; +import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroup; +import org.apache.servicecomb.metrics.core.publish.model.invocation.OperationPerfGroups; +import org.apache.servicecomb.metrics.core.publish.model.invocation.PerfInfo; +import org.apache.servicecomb.registry.sc.SCRegistration; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; + +import com.google.common.eventbus.Subscribe; + +import io.micrometer.core.instrument.Meter; + +/** + * Monitor data based on metrics-core module. + */ +public class MetricsMonitorDataProvider implements MonitorDataProvider { + + public static final String CODE_SUCCESS = "2[0-9]{2}"; + + public static final String CODE_TIMEOUT = "408"; + + public static final String NAME_PROVIDER = "Provider."; + + public static final String NAME_CONSUMER = "Consumer."; + + private volatile List meters = null; + + private SCRegistration scRegistration; + + private Environment environment; + + private MonitorConstant monitorConstant; + + public MetricsMonitorDataProvider() { + EventManager.register(this); + } + + @Autowired + public void setSCRegistration(SCRegistration scRegistration) { + this.scRegistration = scRegistration; + } + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + + @Autowired + public void setMonitorConstant(MonitorConstant monitorConstant) { + this.monitorConstant = monitorConstant; + } + + @Override + public boolean enabled() { + return environment.getProperty("servicecomb.monitor.provider.metrics.enabled", boolean.class, true); + } + + @Override + public String getURL() { + return String.format(monitorConstant.getMonitorUri(), scRegistration.getMicroserviceInstance().getServiceName()); + } + + @Override + public void extractServiceInfo(MonitorData monitorData) { + monitorData.setAppId(scRegistration.getMicroserviceInstance().getApplication()); + monitorData.setName(scRegistration.getMicroserviceInstance().getServiceName()); + monitorData.setVersion(scRegistration.getMicroserviceInstance().getVersion()); + monitorData.setServiceId(scRegistration.getMicroserviceInstance().getBackendMicroservice().getServiceId()); + monitorData.setInstance(scRegistration.getMicroserviceInstance().getBackendMicroserviceInstance().getHostName()); + monitorData.setInstanceId(scRegistration.getMicroserviceInstance().getInstanceId()); + monitorData.setEnvironment(scRegistration.getMicroserviceInstance().getEnvironment()); + } + + @Override + public void extractInterfaceInfo(MonitorData monitorData) { + if (meters == null) { + return; + } + PublishModelFactory factory = new PublishModelFactory(meters); + DefaultPublishModel model = factory.createDefaultPublishModel(); + + Map combinedResults = new HashMap<>(); + extractProviderInfo(model, combinedResults); + extractConsumerInfo(model, combinedResults); + extractEdgeInfo(model, combinedResults); + combinedResults.forEach((k, v) -> { + v.setFailureRate(v.getTotal() == 0 ? 0 : v.getFailure() / (double) v.getTotal()); + monitorData.addInterfaceInfo(v); + }); + } + + private void extractProviderInfo(DefaultPublishModel model, Map combinedResults) { + OperationPerfGroups producerPerf = model.getProducer().getOperationPerfGroups(); + if (producerPerf == null) { + return; + } + + for (Map statusMap : producerPerf.getGroups().values()) { + for (OperationPerfGroup perfGroup : statusMap.values()) { + for (int i = 0; i < perfGroup.getOperationPerfs().size(); i++) { + OperationPerf operationPerf = perfGroup.getOperationPerfs().get(i); + PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL); + String name = NAME_PROVIDER + operationPerf.getOperation(); + InterfaceInfo interfaceInfo = combinedResults.computeIfAbsent(name, + k -> { + InterfaceInfo obj = new InterfaceInfo(); + obj.setName(name); + return obj; + }); + // dashboard calculates the latest 10 seconds, different with metrics cycle. + interfaceInfo.setTotal( + doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests())); + if (perfGroup.getStatus().matches(CODE_SUCCESS)) { + interfaceInfo.setQps(stageTotal.getTotalRequests() / 10); + interfaceInfo.setLatency(doubleToInt(stageTotal.calcMsLatency())); + } else { + interfaceInfo.setFailure( + doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests())); + if (perfGroup.getStatus().equals(CODE_TIMEOUT)) { + interfaceInfo.setCountTimeout( + doubleToInt(interfaceInfo.getCountTimeout() + stageTotal.getTotalRequests())); + } + } + } + } + } + } + + private void extractEdgeInfo(DefaultPublishModel model, Map combinedResults) { + OperationPerfGroups edgePerf = model.getEdge().getOperationPerfGroups(); + if (edgePerf == null) { + return; + } + for (Map statusMap : edgePerf.getGroups().values()) { + for (OperationPerfGroup perfGroup : statusMap.values()) { + for (int i = 0; i < perfGroup.getOperationPerfs().size(); i++) { + OperationPerf operationPerf = perfGroup.getOperationPerfs().get(i); + PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL); + String name = NAME_CONSUMER + operationPerf.getOperation(); + InterfaceInfo interfaceInfo = combinedResults.computeIfAbsent(name, + k -> { + InterfaceInfo obj = new InterfaceInfo(); + obj.setName(name); + return obj; + }); + // dashboard calculates the latest 10 seconds, different with metrics cycle. + interfaceInfo.setTotal( + doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests())); + if (perfGroup.getStatus().matches(CODE_SUCCESS)) { + interfaceInfo.setQps(stageTotal.getTotalRequests() / 10); + interfaceInfo.setLatency(doubleToInt(stageTotal.calcMsLatency())); + } else { + interfaceInfo.setFailure( + doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests())); + if (perfGroup.getStatus().equals(CODE_TIMEOUT)) { + interfaceInfo.setCountTimeout( + doubleToInt( + interfaceInfo.getCountTimeout() + stageTotal.getTotalRequests())); + } + } + } + } + } + } + + private void extractConsumerInfo(DefaultPublishModel model, Map combinedResults) { + OperationPerfGroups consumerPerf = model.getConsumer().getOperationPerfGroups(); + if (consumerPerf == null) { + return; + } + for (Map statusMap : consumerPerf.getGroups().values()) { + for (OperationPerfGroup perfGroup : statusMap.values()) { + for (int i = 0; i < perfGroup.getOperationPerfs().size(); i++) { + OperationPerf operationPerf = perfGroup.getOperationPerfs().get(i); + PerfInfo stageTotal = operationPerf.findStage(InvocationStageTrace.STAGE_TOTAL); + String name = NAME_CONSUMER + operationPerf.getOperation(); + InterfaceInfo interfaceInfo = combinedResults.computeIfAbsent(name, + k -> { + InterfaceInfo obj = new InterfaceInfo(); + obj.setName(name); + return obj; + }); + // dashboard calculates the latest 10 seconds, different with metrics cycle. + interfaceInfo.setTotal( + doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests())); + if (perfGroup.getStatus().matches(CODE_SUCCESS)) { + interfaceInfo.setQps(stageTotal.getTotalRequests() / 10); + interfaceInfo.setLatency(doubleToInt(stageTotal.calcMsLatency())); + } else { + interfaceInfo.setFailure( + doubleToInt(interfaceInfo.getTotal() + stageTotal.getTotalRequests())); + if (perfGroup.getStatus().equals(CODE_TIMEOUT)) { + interfaceInfo.setCountTimeout( + doubleToInt( + interfaceInfo.getCountTimeout() + stageTotal.getTotalRequests())); + } + } + } + } + } + } + + private int doubleToInt(Double d) { + return d.intValue(); + } + + @Subscribe + public void onPolledEvent(PolledEvent event) { + this.meters = event.getMeters(); + } +} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorBootListener.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorBootListener.java index 2ae7f21640a..06dd4aa6d63 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorBootListener.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorBootListener.java @@ -18,16 +18,23 @@ package org.apache.servicecomb.huaweicloud.dashboard.monitor; import org.apache.servicecomb.core.BootListener; - -import javax.inject.Inject; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; +import org.springframework.beans.factory.annotation.Autowired; public class MonitorBootListener implements BootListener { - @Inject + @Autowired private DataFactory dataFactory; + @Autowired + private MonitorConstant monitorConstant; + @Override public void onBootEvent(BootEvent event) { + if (!monitorConstant.isMonitorEnabled()) { + return; + } + if (EventType.AFTER_REGISTRY == event.getEventType()) { dataFactory.start(); } diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorDefaultDeploymentProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorDefaultDeploymentProvider.java deleted file mode 100644 index 35a5ff23270..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorDefaultDeploymentProvider.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor; - -import java.util.List; - -import org.apache.commons.configuration.AbstractConfiguration; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.deployment.DeploymentProvider; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; -import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; - -import com.google.common.annotations.VisibleForTesting; - -public class MonitorDefaultDeploymentProvider implements DeploymentProvider { - private static AbstractConfiguration configuration = ConfigUtil.createLocalConfig(); - - @Override - public int getOrder() { - return 3; - } - - @Override - public SystemBootstrapInfo getSystemBootStrapInfo(String systemKey) { - if (!systemKey.equals(MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE)) { - return null; - } - List msAddresses = ConfigUtil.parseArrayValue(configuration.getString(MonitorConstant.MONITOR_URI)); - if (msAddresses.isEmpty()) { - return null; - } - SystemBootstrapInfo ms = new SystemBootstrapInfo(); - ms.setAccessURL(msAddresses); - return ms; - } - - @VisibleForTesting - public static void setConfiguration(AbstractConfiguration configuration) { - MonitorDefaultDeploymentProvider.configuration = configuration; - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorInformationCollector.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorInformationCollector.java index 30f765d3034..ef8b03a1368 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorInformationCollector.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MonitorInformationCollector.java @@ -17,25 +17,29 @@ package org.apache.servicecomb.huaweicloud.dashboard.monitor; +import org.apache.servicecomb.config.ConfigUtil; import org.apache.servicecomb.core.bootup.BootUpInformationCollector; -import org.apache.servicecomb.deployment.Deployment; -import org.apache.servicecomb.deployment.SystemBootstrapInfo; import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.MonitorConstant; - -import java.util.Objects; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; public class MonitorInformationCollector implements BootUpInformationCollector { + private Environment environment; + + @Autowired + public void setEnvironment(Environment environment) { + this.environment = environment; + } + @Override public String collect() { - return "monitor center: " + getCenterInfo(Deployment.getSystemBootStrapInfo(MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE)); + return "monitor center: " + + ConfigUtil.parseArrayValue( + environment.getProperty(MonitorConstant.SYSTEM_KEY_DASHBOARD_SERVICE, "")); } @Override public int getOrder() { return 100; } - - private String getCenterInfo(SystemBootstrapInfo systemBootstrapInfo) { - return Objects.isNull(systemBootstrapInfo) ? "not exist" : systemBootstrapInfo.getAccessURL().toString(); - } } diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/SignUtil.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/SignUtil.java deleted file mode 100644 index b950f06b398..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/SignUtil.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor; - -import org.apache.commons.lang.StringUtils; -import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; -import org.apache.servicecomb.foundation.auth.SignRequest; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class SignUtil { - private static final Logger LOGGER = LoggerFactory.getLogger(SignUtil.class); - - private static List authHeaderProviders = SPIServiceUtils. - getSortedService(AuthHeaderProvider.class); - - public static SignRequest createSignRequest(String method, String endpoint, Map - headers, InputStream content) { - SignRequest signReq = new SignRequest(); - try { - signReq.setEndpoint(new URI(endpoint)); - } catch (URISyntaxException e) { - LOGGER.warn("set uri failed, uri is {}, message: {}", endpoint, e.getMessage()); - } - - Map queryParams = new HashMap<>(); - if (endpoint.contains("?")) { - String parameters = endpoint.substring(endpoint.indexOf("?") + 1); - if (!StringUtils.isEmpty(parameters)) { - String[] parameterArray = parameters.split("&"); - for (String p : parameterArray) { - String key = p.split("=")[0]; - String value = p.split("=")[1]; - if (!queryParams.containsKey(key)) { - queryParams.put(key, new String[]{value}); - } else { - List vals = new ArrayList<>(Arrays.asList(queryParams.get(key))); - vals.add(value); - queryParams.put(key, vals.toArray(new String[vals.size()])); - } - } - } - } - - signReq.setQueryParams(queryParams); - signReq.setHeaders(headers); - signReq.setHttpMethod(method); - signReq.setContent(content); - return signReq; - } - - - public static List getAuthHeaderProviders() { - return authHeaderProviders; - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/TransportUtils.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/TransportUtils.java new file mode 100644 index 00000000000..d58482d23af --- /dev/null +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/TransportUtils.java @@ -0,0 +1,128 @@ +/* + * 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.huaweicloud.dashboard.monitor; + +import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION; + +import org.apache.servicecomb.foundation.ssl.SSLCustom; +import org.apache.servicecomb.foundation.ssl.SSLOption; +import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; +import org.springframework.core.env.Environment; + +public class TransportUtils { + public static SSLProperties createSSLProperties(boolean sslEnabled, Environment environment, String tag) { + SSLProperties sslProperties = new SSLProperties(); + sslProperties.setEnabled(sslEnabled); + + if (!sslEnabled) { + return sslProperties; + } + + SSLOption option = new SSLOption(); + option.setEngine(getStringProperty(environment, + DEFAULT_OPTION.getEngine(), + "ssl." + tag + ".engine", + "ssl.engine")); + option.setProtocols( + getStringProperty(environment, + DEFAULT_OPTION.getProtocols(), + "ssl." + tag + ".protocols", + "ssl.protocols")); + option.setCiphers( + getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + tag + ".ciphers", "ssl.ciphers")); + option.setAuthPeer( + getBooleanProperty(environment, DEFAULT_OPTION.isAuthPeer(), "ssl." + tag + ".authPeer", "ssl.authPeer")); + option.setCheckCNHost( + getBooleanProperty(environment, + DEFAULT_OPTION.isCheckCNHost(), + "ssl." + tag + ".checkCN.host", + "ssl.checkCN.host")); + option.setCheckCNWhite( + getBooleanProperty(environment, + DEFAULT_OPTION.isCheckCNWhite(), + "ssl." + tag + ".checkCN.white", + "ssl.checkCN.white")); + option.setCheckCNWhiteFile(getStringProperty(environment, + DEFAULT_OPTION.getCiphers(), + "ssl." + tag + ".checkCN.white.file", + "ssl.checkCN.white.file")); + option.setAllowRenegotiate(getBooleanProperty(environment, + DEFAULT_OPTION.isAllowRenegotiate(), + "ssl." + tag + ".allowRenegotiate", + "ssl.allowRenegotiate")); + option.setStorePath( + getStringProperty(environment, + DEFAULT_OPTION.getStorePath(), + "ssl." + tag + ".storePath", + "ssl.storePath")); + option.setClientAuth( + getStringProperty(environment, + DEFAULT_OPTION.getClientAuth(), + "ssl." + tag + ".clientAuth", + "ssl.clientAuth")); + option.setTrustStore( + getStringProperty(environment, + DEFAULT_OPTION.getTrustStore(), + "ssl." + tag + ".trustStore", + "ssl.trustStore")); + option.setTrustStoreType(getStringProperty(environment, + DEFAULT_OPTION.getTrustStoreType(), + "ssl." + tag + ".trustStoreType", + "ssl.trustStoreType")); + option.setTrustStoreValue(getStringProperty(environment, + DEFAULT_OPTION.getTrustStoreValue(), + "ssl." + tag + ".trustStoreValue", + "ssl.trustStoreValue")); + option.setKeyStore( + getStringProperty(environment, DEFAULT_OPTION.getKeyStore(), "ssl." + tag + ".keyStore", "ssl.keyStore")); + option.setKeyStoreType( + getStringProperty(environment, + DEFAULT_OPTION.getKeyStoreType(), + "ssl." + tag + ".keyStoreType", + "ssl.keyStoreType")); + option.setKeyStoreValue(getStringProperty(environment, + DEFAULT_OPTION.getKeyStoreValue(), + "ssl." + tag + ".keyStoreValue", + "ssl.keyStoreValue")); + option.setCrl(getStringProperty(environment, DEFAULT_OPTION.getCrl(), "ssl." + tag + ".crl", "ssl.crl")); + option.setSslCustomClass( + getStringProperty(environment, null, "ssl." + tag + ".sslCustomClass", "ssl.sslCustomClass")); + + sslProperties.setSslOption(option); + sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass())); + return sslProperties; + } + + private static String getStringProperty(Environment environment, String defaultValue, String... keys) { + for (String key : keys) { + if (environment.getProperty(key) != null) { + return environment.getProperty(key); + } + } + return defaultValue; + } + + private static boolean getBooleanProperty(Environment environment, boolean defaultValue, String... keys) { + for (String key : keys) { + if (environment.getProperty(key) != null) { + return environment.getProperty(key, boolean.class, false); + } + } + return defaultValue; + } +} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/CPUMonitorCalc.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/CPUMonitorCalc.java index 79ee974991c..6db0a859e47 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/CPUMonitorCalc.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/CPUMonitorCalc.java @@ -25,17 +25,17 @@ public class CPUMonitorCalc { private static final int PERCENTAGE = 100; - private static CPUMonitorCalc instance = new CPUMonitorCalc(); + private static final CPUMonitorCalc instance = new CPUMonitorCalc(); - private OperatingSystemMXBean osMxBean; + private final OperatingSystemMXBean osMxBean; - private ThreadMXBean threadMXBean; + private final ThreadMXBean threadMXBean; private long preTime = System.nanoTime(); private long preUsedTime = 0; - public CPUMonitorCalc() { + private CPUMonitorCalc() { osMxBean = ManagementFactory.getOperatingSystemMXBean(); threadMXBean = ManagementFactory.getThreadMXBean(); } diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/Diagnosis.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/Diagnosis.java deleted file mode 100644 index 0ee6605b3f6..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/Diagnosis.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor.data; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.apache.servicecomb.serviceregistry.diagnosis.instance.InstanceCacheSummary; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class Diagnosis { - - private InstanceCacheSummary instanceCache; - - public InstanceCacheSummary getInstanceCache() { - return instanceCache; - } - - public void setInstanceCache(InstanceCacheSummary instanceCache) { - this.instanceCache = instanceCache; - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorConstant.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorConstant.java index 42c336178e4..19b20787843 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorConstant.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorConstant.java @@ -17,22 +17,9 @@ package org.apache.servicecomb.huaweicloud.dashboard.monitor.data; -import com.netflix.config.DynamicBooleanProperty; -import com.netflix.config.DynamicIntProperty; -import com.netflix.config.DynamicPropertyFactory; -import com.netflix.config.DynamicStringProperty; +import org.springframework.core.env.Environment; public class MonitorConstant { - public static final String DOMAIN_NAME = getDomainName(); - - public static final String CURRENT_VERSION = getApiVersion(); - - public static final String VERSION_V1 = "v1"; - - public static final String PREFIX_V2 = String.format("/v2/%s/csemonitor", DOMAIN_NAME); - - public static final String MONITORS_URI; - public static final String SYSTEM_KEY_DASHBOARD_SERVICE = "DashboardService"; public static final String MONITOR_URI = "servicecomb.monitor.client.serverUri"; @@ -53,108 +40,89 @@ public class MonitorConstant { public static final int DEFAULT_INTERVAL = 10000; - public static final int MAX_RETRY_TIMES = 3; + private final String DOMAIN_NAME; - static { - if (VERSION_V1.equals(CURRENT_VERSION)) { - MONITORS_URI = "/csemonitor/v1/metric?service=%s"; - } else { - MONITORS_URI = PREFIX_V2 + "/metric?service=%s"; - } - } + private final String CURRENT_VERSION; + + private final String VERSION_V1; + + private final String PREFIX_V2; + + private final String monitorsUri; - public static final String TRANSACTION_URI; + private Environment environment; + + public MonitorConstant(Environment environment) { + this.environment = environment; + this.VERSION_V1 = "v1"; + this.DOMAIN_NAME = getDomainName(); + this.PREFIX_V2 = String.format("/v2/%s/csemonitor", DOMAIN_NAME); + this.CURRENT_VERSION = getApiVersion(); - static { if (VERSION_V1.equals(CURRENT_VERSION)) { - TRANSACTION_URI = "/csemonitor/v1/transaction"; + monitorsUri = "/csemonitor/v1/metric?service=%s"; } else { - TRANSACTION_URI = PREFIX_V2 + "/transaction"; + monitorsUri = PREFIX_V2 + "/metric?service=%s"; } } - public static String getTanentName() { - DynamicStringProperty property = DynamicPropertyFactory.getInstance(). - getStringProperty("servicecomb.config.client.tenantName", "default"); - return property.getValue(); - } - - public static String getDomainName() { - DynamicStringProperty property = DynamicPropertyFactory.getInstance(). - getStringProperty("servicecomb.config.client.domainName", "default"); - return property.getValue(); + public String getMonitorUri() { + return this.monitorsUri; } - public static String getApiVersion() { - DynamicStringProperty property = DynamicPropertyFactory.getInstance(). - getStringProperty("servicecomb.monitor.client.api.version", "v2"); - return property.getValue(); + public String getDomainName() { + return environment.getProperty("servicecomb.config.client.domainName", "default"); } - public static String getServerUrl() { - DynamicStringProperty property = DynamicPropertyFactory.getInstance(). - getStringProperty("servicecomb.monitor.client.serverUri", null); - return property.getValue(); + public String getApiVersion() { + return environment.getProperty("servicecomb.monitor.client.api.version", "v2"); } - public static boolean insCacheEnabled() { - DynamicBooleanProperty property = DynamicPropertyFactory.getInstance(). - getBooleanProperty("servicecomb.monitor.client.pushInsCache", false); - return property.getValue(); + public String getServerUrl() { + return environment.getProperty("servicecomb.monitor.client.serverUri"); } - public static boolean sslEnabled() { - DynamicBooleanProperty property = DynamicPropertyFactory.getInstance(). - getBooleanProperty("servicecomb.monitor.client.sslEnabled", true); - return property.getValue(); + public boolean sslEnabled() { + return environment.getProperty("servicecomb.monitor.client.sslEnabled", boolean.class, true); } - public static boolean isMonitorEnabled() { - DynamicBooleanProperty property = DynamicPropertyFactory.getInstance(). - getBooleanProperty("servicecomb.monitor.client.enabled", true); - return property.getValue(); + public boolean isMonitorEnabled() { + return environment.getProperty("servicecomb.monitor.client.enabled", boolean.class, false); } - public static int getConnectionTimeout() { - DynamicIntProperty property = DynamicPropertyFactory.getInstance(). - getIntProperty("servicecomb.monitor.client.timeout", DEFAULT_TIMEOUT); - return property.getValue(); + public int getConnectionTimeout() { + return environment.getProperty("servicecomb.monitor.client.timeout", int.class, DEFAULT_TIMEOUT); } - public static int getInterval() { - DynamicIntProperty property = DynamicPropertyFactory.getInstance(). - getIntProperty("servicecomb.monitor.client.interval", DEFAULT_INTERVAL); - int val = property.getValue(); - if (val < MIN_INTERVAL_MILLISECONDS) { - return MIN_INTERVAL_MILLISECONDS; - } - return val; + public int getInterval() { + return Math.max(environment.getProperty("servicecomb.monitor.client.interval", int.class, DEFAULT_INTERVAL), + MIN_INTERVAL_MILLISECONDS); } - public static Boolean isProxyEnable() { + public Boolean isProxyEnable() { return Boolean.parseBoolean(getProperty("false", PROXY_ENABLE)); } - public static String getProxyHost() { + public String getProxyHost() { return getProperty("127.0.0.1", PROXY_HOST); } - public static int getProxyPort() { + public int getProxyPort() { return Integer.parseInt(getProperty("8080", PROXY_PORT)); } - public static String getProxyUsername() { + public String getProxyUsername() { return getProperty(null, PROXY_USERNAME); } - public static String getProxyPasswd() { + public String getProxyPasswd() { return getProperty(null, PROXY_PASSWD); } - private static String getProperty(String defaultValue, String... keys) { + private String getProperty(String defaultValue, String... keys) { String property = null; for (String key : keys) { - property = DynamicPropertyFactory.getInstance().getStringProperty(key, null).get(); + property = environment.getProperty(key); if (property != null) { break; } diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorData.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorData.java deleted file mode 100644 index 016ed18a097..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/data/MonitorData.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor.data; - -import com.netflix.hystrix.HystrixCircuitBreaker; -import com.netflix.hystrix.HystrixCommandMetrics; -import com.netflix.hystrix.HystrixEventType; -import org.apache.servicecomb.serviceregistry.diagnosis.instance.InstanceCacheResult; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class MonitorData { - private static final double PERCENTAGE_995 = 99.5; - - private static final double PERCENTAGE_99 = 99; - - private static final double PERCENTAGE_90 = 90; - - private static final double PERCENTAGE_75 = 75; - - private static final double PERCENTAGE_50 = 50; - - private static final double PERCENTAGE_25 = 25; - - private static final double PERCENTAGE_5 = 5; - - private static final int SCALE_VAL = 1; - - private static final double DEFAULT_SUCCESS_RATE = 1.0d; - - private String appId; - - private String version; - - private String name; - - private String serviceId; - - private String instance; - - private String instanceId; - - private int thread; - - private double cpu; - - private double loadAverage; - - private long uptime; - - private Map memory; - - private List interfaces = new ArrayList<>(); - - private Diagnosis diagnosis; - - private Map customs; - - private static final int CONVERSION = 1000; - - private List providersCache; - - public void appendInterfaceInfo(HystrixCommandMetrics metrics) { - InterfaceInfo interfaceInfo = new InterfaceInfo(); - int windowTime = metrics.getProperties().metricsRollingStatisticalWindowInMilliseconds().get() / CONVERSION; - long successCount = metrics.getRollingCount(HystrixEventType.SUCCESS); - long failureCount = metrics.getRollingCount(HystrixEventType.FAILURE); - long semRejectCount = metrics.getRollingCount(HystrixEventType.SEMAPHORE_REJECTED); - long threadRejectCount = metrics.getRollingCount(HystrixEventType.THREAD_POOL_REJECTED); - long timeoutCount = metrics.getRollingCount(HystrixEventType.TIMEOUT); - long shortCircuitedCount = metrics.getRollingCount(HystrixEventType.SHORT_CIRCUITED); - long rollingErrorTotal = failureCount + semRejectCount + threadRejectCount + timeoutCount; - long rollingTotal = successCount + rollingErrorTotal; - - if (rollingTotal == 0) { - interfaceInfo.setRate(DEFAULT_SUCCESS_RATE); - interfaceInfo.setFailureRate(0d); - } else { - double failurePercentage = (double) rollingErrorTotal / rollingTotal; - interfaceInfo.setRate(DEFAULT_SUCCESS_RATE - failurePercentage); - interfaceInfo.setFailureRate(failurePercentage); - } - - int latency = metrics.getTotalTimeMean(); - int latency995 = metrics.getTotalTimePercentile(PERCENTAGE_995); - int latency99 = metrics.getTotalTimePercentile(PERCENTAGE_99); - int latency90 = metrics.getTotalTimePercentile(PERCENTAGE_90); - int latency75 = metrics.getTotalTimePercentile(PERCENTAGE_75); - int latency50 = metrics.getTotalTimePercentile(PERCENTAGE_50); - int latency25 = metrics.getTotalTimePercentile(PERCENTAGE_25); - int latency5 = metrics.getTotalTimePercentile(PERCENTAGE_5); - - interfaceInfo.setName(metrics.getCommandKey().name()); - interfaceInfo.setCircuitBreakerOpen(isOpen(metrics)); - interfaceInfo.setShortCircuited(shortCircuitedCount); - interfaceInfo.setFailureRate(failureCount); - interfaceInfo.setSemaphoreRejected(semRejectCount); - interfaceInfo.setThreadPoolRejected(threadRejectCount); - interfaceInfo.setCountTimeout(timeoutCount); - interfaceInfo.setDesc(metrics.getCommandKey().name()); - interfaceInfo.setLatency(latency); - interfaceInfo.setL995(latency995); - interfaceInfo.setL99(latency99); - interfaceInfo.setL90(latency90); - interfaceInfo.setL75(latency75); - interfaceInfo.setL50(latency50); - interfaceInfo.setL25(latency25); - interfaceInfo.setL5(latency5); - interfaceInfo.setTotal(rollingTotal); - double qpsVal = ((double) rollingTotal) / windowTime; - BigDecimal b = new BigDecimal(qpsVal); - BigDecimal qps = b.setScale(SCALE_VAL, RoundingMode.HALF_DOWN); - interfaceInfo.setQps(qps.doubleValue()); - interfaces.add(interfaceInfo); - } - - public boolean isOpen(HystrixCommandMetrics metrics) { - if (metrics.getProperties().circuitBreakerForceOpen().get()) { - return true; - } - if (metrics.getProperties().circuitBreakerForceClosed().get()) { - return false; - } - HystrixCircuitBreaker circuitBreaker = HystrixCircuitBreaker.Factory.getInstance(metrics.getCommandKey()); - return circuitBreaker != null && circuitBreaker.isOpen(); - } - - public String getAppId() { - return appId; - } - - public void setAppId(String appId) { - this.appId = appId; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getServiceId() { - return serviceId; - } - - public void setServiceId(String serviceId) { - this.serviceId = serviceId; - } - - public String getInstance() { - return instance; - } - - public void setInstance(String instance) { - this.instance = instance; - } - - public String getInstanceId() { - return instanceId; - } - - public void setInstanceId(String instanceId) { - this.instanceId = instanceId; - } - - public int getThreadCount() { - return thread; - } - - public void setThreadCount(int threadCount) { - this.thread = threadCount; - } - - public double getCpu() { - return cpu; - } - - public void setCpu(double cpu) { - this.cpu = cpu; - } - - public double getLoadAverage() { - return loadAverage; - } - - public void setLoadAverage(double loadAverage) { - this.loadAverage = loadAverage; - } - - public long getUptime() { - return uptime; - } - - public void setUptime(long uptime) { - this.uptime = uptime; - } - - public Map getMemory() { - return memory; - } - - public void setMemory(Map memory) { - this.memory = memory; - } - - public List getInterfaces() { - return interfaces; - } - - public void setInterfaces(List interfaces) { - this.interfaces = interfaces; - } - - public Diagnosis getDiagnosis() { - return diagnosis; - } - - public void setDiagnosis(Diagnosis diagnosis) { - this.diagnosis = diagnosis; - } - - public Map getCustoms() { - return customs; - } - - public void setCustoms(Map customs) { - this.customs = customs; - } - - public List getProvidersCache() { - return providersCache; - } - - public void setProvidersCache(List providersCache) { - this.providersCache = providersCache; - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/ConsoleMonitorDataEvent.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/ConsoleMonitorDataEvent.java deleted file mode 100644 index 73a68f52c04..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/ConsoleMonitorDataEvent.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor.event; - -public class ConsoleMonitorDataEvent { - private String jsonData; - - public ConsoleMonitorDataEvent(String jsonData) { - this.setJsonData(jsonData); - } - - public String getJsonData() { - return jsonData; - } - - public void setJsonData(String jsonData) { - this.jsonData = jsonData; - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/MonitorFailEvent.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/MonitorFailEvent.java deleted file mode 100644 index 9c4341437b1..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/MonitorFailEvent.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor.event; - -public class MonitorFailEvent { - - private String msg; - - public MonitorFailEvent(String msg) { - this.msg = msg; - } - - public String getMsg() { - return msg; - } - - public void setMsg(String msg) { - this.msg = msg; - } -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/MonitorSuccEvent.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/MonitorSuccEvent.java deleted file mode 100644 index c3cac1d7447..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/event/MonitorSuccEvent.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor.event; - -public class MonitorSuccEvent { -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDaraProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDaraProvider.java deleted file mode 100644 index 40dd950b25d..00000000000 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDaraProvider.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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.huaweicloud.dashboard.monitor.model; - -public interface MonitorDaraProvider { - String getURL(); - - Object getData(); -} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataProvider.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataProvider.java new file mode 100644 index 00000000000..4f88a5a4492 --- /dev/null +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataProvider.java @@ -0,0 +1,74 @@ +/* + * 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.huaweicloud.dashboard.monitor.model; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryUsage; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.RuntimeMXBean; +import java.lang.management.ThreadMXBean; +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.dashboard.client.model.MonitorData; +import org.apache.servicecomb.huaweicloud.dashboard.monitor.data.CPUMonitorCalc; + +public interface MonitorDataProvider { + boolean enabled(); + + String getURL(); + + void extractServiceInfo(MonitorData monitorData); + + default void exactProcessInfo(MonitorData monitorData) { + MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); + MemoryUsage memoryHeapUsage = memoryMXBean.getHeapMemoryUsage(); + MemoryUsage memoryNonHeapUsage = memoryMXBean.getNonHeapMemoryUsage(); + ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + int threadCount = threadMXBean.getThreadCount(); + OperatingSystemMXBean operatingSystemMXBean = ManagementFactory.getOperatingSystemMXBean(); + + double cpu = operatingSystemMXBean.getSystemLoadAverage(); + monitorData.setCpu(CPUMonitorCalc.getInstance().getProcessCpu()); + monitorData.setLoadAverage(cpu); + monitorData.setThreadCount(threadCount); + monitorData.setUptime(runtimeMXBean.getUptime()); + + Map memoryInfo = new HashMap<>(); + memoryInfo.put("heapInit", memoryHeapUsage.getInit()); + memoryInfo.put("headMax", memoryHeapUsage.getMax()); + memoryInfo.put("heapCommit", memoryHeapUsage.getCommitted()); + memoryInfo.put("heapUsed", memoryHeapUsage.getUsed()); + memoryInfo.put("nonHeapInit", memoryNonHeapUsage.getInit()); + memoryInfo.put("nonHeapCommit", memoryNonHeapUsage.getCommitted()); + memoryInfo.put("nonHeapUsed", memoryNonHeapUsage.getUsed()); + monitorData.setMemory(memoryInfo); + } + + void extractInterfaceInfo(MonitorData monitorData); + + default MonitorData getData() { + MonitorData monitorData = new MonitorData(); + extractServiceInfo(monitorData); + exactProcessInfo(monitorData); + extractInterfaceInfo(monitorData); + return monitorData; + } +} diff --git a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataPublisher.java b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataPublisher.java index a5b10121510..7876c2e3f64 100644 --- a/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataPublisher.java +++ b/huawei-cloud/dashboard/src/main/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/model/MonitorDataPublisher.java @@ -18,7 +18,7 @@ package org.apache.servicecomb.huaweicloud.dashboard.monitor.model; public interface MonitorDataPublisher { - void publish(MonitorDaraProvider provider); + void publish(MonitorDataProvider provider); default void init() { diff --git a/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector b/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector index 39268d6eca3..008bc6a1526 100644 --- a/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector +++ b/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.core.bootup.BootUpInformationCollector @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -org.apache.servicecomb.huaweicloud.dashboard.monitor.MonitorInformationCollector \ No newline at end of file +org.apache.servicecomb.huaweicloud.dashboard.monitor.MonitorInformationCollector diff --git a/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider b/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider deleted file mode 100644 index 38547076ba5..00000000000 --- a/huawei-cloud/dashboard/src/main/resources/META-INF/services/org.apache.servicecomb.deployment.DeploymentProvider +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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.servicecomb.huaweicloud.dashboard.monitor.MonitorDefaultDeploymentProvider \ No newline at end of file diff --git a/huawei-cloud/dashboard/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/huawei-cloud/dashboard/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..54229959fcb --- /dev/null +++ b/huawei-cloud/dashboard/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.servicecomb.huaweicloud.dashboard.monitor.DashboardConfiguration diff --git a/huawei-cloud/dashboard/src/main/resources/META-INF/spring/services.bean.xml b/huawei-cloud/dashboard/src/main/resources/META-INF/spring/services.bean.xml deleted file mode 100644 index 89a15992109..00000000000 --- a/huawei-cloud/dashboard/src/main/resources/META-INF/spring/services.bean.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - diff --git a/huawei-cloud/dashboard/src/test/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProviderTest.java b/huawei-cloud/dashboard/src/test/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProviderTest.java new file mode 100644 index 00000000000..c5411febdb8 --- /dev/null +++ b/huawei-cloud/dashboard/src/test/java/org/apache/servicecomb/huaweicloud/dashboard/monitor/MetricsMonitorDataProviderTest.java @@ -0,0 +1,30 @@ +/* + * 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.huaweicloud.dashboard.monitor; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class MetricsMonitorDataProviderTest { + @Test + public void testCodeMatch() { + Assertions.assertTrue("200".matches(MetricsMonitorDataProvider.CODE_SUCCESS)); + Assertions.assertTrue("202".matches(MetricsMonitorDataProvider.CODE_SUCCESS)); + Assertions.assertFalse("2002".matches(MetricsMonitorDataProvider.CODE_SUCCESS)); + Assertions.assertFalse("400".matches(MetricsMonitorDataProvider.CODE_SUCCESS)); + } +} diff --git a/huawei-cloud/dashboard/src/test/resources/microservice.yaml b/huawei-cloud/dashboard/src/test/resources/microservice.yaml new file mode 100644 index 00000000000..363e3369fa0 --- /dev/null +++ b/huawei-cloud/dashboard/src/test/resources/microservice.yaml @@ -0,0 +1,42 @@ +# +## --------------------------------------------------------------------------- +## 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 +server: + port: 9093 # should be same with servicecomb.rest.address to use web container + +# override common configurations in common module +servicecomb-config-order: 10 +instance_description: + environment: production + +servicecomb: + service: + environment: development + application: demo-java-chassis-dashboard + name: test-dashboard + version: 0.0.1 + registry: + address: http://127.0.0.1:30100 + instance: + watch: false + kie: + serverUri: http://127.0.0.1:30110 + customLabel: public + + rest: + address: 0.0.0.0:9097 # should be same with server.port to use web container diff --git a/huawei-cloud/environment/README.md b/huawei-cloud/environment/README.md deleted file mode 100644 index a006657ade8..00000000000 --- a/huawei-cloud/environment/README.md +++ /dev/null @@ -1,20 +0,0 @@ -这个模块主要提供 servicestage 部署环境变量和配置项的映射,通过这种方式可以简化配置。 - -servicestage 存在环境、应用、组件等概念,这些内容都是在部署的时候输入,可以将这些内容用于微服务的配置信息。 - -|概念|环境变量|微服务配置项| -| :--- | :--- | :--- | -|应用|CAS_APPLICATION_NAME|servicecomb.service.application| -|组件|CAS_COMPONENT_NAME|servicecomb.service.name| -|组件版本|CAS_INSTANCE_VERSION|servicecomb.service.version| - -部署的过程还会注入环境里面的资源信息。 - -|概念|环境变量|微服务配置项| -| :--- | :--- | :--- | -|服务/配置中心地址(逻辑多租,APIG场景)| PAAS_CSE_ENDPOINT | servicecomb.service.registry.address
servicecomb.config.client.serverUri| -|服务中心地址 | PAAS_CSE_SC_ENDPOINT | servicecomb.service.registry.address | -|配置中心地址 | PAAS_CSE_CC_ENDPOINT | servicecomb.config.client.serverUri | -|项目(区域) | PAAS_PROJECT_NAME | servicecomb.credentials.project | - - diff --git a/huawei-cloud/environment/pom.xml b/huawei-cloud/environment/pom.xml deleted file mode 100644 index 0e9c38779f5..00000000000 --- a/huawei-cloud/environment/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - huawei-cloud - org.apache.servicecomb - 2.6.0-SNAPSHOT - - 4.0.0 - servicestage-environment - Java Chassis::Huawei Cloud::ServiceStage - - - - org.apache.servicecomb - java-chassis-core - - - org.apache.servicecomb - registry-service-center - - - - \ No newline at end of file diff --git a/huawei-cloud/environment/src/main/resources/mapping.yaml b/huawei-cloud/environment/src/main/resources/mapping.yaml deleted file mode 100644 index 936a03c27c3..00000000000 --- a/huawei-cloud/environment/src/main/resources/mapping.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# -# 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-config-order: -100 - -PAAS_CSE_ENDPOINT: - - servicecomb.service.registry.address - - servicecomb.config.client.serverUri - - servicecomb.monitor.client.serverUri -PAAS_CSE_SC_ENDPOINT: - - servicecomb.service.registry.address -PAAS_CSE_CC_ENDPOINT: - - servicecomb.config.client.serverUri -PAAS_CSE_DS_ENDPOINT: - - servicecomb.monitor.client.serverUri -PAAS_PROJECT_NAME: - - servicecomb.credentials.project - -## other possible and useful mappings - -#CAS_APPLICATION_NAME: -# - servicecomb.service.application -#CAS_COMPONENT_NAME: -# - servicecomb.service.name -#CAS_INSTANCE_VERSION: -# - servicecomb.service.version \ No newline at end of file diff --git a/huawei-cloud/pom.xml b/huawei-cloud/pom.xml index 49b7fc46887..eb70052ed01 100644 --- a/huawei-cloud/pom.xml +++ b/huawei-cloud/pom.xml @@ -21,7 +21,7 @@ org.apache.servicecomb java-chassis-parent - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT ../parents/default @@ -32,9 +32,8 @@ servicestage - environment dashboard darklaunch - \ No newline at end of file + diff --git a/huawei-cloud/servicestage/pom.xml b/huawei-cloud/servicestage/pom.xml index 00726296b1f..d92064951f9 100644 --- a/huawei-cloud/servicestage/pom.xml +++ b/huawei-cloud/servicestage/pom.xml @@ -21,7 +21,7 @@ huawei-cloud org.apache.servicecomb - 2.6.0-SNAPSHOT + 3.4.0-SNAPSHOT 4.0.0 servicestage @@ -40,6 +40,11 @@ org.apache.servicecomb foundation-test-scaffolding + + org.apache.logging.log4j + log4j-slf4j-impl + test + - \ No newline at end of file + diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java index 9467ae67d56..e80e867cab4 100644 --- a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/AKSKAuthHeaderProvider.java @@ -17,9 +17,9 @@ package org.apache.servicecomb.huaweicloud.servicestage; -import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -28,19 +28,18 @@ import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Hex; -import org.apache.commons.configuration.Configuration; import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.config.ConfigUtil; import org.apache.servicecomb.foundation.auth.AuthHeaderProvider; import org.apache.servicecomb.foundation.auth.Cipher; import org.apache.servicecomb.foundation.auth.DefaultCipher; import org.apache.servicecomb.foundation.auth.ShaAKSKCipher; -import org.apache.servicecomb.foundation.common.utils.BeanUtils; +import org.apache.servicecomb.foundation.bootstrap.BootStrapService; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.env.Environment; -public class AKSKAuthHeaderProvider implements AuthHeaderProvider { +public class AKSKAuthHeaderProvider implements AuthHeaderProvider, BootStrapService { private static final Logger LOGGER = LoggerFactory.getLogger(AKSKAuthHeaderProvider.class); private static final String CONFIG_AKSK_ENABLED = "servicecomb.credentials.akskEnabled"; @@ -63,34 +62,25 @@ public class AKSKAuthHeaderProvider implements AuthHeaderProvider { private static final String X_SERVICE_PROJECT = "X-Service-Project"; - private Map headers = new HashMap<>(); + private static Environment environment; - private final Configuration configuration; - - private boolean enabled; + private final Map headers = new HashMap<>(); private boolean loaded = false; public AKSKAuthHeaderProvider() { - this(ConfigUtil.createLocalConfig()); - } - - public AKSKAuthHeaderProvider(Configuration configuration) { - this.configuration = configuration; - this.enabled = configuration.getBoolean(CONFIG_AKSK_ENABLED, true); } public Map authHeaders() { - if (!enabled) { - return headers; + if (!environment.getProperty(CONFIG_AKSK_ENABLED, boolean.class, true)) { + return Collections.emptyMap(); } if (StringUtils.isEmpty(getAccessKey())) { LOGGER.warn("ak sk auth enabled but access key is not configured, disable it at runtime. " + "Config [{}] to false to disable it implicitly.", CONFIG_AKSK_ENABLED); - enabled = false; - return headers; + return Collections.emptyMap(); } if (!loaded) { @@ -104,19 +94,20 @@ private synchronized void load() { headers.put(X_SERVICE_AK, getAccessKey()); headers.put(X_SERVICE_SHAAKSK, getSecretKey()); headers.put(X_SERVICE_PROJECT, getProject()); + loaded = true; } } private String getAccessKey() { - return configuration.getString(CONFIG_ACCESS_KEY, ""); + return environment.getProperty(CONFIG_ACCESS_KEY, ""); } private String getCipher() { - return configuration.getString(CONFIG_CIPHER, VALUE_DEFAULT_CIPHER); + return environment.getProperty(CONFIG_CIPHER, VALUE_DEFAULT_CIPHER); } private String getSecretKey() { - String secretKey = configuration.getString(CONFIG_SECRET_KEY, ""); + String secretKey = environment.getProperty(CONFIG_SECRET_KEY, ""); String decodedSecretKey = new String(findCipher().decrypt(secretKey.toCharArray())); // ShaAKSKCipher 不解密, 认证的时候不处理;其他算法解密为 plain,需要 encode 为 ShaAKSKCipher 去认证。 @@ -128,15 +119,11 @@ private String getSecretKey() { } private String getProject() { - String project = configuration.getString(CONFIG_PROJECT, VALUE_DEFAULT_PROJECT); + String project = environment.getProperty(CONFIG_PROJECT, VALUE_DEFAULT_PROJECT); if (StringUtils.isEmpty(project)) { return project; } - try { - return URLEncoder.encode(project, "UTF-8"); - } catch (UnsupportedEncodingException e) { - return project; - } + return URLEncoder.encode(project, StandardCharsets.UTF_8); } private Cipher findCipher() { @@ -160,4 +147,9 @@ public static String sha256Encode(String key, String data) { throw new IllegalArgumentException("Can not encode ak sk. Please check the value is correct.", e); } } + + @Override + public void startup(Environment environment) { + AKSKAuthHeaderProvider.environment = environment; + } } diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvConfig.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvConfig.java index 12bc2ce81b6..baadb927b40 100644 --- a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvConfig.java +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvConfig.java @@ -18,14 +18,14 @@ import static org.apache.commons.lang3.StringUtils.EMPTY; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; - -import com.netflix.config.DynamicPropertyFactory; +import org.apache.servicecomb.foundation.common.LegacyPropertyFactory; public class CasEnvConfig { private static final String APPLICATION_ID = "CAS_APPLICATION_ID"; @@ -38,29 +38,48 @@ public class CasEnvConfig { private static final String ENVIRONMENT_ID = "CAS_ENVIRONMENT_ID"; - public static final CasEnvConfig INSTANCE = new CasEnvConfig(); + private static final String SERVICE_PROPS = "SERVICECOMB_SERVICE_PROPS"; - private Map properties = new HashMap<>(); + private static final String INSTANCE_PROPS = "SERVICECOMB_INSTANCE_PROPS"; - private CasEnvConfig() { - init(); - } + public static final CasEnvConfig INSTANCE = new CasEnvConfig(); - private void init() { - properties.put(APPLICATION_ID, DynamicPropertyFactory - .getInstance().getStringProperty(APPLICATION_ID, EMPTY).get()); - properties.put(COMPONENT_NAME, DynamicPropertyFactory - .getInstance().getStringProperty(COMPONENT_NAME, EMPTY).get()); - properties.put(INSTANCE_VERSION, DynamicPropertyFactory - .getInstance().getStringProperty(INSTANCE_VERSION, EMPTY).get()); - properties.put(INSTANCE_ID, DynamicPropertyFactory - .getInstance().getStringProperty(INSTANCE_ID, EMPTY).get()); - properties.put(ENVIRONMENT_ID, DynamicPropertyFactory - .getInstance().getStringProperty(ENVIRONMENT_ID, EMPTY).get()); + private Map parseProps(String value) { + Map rs = new HashMap<>(); + if (StringUtils.isEmpty(value)) { + return rs; + } + return Arrays.stream(value.split(",")).map(v -> v.split(":")) + .filter(v -> v.length == 2) + .collect(Collectors.toMap(v -> v[0], v -> v[1])); } - public Map getNonEmptyProperties() { - return properties.entrySet().stream().filter(entry -> StringUtils.isNotEmpty(entry.getValue())) + public Map getNonEmptyInstanceProperties() { + Map map = new HashMap<>(); + + map.put(APPLICATION_ID, LegacyPropertyFactory + .getStringProperty(APPLICATION_ID, EMPTY)); + map.put(COMPONENT_NAME, LegacyPropertyFactory + .getStringProperty(COMPONENT_NAME, EMPTY)); + map.put(INSTANCE_VERSION, LegacyPropertyFactory + .getStringProperty(INSTANCE_VERSION, EMPTY)); + map.put(INSTANCE_ID, LegacyPropertyFactory + .getStringProperty(INSTANCE_ID, EMPTY)); + map.put(ENVIRONMENT_ID, LegacyPropertyFactory + .getStringProperty(ENVIRONMENT_ID, EMPTY)); + + Map instanceProps = map.entrySet().stream() + .filter(entry -> StringUtils.isNotEmpty(entry.getValue())) .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + + instanceProps.putAll(parseProps(LegacyPropertyFactory + .getStringProperty(INSTANCE_PROPS, EMPTY))); + + return instanceProps; + } + + public Map getNonEmptyServiceProperties() { + return parseProps(LegacyPropertyFactory + .getStringProperty(SERVICE_PROPS, EMPTY)); } } diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvVariablesAdapter.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvVariablesAdapter.java index e8896f96e66..41cfc848df6 100644 --- a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvVariablesAdapter.java +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/CasEnvVariablesAdapter.java @@ -17,24 +17,26 @@ package org.apache.servicecomb.huaweicloud.servicestage; -import org.apache.servicecomb.serviceregistry.adapter.EnvAdapter; -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; +import java.util.Map; -public class CasEnvVariablesAdapter implements EnvAdapter { - private static final String NAME = "cas-env-variables-adapter"; +import org.apache.servicecomb.registry.RegistrationManager; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; - @Override - public String getEnvName() { - return NAME; - } +public class CasEnvVariablesAdapter implements InitializingBean { - @Override - public int getOrder() { - return 0; + private RegistrationManager registrationManager; + + @Autowired + public void setRegistrationManager(RegistrationManager registrationManager) { + this.registrationManager = registrationManager; } @Override - public void beforeRegisterInstance(MicroserviceInstance instance) { - instance.getProperties().putAll(CasEnvConfig.INSTANCE.getNonEmptyProperties()); + public void afterPropertiesSet() throws Exception { + Map extras = CasEnvConfig.INSTANCE.getNonEmptyServiceProperties(); + extras.forEach((k, v) -> this.registrationManager.addProperty(k, v)); + extras = CasEnvConfig.INSTANCE.getNonEmptyInstanceProperties(); + extras.forEach((k, v) -> this.registrationManager.addProperty(k, v)); } } diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/RBACBootStrapService.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/RBACBootStrapService.java new file mode 100644 index 00000000000..007e3e56c96 --- /dev/null +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/RBACBootStrapService.java @@ -0,0 +1,261 @@ +/* + * 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.huaweicloud.servicestage; + +import static org.apache.servicecomb.foundation.ssl.SSLOption.DEFAULT_OPTION; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.http.HttpHost; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.servicecomb.foundation.auth.Cipher; +import org.apache.servicecomb.foundation.auth.DefaultCipher; +import org.apache.servicecomb.foundation.bootstrap.BootStrapService; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; +import org.apache.servicecomb.foundation.ssl.SSLCustom; +import org.apache.servicecomb.foundation.ssl.SSLOption; +import org.apache.servicecomb.foundation.vertx.VertxConst; +import org.apache.servicecomb.http.client.auth.DefaultRequestAuthHeaderProvider; +import org.apache.servicecomb.http.client.common.HttpConfiguration.SSLProperties; +import org.apache.servicecomb.http.client.common.HttpTransport; +import org.apache.servicecomb.http.client.common.HttpTransportFactory; +import org.apache.servicecomb.registry.sc.SCClientUtils; +import org.apache.servicecomb.service.center.client.ServiceCenterAddressManager; +import org.apache.servicecomb.service.center.client.ServiceCenterClient; +import org.apache.servicecomb.service.center.client.ServiceCenterRawClient; +import org.springframework.core.env.Environment; + +import com.google.common.annotations.VisibleForTesting; + +public class RBACBootStrapService implements BootStrapService { + private static final String RBAC_ADDRESS = "servicecomb.service.registry.address"; + + public static final String DEFAULT_REGISTRY_NAME = "default"; + + public static final String RBAC_ENABLED = "servicecomb.credentials.rbac.enabled"; + + public static final String ACCOUNT_NAME_KEY = "servicecomb.credentials.account.name"; + + public static final String PASSWORD_KEY = "servicecomb.credentials.account.password"; + + public static final String CIPHER_KEY = "servicecomb.credentials.cipher"; + + public static final String PROJECT_KEY = "servicecomb.credentials.project"; + + private static final String SSL_TAG = "sc.consumer"; + + @Override + public void startup(Environment environment) { + if (!getBooleanProperty(environment, false, RBAC_ENABLED)) { + return; + } + + ServiceCenterAddressManager addressManager = createAddressManager(environment); + addressManager.setEventBus(EventManager.getEventBus()); + SSLProperties sslProperties = createSSLProperties(environment); + sslProperties.setEnabled(addressManager.sslEnabled()); + + ServiceCenterClient serviceCenterClient = + new ServiceCenterClient(new ServiceCenterRawClient.Builder() + .setTenantName("default") + .setAddressManager(addressManager) + .setHttpTransport(createHttpTransport(environment, sslProperties)).build(), addressManager); + + Map clients = new HashMap<>(1); + clients.put(DEFAULT_REGISTRY_NAME, serviceCenterClient); + TokenCacheManager.getInstance().setServiceCenterClients(clients); + TokenCacheManager.getInstance().addTokenCache( + DEFAULT_REGISTRY_NAME, + getStringProperty(environment, null, ACCOUNT_NAME_KEY), + getStringProperty(environment, null, PASSWORD_KEY), + getCipher(getStringProperty(environment, DefaultCipher.CIPHER_NAME, CIPHER_KEY))); + } + + private static HttpTransport createHttpTransport(Environment environment, SSLProperties sslProperties) { + if (isProxyEnable(environment)) { + HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(). + setDefaultRequestConfig(HttpTransportFactory.defaultRequestConfig().build()); + HttpHost proxy = new HttpHost(getProxyHost(environment), + getProxyPort(environment), "http"); // now only support http proxy + httpClientBuilder.setProxy(proxy); + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(proxy), + new UsernamePasswordCredentials(getProxyUsername(environment), + getProxyPasswd(environment))); + httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider); + + return HttpTransportFactory + .createHttpTransport(sslProperties, + new DefaultRequestAuthHeaderProvider(), httpClientBuilder); + } + + return HttpTransportFactory + .createHttpTransport(sslProperties, + new DefaultRequestAuthHeaderProvider(), HttpTransportFactory.defaultRequestConfig().build()); + } + + @VisibleForTesting + Cipher getCipher(String cipherName) { + if (DefaultCipher.CIPHER_NAME.equals(cipherName)) { + return DefaultCipher.getInstance(); + } + + List ciphers = SPIServiceUtils.getOrLoadSortedService(Cipher.class); + return ciphers.stream().filter(c -> c.name().equals(cipherName)).findFirst() + .orElseThrow(() -> new IllegalArgumentException("failed to find cipher named " + cipherName)); + } + + private ServiceCenterAddressManager createAddressManager(Environment environment) { + return SCClientUtils.createAddressManager(getProjectName(environment), getRBACAddressList(environment), + environment); + } + + private SSLProperties createSSLProperties(Environment environment) { + SSLProperties sslProperties = new SSLProperties(); + + SSLOption option = new SSLOption(); + option.setEngine(getStringProperty(environment, + DEFAULT_OPTION.getEngine(), + "ssl." + SSL_TAG + ".engine", + "ssl.engine")); + option.setProtocols( + getStringProperty(environment, + DEFAULT_OPTION.getProtocols(), + "ssl." + SSL_TAG + ".protocols", + "ssl.protocols")); + option.setCiphers( + getStringProperty(environment, DEFAULT_OPTION.getCiphers(), "ssl." + SSL_TAG + ".ciphers", "ssl.ciphers")); + option.setAuthPeer( + getBooleanProperty(environment, DEFAULT_OPTION.isAuthPeer(), "ssl." + SSL_TAG + ".authPeer", "ssl.authPeer")); + option.setCheckCNHost( + getBooleanProperty(environment, + DEFAULT_OPTION.isCheckCNHost(), + "ssl." + SSL_TAG + ".checkCN.host", + "ssl.checkCN.host")); + option.setCheckCNWhite( + getBooleanProperty(environment, + DEFAULT_OPTION.isCheckCNWhite(), + "ssl." + SSL_TAG + ".checkCN.white", + "ssl.checkCN.white")); + option.setCheckCNWhiteFile(getStringProperty(environment, + DEFAULT_OPTION.getCiphers(), + "ssl." + SSL_TAG + ".checkCN.white.file", + "ssl.checkCN.white.file")); + option.setAllowRenegotiate(getBooleanProperty(environment, + DEFAULT_OPTION.isAllowRenegotiate(), + "ssl." + SSL_TAG + ".allowRenegotiate", + "ssl.allowRenegotiate")); + option.setStorePath( + getStringProperty(environment, + DEFAULT_OPTION.getStorePath(), + "ssl." + SSL_TAG + ".storePath", + "ssl.storePath")); + option.setClientAuth( + getStringProperty(environment, + DEFAULT_OPTION.getClientAuth(), + "ssl." + SSL_TAG + ".clientAuth", + "ssl.clientAuth")); + option.setTrustStore( + getStringProperty(environment, + DEFAULT_OPTION.getTrustStore(), + "ssl." + SSL_TAG + ".trustStore", + "ssl.trustStore")); + option.setTrustStoreType(getStringProperty(environment, + DEFAULT_OPTION.getTrustStoreType(), + "ssl." + SSL_TAG + ".trustStoreType", + "ssl.trustStoreType")); + option.setTrustStoreValue(getStringProperty(environment, + DEFAULT_OPTION.getTrustStoreValue(), + "ssl." + SSL_TAG + ".trustStoreValue", + "ssl.trustStoreValue")); + option.setKeyStore( + getStringProperty(environment, DEFAULT_OPTION.getKeyStore(), "ssl." + SSL_TAG + ".keyStore", "ssl.keyStore")); + option.setKeyStoreType( + getStringProperty(environment, + DEFAULT_OPTION.getKeyStoreType(), + "ssl." + SSL_TAG + ".keyStoreType", + "ssl.keyStoreType")); + option.setKeyStoreValue(getStringProperty(environment, + DEFAULT_OPTION.getKeyStoreValue(), + "ssl." + SSL_TAG + ".keyStoreValue", + "ssl.keyStoreValue")); + option.setCrl(getStringProperty(environment, DEFAULT_OPTION.getCrl(), "ssl." + SSL_TAG + ".crl", "ssl.crl")); + option.setSslCustomClass( + getStringProperty(environment, null, "ssl." + SSL_TAG + ".sslCustomClass", "ssl.sslCustomClass")); + + sslProperties.setSslOption(option); + sslProperties.setSslCustom(SSLCustom.createSSLCustom(option.getSslCustomClass())); + return sslProperties; + } + + private String getStringProperty(Environment environment, String defaultValue, String... keys) { + for (String key : keys) { + if (environment.getProperty(key) != null) { + return environment.getProperty(key); + } + } + return defaultValue; + } + + private boolean getBooleanProperty(Environment environment, boolean defaultValue, String... keys) { + for (String key : keys) { + if (environment.getProperty(key) != null) { + return Boolean.parseBoolean(environment.getProperty(key)); + } + } + return defaultValue; + } + + private String getProjectName(Environment environment) { + return getStringProperty(environment, "default", PROJECT_KEY); + } + + private List getRBACAddressList(Environment environment) { + String address = environment.getProperty(RBAC_ADDRESS, "http://127.0.0.1:30100"); + return Arrays.asList(address.split(",")); + } + + + public static Boolean isProxyEnable(Environment environment) { + return environment.getProperty(VertxConst.PROXY_ENABLE, boolean.class, false); + } + + public static String getProxyHost(Environment environment) { + return environment.getProperty(VertxConst.PROXY_HOST, "127.0.0.1"); + } + + public static int getProxyPort(Environment environment) { + return environment.getProperty(VertxConst.PROXY_PORT, int.class, 8080); + } + + public static String getProxyUsername(Environment environment) { + return environment.getProperty(VertxConst.PROXY_USERNAME); + } + + public static String getProxyPasswd(Environment environment) { + return environment.getProperty(VertxConst.PROXY_PASSWD); + } +} diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java new file mode 100644 index 00000000000..5a369b70bf9 --- /dev/null +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/ServiceStageConfiguration.java @@ -0,0 +1,28 @@ +/* + * 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.huaweicloud.servicestage; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ServiceStageConfiguration { + @Bean + public CasEnvVariablesAdapter casEnvVariablesAdapter() { + return new CasEnvVariablesAdapter(); + } +} diff --git a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/TokenAuthHeaderProvider.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenAuthHeaderProvider.java similarity index 86% rename from service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/TokenAuthHeaderProvider.java rename to huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenAuthHeaderProvider.java index 0f075568313..19bd550602b 100644 --- a/service-registry/registry-service-center/src/main/java/org/apache/servicecomb/serviceregistry/auth/TokenAuthHeaderProvider.java +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenAuthHeaderProvider.java @@ -15,7 +15,7 @@ * limitations under the License. */ -package org.apache.servicecomb.serviceregistry.auth; +package org.apache.servicecomb.huaweicloud.servicestage; import java.util.Collections; import java.util.HashMap; @@ -26,8 +26,8 @@ public class TokenAuthHeaderProvider implements AuthHeaderProvider { @Override - public Map authHeaders() { - String token = TokenCacheManager.getInstance().getToken(RBACBootStrapService.DEFAULT_REGISTRY_NAME); + public Map authHeaders(String host) { + String token = TokenCacheManager.getInstance().getToken(host); if (StringUtils.isEmpty(token)) { return new HashMap<>(); } diff --git a/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenCacheManager.java b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenCacheManager.java new file mode 100644 index 00000000000..b4510bb4238 --- /dev/null +++ b/huawei-cloud/servicestage/src/main/java/org/apache/servicecomb/huaweicloud/servicestage/TokenCacheManager.java @@ -0,0 +1,206 @@ +/* + * 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.huaweicloud.servicestage; + +import java.net.URI; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.lang3.StringUtils; +import org.apache.servicecomb.foundation.auth.Cipher; +import org.apache.servicecomb.foundation.common.event.EventManager; +import org.apache.servicecomb.http.client.event.OperationEvents; +import org.apache.servicecomb.service.center.client.ServiceCenterClient; +import org.apache.servicecomb.service.center.client.model.RbacTokenRequest; +import org.apache.servicecomb.service.center.client.model.RbacTokenResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.eventbus.Subscribe; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; + +import jakarta.ws.rs.core.Response.Status; + +public final class TokenCacheManager { + private static final Logger LOGGER = LoggerFactory.getLogger(TokenCacheManager.class); + + // special token used for special conditions + // e.g. un-authorized: will query token after token expired period + // e.g. not found: will query token after token expired period + public static final String INVALID_TOKEN = ""; + + private static final TokenCacheManager INSTANCE = new TokenCacheManager(); + + private Map serviceCenterClients; + + private TokenCache tokenCache; + + public static TokenCacheManager getInstance() { + return INSTANCE; + } + + private TokenCacheManager() { + } + + public void setServiceCenterClients(Map serviceCenterClients) { + this.serviceCenterClients = serviceCenterClients; + } + + public void addTokenCache(String registryName, String accountName, String password, Cipher cipher) { + tokenCache = new TokenCache(registryName, accountName, password, cipher); + } + + public String getToken(String host) { + if (tokenCache == null) { + return null; + } + return tokenCache.getToken(host); + } + + public class TokenCache { + private static final long TOKEN_REFRESH_TIME_IN_SECONDS = 20 * 60 * 1000; + + private final String registryName; + + private final String accountName; + + private final String password; + + private ExecutorService executorService; + + private LoadingCache cache; + + private final Cipher cipher; + + public TokenCache(String registryName, String accountName, String password, + Cipher cipher) { + this.registryName = registryName; + this.accountName = accountName; + this.password = password; + this.cipher = cipher; + + if (enabled()) { + executorService = Executors.newFixedThreadPool(1, t -> new Thread(t, "rbac-executor-" + this.registryName) { + @Override + public void run() { + try { + super.run(); + } catch (Throwable e) { + LOGGER.error("", e); + } + } + }); + cache = CacheBuilder.newBuilder() + .maximumSize(10) + .refreshAfterWrite(refreshTime(), TimeUnit.MILLISECONDS) + .build(new CacheLoader() { + @Override + public String load(String key) throws Exception { + return createHeaders(key); + } + + @Override + public ListenableFuture reload(String key, String oldValue) throws Exception { + return Futures.submit(() -> createHeaders(key), executorService); + } + }); + EventManager.getEventBus().register(this); + } + } + + @Subscribe + public void onNotPermittedEvent(OperationEvents.UnAuthorizedOperationEvent event) { + LOGGER.warn("address {} unAuthorized, refresh cache token!", event.getAddress()); + cache.refresh(getHostByAddress(event.getAddress())); + } + + private String getHostByAddress(String address) { + try { + URI uri = URI.create(address); + return uri.getHost(); + } catch (Exception e) { + LOGGER.error("get host by address [{}] error!", address, e); + return registryName; + } + } + + private String createHeaders(String host) { + LOGGER.info("start to create RBAC headers for host: {}", host); + + ServiceCenterClient serviceCenterClient = serviceCenterClients.get(this.registryName); + + RbacTokenRequest request = new RbacTokenRequest(); + request.setName(accountName); + request.setPassword(new String(cipher.decrypt(password.toCharArray()))); + + RbacTokenResponse rbacTokenResponse = serviceCenterClient.queryToken(request, host); + + if (Status.UNAUTHORIZED.getStatusCode() == rbacTokenResponse.getStatusCode() + || Status.FORBIDDEN.getStatusCode() == rbacTokenResponse.getStatusCode()) { + // password wrong, do not try anymore + LOGGER.warn("username or password may be wrong, stop trying to query tokens."); + return INVALID_TOKEN; + } + if (Status.NOT_FOUND.getStatusCode() == rbacTokenResponse.getStatusCode()) { + // service center not support, do not try + LOGGER.warn("service center do not support RBAC token, you should not config account info"); + return INVALID_TOKEN; + } + if (Status.INTERNAL_SERVER_ERROR.getStatusCode() == rbacTokenResponse.getStatusCode()) { + // return null for server_error, so the token information can be re-fetched on the next call. + // It will prompt 'CacheLoader returned null for key xxx' + LOGGER.warn("service center query RBAC token error!"); + return null; + } + + LOGGER.info("refresh host [{}] token successfully {}", host, rbacTokenResponse.getStatusCode()); + return rbacTokenResponse.getToken(); + } + + protected long refreshTime() { + return TOKEN_REFRESH_TIME_IN_SECONDS; + } + + public String getToken(String host) { + if (!enabled()) { + return null; + } + String address = host; + if (StringUtils.isEmpty(address)) { + address = registryName; + } + try { + return cache.get(address); + } catch (Exception e) { + LOGGER.error("failed to create token", e); + return null; + } + } + + private boolean enabled() { + return !StringUtils.isEmpty(this.accountName) + && !StringUtils.isEmpty(this.password); + } + } +} diff --git a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider index e756f8985d0..a78d2c2e33b 100644 --- a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider +++ b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.AuthHeaderProvider @@ -16,3 +16,4 @@ # org.apache.servicecomb.huaweicloud.servicestage.AKSKAuthHeaderProvider +org.apache.servicecomb.huaweicloud.servicestage.TokenAuthHeaderProvider diff --git a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.Cipher b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.Cipher index e242e7a854a..8d0efa25aef 100644 --- a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.Cipher +++ b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.auth.Cipher @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.foundation.auth.ShaAKSKCipher \ No newline at end of file +org.apache.servicecomb.foundation.auth.ShaAKSKCipher diff --git a/service-registry/registry-service-center/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService similarity index 84% rename from service-registry/registry-service-center/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService rename to huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService index e515f0a1aa6..90c339ba065 100644 --- a/service-registry/registry-service-center/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService +++ b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.foundation.bootstrap.BootStrapService @@ -15,4 +15,5 @@ # limitations under the License. # -org.apache.servicecomb.serviceregistry.auth.RBACBootStrapService \ No newline at end of file +org.apache.servicecomb.huaweicloud.servicestage.RBACBootStrapService +org.apache.servicecomb.huaweicloud.servicestage.AKSKAuthHeaderProvider diff --git a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.adapter.EnvAdapter b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.adapter.EnvAdapter index a7eb97b3bc3..2aa5b486121 100644 --- a/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.adapter.EnvAdapter +++ b/huawei-cloud/servicestage/src/main/resources/META-INF/services/org.apache.servicecomb.serviceregistry.adapter.EnvAdapter @@ -15,4 +15,4 @@ # limitations under the License. # -org.apache.servicecomb.huaweicloud.servicestage.CasEnvVariablesAdapter \ No newline at end of file +org.apache.servicecomb.huaweicloud.servicestage.CasEnvVariablesAdapter diff --git a/huawei-cloud/servicestage/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/huawei-cloud/servicestage/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..04b38f05d6f --- /dev/null +++ b/huawei-cloud/servicestage/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.servicecomb.huaweicloud.servicestage.ServiceStageConfiguration diff --git a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java index 72935a5e0f1..2b82672c77c 100644 --- a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java +++ b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestAKSKAuthHeaderProvider.java @@ -17,36 +17,46 @@ package org.apache.servicecomb.huaweicloud.servicestage; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; - -import com.netflix.config.ConcurrentCompositeConfiguration; +import org.springframework.core.env.Environment; public class TestAKSKAuthHeaderProvider { @Test public void test_project_name_properly_encoded_en() { - ConcurrentCompositeConfiguration configuration = Mockito.mock(ConcurrentCompositeConfiguration.class); - Mockito.when(configuration.getBoolean("servicecomb.credentials.akskEnabled", true)).thenReturn(true); - Mockito.when(configuration.getString("servicecomb.credentials.project", "default")).thenReturn("hello"); - Mockito.when(configuration.getString("servicecomb.credentials.accessKey", "")).thenReturn("access key"); - Mockito.when(configuration.getString("servicecomb.credentials.secretKey", "")).thenReturn("secret key"); - Mockito.when(configuration.getString("servicecomb.credentials.akskCustomCipher", "default")).thenReturn("default"); + Environment environment = Mockito.mock(Environment.class); + Mockito.when(environment.getProperty("servicecomb.credentials.akskEnabled", + boolean.class, true)).thenReturn(true); + Mockito.when(environment.getProperty("servicecomb.credentials.project", + "default")).thenReturn("hello"); + Mockito.when(environment.getProperty("servicecomb.credentials.accessKey", + "")).thenReturn("access key"); + Mockito.when(environment.getProperty("servicecomb.credentials.secretKey", + "")).thenReturn("secret key"); + Mockito.when(environment.getProperty("servicecomb.credentials.akskCustomCipher", + "default")).thenReturn("default"); - AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(configuration); - Assert.assertEquals("hello", provider.authHeaders().get("X-Service-Project"), "hello"); + AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(); + provider.startup(environment); + Assertions.assertEquals("hello", provider.authHeaders().get("X-Service-Project")); } @Test public void test_project_name_properly_encoded_cn() { - ConcurrentCompositeConfiguration configuration = Mockito.mock(ConcurrentCompositeConfiguration.class); - Mockito.when(configuration.getBoolean("servicecomb.credentials.akskEnabled", true)).thenReturn(true); - Mockito.when(configuration.getString("servicecomb.credentials.project", "default")).thenReturn("测试"); - Mockito.when(configuration.getString("servicecomb.credentials.accessKey", "")).thenReturn("access key"); - Mockito.when(configuration.getString("servicecomb.credentials.secretKey", "")).thenReturn("secret key"); - Mockito.when(configuration.getString("servicecomb.credentials.akskCustomCipher", "default")).thenReturn("default"); - - AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(configuration); - Assert.assertEquals("hello", provider.authHeaders().get("X-Service-Project"), "%E6%B5%8B%E8%AF%95"); + Environment environment = Mockito.mock(Environment.class); + Mockito.when(environment.getProperty("servicecomb.credentials.akskEnabled", + boolean.class, true)).thenReturn(true); + Mockito.when(environment.getProperty("servicecomb.credentials.project", + "default")).thenReturn("测试"); + Mockito.when(environment.getProperty("servicecomb.credentials.accessKey", + "")).thenReturn("access key"); + Mockito.when(environment.getProperty("servicecomb.credentials.secretKey", + "")).thenReturn("secret key"); + Mockito.when(environment.getProperty("servicecomb.credentials.akskCustomCipher", + "default")).thenReturn("default"); + AKSKAuthHeaderProvider provider = new AKSKAuthHeaderProvider(); + provider.startup(environment); + Assertions.assertEquals("%E6%B5%8B%E8%AF%95", provider.authHeaders().get("X-Service-Project")); } } diff --git a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestCasEnvConfig.java b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestCasEnvConfig.java deleted file mode 100644 index a525d4941f2..00000000000 --- a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestCasEnvConfig.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.huaweicloud.servicestage; - -import static org.junit.Assert.assertEquals; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; - -public class TestCasEnvConfig { - - @BeforeClass - public static void init() { - System.setProperty("CAS_APPLICATION_ID", "application-id"); - System.setProperty("CAS_ENVIRONMENT_ID", "env-id"); - } - - @Test - public void testConfig() { - CasEnvConfig instance = CasEnvConfig.INSTANCE; - assertEquals(2, instance.getNonEmptyProperties().size()); - assertEquals("application-id", instance.getNonEmptyProperties().get("CAS_APPLICATION_ID")); - assertEquals("env-id", instance.getNonEmptyProperties().get("CAS_ENVIRONMENT_ID")); - } - - @AfterClass - public static void destroy() { - System.getProperties().remove("CAS_ENVIRONMENT_ID"); - System.getProperties().remove("CAS_APPLICATION_ID"); - } -} diff --git a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestEnvVariablesAdapter.java b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestEnvVariablesAdapter.java index a43751e42d2..5fc8bea722f 100644 --- a/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestEnvVariablesAdapter.java +++ b/huawei-cloud/servicestage/src/test/java/org/apache/servicecomb/huaweicloud/servicestage/TestEnvVariablesAdapter.java @@ -16,35 +16,44 @@ */ package org.apache.servicecomb.huaweicloud.servicestage; -import static org.junit.Assert.assertEquals; - -import org.apache.servicecomb.registry.api.registry.MicroserviceInstance; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; public class TestEnvVariablesAdapter { - @BeforeClass + @BeforeAll public static void init() { - System.setProperty("servicecomb.huaweicloud.servicestage.cas.application-id", "application-id"); - System.setProperty("servicecomb.huaweicloud.servicestage.cas.environment-id", "env-id"); + System.setProperty("CAS_APPLICATION_ID", "application-id"); + System.setProperty("CAS_ENVIRONMENT_ID", "env-id"); + System.setProperty("SERVICECOMB_SERVICE_PROPS", "component:ConsumerService,other:A"); + System.setProperty("SERVICECOMB_INSTANCE_PROPS", "route:gray"); } @Test public void testProcessInstance() { + // TODO: set CAS properties for service center CasEnvVariablesAdapter adapter = new CasEnvVariablesAdapter(); - MicroserviceInstance instance = new MicroserviceInstance(); - adapter.beforeRegisterInstance(instance); - - assertEquals(2, instance.getProperties().size()); - assertEquals("application-id", instance.getProperties().get("CAS_APPLICATION_ID")); - assertEquals("env-id", instance.getProperties().get("CAS_ENVIRONMENT_ID")); +// MicroserviceInstance instance = new MicroserviceInstance(); +// adapter.beforeRegisterInstance(instance); +// +// Assertions.assertEquals(3, instance.getProperties().size()); +// Assertions.assertEquals("application-id", instance.getProperties().get("CAS_APPLICATION_ID")); +// Assertions.assertEquals("env-id", instance.getProperties().get("CAS_ENVIRONMENT_ID")); +// Assertions.assertEquals("gray", instance.getProperties().get("route")); +// +// Microservice microservice = new Microservice(); +// adapter.beforeRegisterService(microservice); +// Assertions.assertEquals(2, microservice.getProperties().size()); +// Assertions.assertEquals("ConsumerService", microservice.getProperties().get("component")); +// Assertions.assertEquals("A", microservice.getProperties().get("other")); } - @AfterClass + @AfterAll public static void destroy() { - System.getProperties().remove("servicecomb.huaweicloud.servicestage.cas.application-id"); - System.getProperties().remove("servicecomb.huaweicloud.servicestage.cas.environment-id"); + System.getProperties().remove("CAS_APPLICATION_ID"); + System.getProperties().remove("CAS_ENVIRONMENT_ID"); + System.getProperties().remove("SERVICECOMB_SERVICE_PROPS"); + System.getProperties().remove("SERVICECOMB_INSTANCE_PROPS"); } } diff --git a/huawei-cloud/servicestage/src/test/resources/log4j2.xml b/huawei-cloud/servicestage/src/test/resources/log4j2.xml new file mode 100644 index 00000000000..8cee07220ec --- /dev/null +++ b/huawei-cloud/servicestage/src/test/resources/log4j2.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + diff --git a/inspector/pom.xml b/inspector/pom.xml deleted file mode 100644 index f515a7505e7..00000000000 --- a/inspector/pom.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - org.apache.servicecomb - java-chassis-parent - 2.6.0-SNAPSHOT - ../parents/default - - 4.0.0 - - inspector - Java Chassis::Inspector - - - - - false - - jcenter-releases - jcenter - https://jcenter.bintray.com - - - - - - org.apache.servicecomb - transport-rest-vertx - - - org.apache.servicecomb - provider-jaxrs - - - org.asciidoctor - asciidoctorj - - - io.github.swagger2markup - swagger2markup - - - org.apache.servicecomb - registry-local - test - - - org.apache.servicecomb - foundation-test-scaffolding - - - org.slf4j - slf4j-log4j12 - test - - - org.apache.servicecomb - transport-rest-servlet - test - - - diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorBootListener.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorBootListener.java deleted file mode 100644 index 7bd08a661ef..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorBootListener.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.inspector.internal; - -import org.apache.servicecomb.config.priority.PriorityPropertyFactory; -import org.apache.servicecomb.core.BootListener; -import org.apache.servicecomb.registry.RegistrationManager; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; - -@Component -public class InspectorBootListener implements BootListener { - private static final Logger LOGGER = LoggerFactory.getLogger(InspectorBootListener.class); - - private final InspectorConfig inspectorConfig; - - private final PriorityPropertyFactory propertyFactory; - - public InspectorBootListener(InspectorConfig inspectorConfig, PriorityPropertyFactory propertyFactory) { - this.inspectorConfig = inspectorConfig; - this.propertyFactory = propertyFactory; - } - - @Override - public int getOrder() { - return Short.MAX_VALUE; - } - - @Override - public void onAfterTransport(BootEvent event) { - if (!inspectorConfig.isEnabled()) { - LOGGER.info("inspector is not enabled."); - return; - } - LOGGER.info("inspector is enabled."); - - // will not register this schemas to service registry - InspectorImpl inspector = new InspectorImpl() - .setInspectorConfig(inspectorConfig) - .setPropertyFactory(propertyFactory) - .setSchemas(RegistrationManager.INSTANCE.getMicroservice().getSchemaMap()) - .correctBasePathForOnlineTest(event.getScbEngine()); - event.getScbEngine().getProducerProviderManager().registerSchema("inspector", inspector); - } -} diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorConfig.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorConfig.java deleted file mode 100644 index 2103608d700..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorConfig.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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.inspector.internal; - -import org.apache.servicecomb.config.inject.InjectProperties; -import org.apache.servicecomb.config.inject.InjectProperty; -import org.springframework.stereotype.Component; - -@Component -@InjectProperties(prefix = "servicecomb.inspector") -public class InspectorConfig { - @InjectProperty(keys = "enabled", defaultValue = "true") - private boolean enabled; - - @InjectProperty(keys = "swagger.html.asciidoctorCss", defaultValue = "https://cdnjs.cloudflare.com/ajax/libs/asciidoctor.js/1.5.9/css/asciidoctor.css") - private String asciidoctorCss; - - public boolean isEnabled() { - return enabled; - } - - public InspectorConfig setEnabled(boolean enabled) { - this.enabled = enabled; - return this; - } - - public String getAsciidoctorCss() { - return asciidoctorCss; - } - - public InspectorConfig setAsciidoctorCss(String asciidoctorCss) { - this.asciidoctorCss = asciidoctorCss; - return this; - } -} diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java deleted file mode 100644 index d41e08f016d..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/InspectorImpl.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * 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.inspector.internal; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import javax.servlet.http.Part; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.Status; - -import org.apache.commons.lang3.StringUtils; -import org.apache.servicecomb.common.rest.resource.ClassPathStaticResourceHandler; -import org.apache.servicecomb.common.rest.resource.StaticResourceHandler; -import org.apache.servicecomb.config.ConfigUtil; -import org.apache.servicecomb.config.priority.PriorityProperty; -import org.apache.servicecomb.config.priority.PriorityPropertyFactory; -import org.apache.servicecomb.core.Const; -import org.apache.servicecomb.core.SCBEngine; -import org.apache.servicecomb.core.Transport; -import org.apache.servicecomb.foundation.common.part.InputStreamPart; -import org.apache.servicecomb.foundation.common.utils.ClassLoaderScopeContext; -import org.apache.servicecomb.inspector.internal.model.DynamicPropertyView; -import org.apache.servicecomb.inspector.internal.model.PriorityPropertyView; -import org.apache.servicecomb.inspector.internal.swagger.AppendStyleProcessor; -import org.apache.servicecomb.inspector.internal.swagger.SchemaFormat; -import org.apache.servicecomb.registry.RegistrationManager; -import org.apache.servicecomb.registry.definition.DefinitionConst; -import org.apache.servicecomb.swagger.SwaggerUtils; -import org.apache.servicecomb.swagger.invocation.Response; -import org.apache.servicecomb.swagger.invocation.exception.InvocationException; -import org.asciidoctor.Asciidoctor; -import org.asciidoctor.Asciidoctor.Factory; -import org.asciidoctor.Attributes; -import org.asciidoctor.AttributesBuilder; -import org.asciidoctor.OptionsBuilder; -import org.asciidoctor.SafeMode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.collect.Ordering; -import com.netflix.config.DynamicProperty; - -import io.github.swagger2markup.Swagger2MarkupConfig; -import io.github.swagger2markup.Swagger2MarkupConverter; -import io.github.swagger2markup.Swagger2MarkupConverter.Builder; -import io.github.swagger2markup.builder.Swagger2MarkupConfigBuilder; -import io.swagger.annotations.ApiResponse; -import io.swagger.models.Swagger; -import io.swagger.models.parameters.Parameter; - -@Path("/inspector") -public class InspectorImpl { - private static final Logger LOGGER = LoggerFactory.getLogger(InspectorImpl.class); - - private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - - private final StaticResourceHandler resourceHandler = new ClassPathStaticResourceHandler(); - - private InspectorConfig inspectorConfig; - - private Map schemas; - - private PriorityPropertyFactory propertyFactory; - - private volatile Asciidoctor asciidoctor; - - public InspectorImpl setInspectorConfig(InspectorConfig inspectorConfig) { - this.inspectorConfig = inspectorConfig; - return this; - } - - public InspectorImpl setPropertyFactory(PriorityPropertyFactory propertyFactory) { - this.propertyFactory = propertyFactory; - return this; - } - - public InspectorImpl setSchemas(Map schemas) { - this.schemas = schemas; - return this; - } - - // when work in servlet mode, should concat url prefix - // otherwise swagger ide can not run online test - // - // ServiceComb consumer has not this problem - // ServiceComb consumer not care for producer deploy with or without servlet - public InspectorImpl correctBasePathForOnlineTest(SCBEngine scbEngine) { - Transport restTransport = scbEngine.getTransportManager().findTransport(Const.RESTFUL); - if (restTransport == null || - !restTransport.getClass().getName() - .equals("org.apache.servicecomb.transport.rest.servlet.ServletRestTransport")) { - return this; - } - - String urlPrefix = ClassLoaderScopeContext.getClassLoaderScopeProperty(DefinitionConst.URL_PREFIX); - if (StringUtils.isEmpty(urlPrefix)) { - return this; - } - - for (Entry entry : schemas.entrySet()) { - Swagger swagger = SwaggerUtils.parseSwagger(entry.getValue()); - if (swagger.getBasePath().startsWith(urlPrefix)) { - continue; - } - - swagger.setBasePath(urlPrefix + swagger.getBasePath()); - - entry.setValue(SwaggerUtils.swaggerToString(swagger)); - } - return this; - } - - @Path("/schemas") - @GET - public Collection getSchemaIds() { - return schemas.keySet(); - } - - @Path("/download/schemas") - @GET - @ApiResponse(code = 200, message = "", response = File.class) - public Response downloadSchemas(@QueryParam("format") SchemaFormat format) { - if (format == null) { - format = SchemaFormat.SWAGGER; - } - - // normally, schema will not be too big, just save them in memory temporarily - ByteArrayOutputStream os = new ByteArrayOutputStream(); - try (ZipOutputStream zos = new ZipOutputStream(os)) { - for (Entry entry : schemas.entrySet()) { - // begin writing a new ZIP entry, positions the stream to the start of the entry data - zos.putNextEntry(new ZipEntry(entry.getKey() + format.getSuffix())); - - String content = entry.getValue(); - if (SchemaFormat.HTML.equals(format)) { - content = swaggerToHtml(content); - } - zos.write(content.getBytes(StandardCharsets.UTF_8)); - zos.closeEntry(); - } - } catch (Throwable e) { - String msg = "failed to create schemas zip file, format=" + format + "."; - LOGGER.error(msg, e); - return Response.failResp(new InvocationException(Status.INTERNAL_SERVER_ERROR, msg)); - } - - Part part = new InputStreamPart(null, new ByteArrayInputStream(os.toByteArray())) - .setSubmittedFileName( - RegistrationManager.INSTANCE.getMicroservice().getServiceName() + format.getSuffix() + ".zip"); - return Response.ok(part); - } - - @Path("/schemas/{schemaId}") - @GET - @ApiResponse(code = 200, message = "", response = File.class) - public Response getSchemaContentById(@PathParam("schemaId") String schemaId, - @QueryParam("format") SchemaFormat format, @QueryParam("download") boolean download) { - String swaggerContent = schemas.get(schemaId); - if (swaggerContent == null) { - return Response.failResp(new InvocationException(Status.NOT_FOUND, Status.NOT_FOUND.getReasonPhrase())); - } - - if (format == null) { - format = SchemaFormat.SWAGGER; - } - - byte[] bytes; - if (SchemaFormat.HTML.equals(format)) { - String html = swaggerToHtml(swaggerContent); - bytes = html.getBytes(StandardCharsets.UTF_8); - } else { - bytes = swaggerContent.getBytes(StandardCharsets.UTF_8); - } - - Part part = new InputStreamPart(null, new ByteArrayInputStream(bytes)) - .setSubmittedFileName(schemaId + format.getSuffix()); - - Response response = Response.ok(part); - if (!download) { - response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "inline"); - } - response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_HTML); - return response; - } - - // swagger not support cookie parameter - // so if swaggerContent contains cookie parameter, will cause problem. - private String swaggerToHtml(String swaggerContent) { - if (asciidoctor == null) { - synchronized (this) { - if (asciidoctor == null) { - // very slow, need a few seconds - LOGGER.info("create AsciiDoctor start."); - asciidoctor = Factory.create(); - asciidoctor.javaExtensionRegistry().docinfoProcessor(AppendStyleProcessor.class); - LOGGER.info("create AsciiDoctor end."); - } - } - } - - // swagger to markup - Builder markupBuilder = Swagger2MarkupConverter.from(SwaggerUtils.parseSwagger(swaggerContent)); - // default not support cookie parameter - // so must customize config - Swagger2MarkupConfig markupConfig = new Swagger2MarkupConfigBuilder() - .withParameterOrdering(Ordering - .explicit("path", "query", "header", "cookie", "formData", "body") - .onResultOf(Parameter::getIn)) - .build(); - String markup = markupBuilder.withConfig(markupConfig).build().toString(); - - // markup to html - OptionsBuilder builder = OptionsBuilder.options(); - builder.docType("book") - .backend("html5") - .headerFooter(true) - .safe(SafeMode.UNSAFE) - .attributes(AttributesBuilder.attributes() - .attribute("toclevels", 3) - .attribute(Attributes.TOC_2, true) - .attribute(Attributes.TOC_POSITION, "left") - .attribute(Attributes.LINK_CSS, true) - .attribute(Attributes.STYLESHEET_NAME, inspectorConfig.getAsciidoctorCss()) - .attribute(Attributes.SECTION_NUMBERS, true) - .attribute(Attributes.SECT_NUM_LEVELS, 4)); - return asciidoctor.convert(markup, builder.asMap()); - } - - @Path("/{path : .+}") - @GET - @ApiResponse(code = 200, message = "", response = File.class) - public Response getStaticResource(@PathParam("path") String path) { - return resourceHandler.handle(path); - } - - @Path("/dynamicProperties") - @GET - public List dynamicProperties() { - List views = new ArrayList<>(); - for (DynamicProperty property : ConfigUtil.getAllDynamicProperties().values()) { - views.add(createDynamicPropertyView(property)); - } - - // show more callback first, because maybe there is memory leak problem - // show recently changed second - // and sort by key - views.sort(Comparator - .comparing(DynamicPropertyView::getCallbackCount) - .thenComparing(DynamicPropertyView::getChangedTime).reversed() - .thenComparing(DynamicPropertyView::getKey)); - return views; - } - - private DynamicPropertyView createDynamicPropertyView(DynamicProperty property) { - DynamicPropertyView view = new DynamicPropertyView(); - view.setKey(property.getName()); - view.setValue(property.getString()); - - if (property.getChangedTimestamp() != 0) { - LocalDateTime localDatetime = LocalDateTime - .ofInstant(Instant.ofEpochMilli(property.getChangedTimestamp()), ZoneId.systemDefault()); - view.setChangedTime(localDatetime.format(FORMATTER)); - } - - view.setCallbackCount(ConfigUtil.getCallbacks(property).size()); - return view; - } - - @Path("/priorityProperties") - @GET - public List priorityProperties() { - List views = new ArrayList<>(); - propertyFactory.getProperties() - .forEach(p -> views.add(createPriorityPropertyView(p))); - return views; - } - - private PriorityPropertyView createPriorityPropertyView(PriorityProperty priorityProperty) { - PriorityPropertyView view = new PriorityPropertyView(); - view.setDynamicProperties(new ArrayList<>()); - for (DynamicProperty property : priorityProperty.getProperties()) { - view.getDynamicProperties().add(createDynamicPropertyView(property)); - } - view.setDefaultValue(String.valueOf(priorityProperty.getDefaultValue())); - view.setValue(String.valueOf(priorityProperty.getValue())); - return view; - } -} diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/DynamicPropertyView.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/DynamicPropertyView.java deleted file mode 100644 index bf7c68fc7cc..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/DynamicPropertyView.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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.inspector.internal.model; - -public class DynamicPropertyView { - private String key; - - private String value; - - private String changedTime = ""; - - private int callbackCount; - - public String getKey() { - return key; - } - - public void setKey(String key) { - this.key = key; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - public String getChangedTime() { - return changedTime; - } - - public void setChangedTime(String changedTime) { - this.changedTime = changedTime; - } - - public int getCallbackCount() { - return callbackCount; - } - - public void setCallbackCount(int callbackCount) { - this.callbackCount = callbackCount; - } -} diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/PriorityPropertyView.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/PriorityPropertyView.java deleted file mode 100644 index d1524946d8f..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/model/PriorityPropertyView.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.inspector.internal.model; - -import java.util.List; - -public class PriorityPropertyView { - private List dynamicProperties; - - private String defaultValue; - - private String value; - - public List getDynamicProperties() { - return dynamicProperties; - } - - public void setDynamicProperties( - List dynamicProperties) { - this.dynamicProperties = dynamicProperties; - } - - public String getDefaultValue() { - return defaultValue; - } - - public void setDefaultValue(String defaultValue) { - this.defaultValue = defaultValue; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } -} diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/swagger/AppendStyleProcessor.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/swagger/AppendStyleProcessor.java deleted file mode 100644 index cd1aa6f2397..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/swagger/AppendStyleProcessor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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.inspector.internal.swagger; - -import org.asciidoctor.ast.Document; -import org.asciidoctor.extension.DocinfoProcessor; -import org.asciidoctor.extension.Location; -import org.asciidoctor.extension.LocationType; - -@Location(LocationType.HEADER) -public class AppendStyleProcessor extends DocinfoProcessor { - @Override - public String process(Document document) { - return ""; - } -} diff --git a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/swagger/SchemaFormat.java b/inspector/src/main/java/org/apache/servicecomb/inspector/internal/swagger/SchemaFormat.java deleted file mode 100644 index 099350c3d3f..00000000000 --- a/inspector/src/main/java/org/apache/servicecomb/inspector/internal/swagger/SchemaFormat.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.inspector.internal.swagger; - -public enum SchemaFormat { - SWAGGER(".yaml"), - HTML(".html"); - - private final String suffix; - - SchemaFormat(String suffix) { - this.suffix = suffix; - } - - public String getSuffix() { - return suffix; - } -} diff --git a/inspector/src/main/resources/webroot/index.html b/inspector/src/main/resources/webroot/index.html deleted file mode 100644 index 29b3ccb9353..00000000000 --- a/inspector/src/main/resources/webroot/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - ServiceComb inspector - - - - - - - - - - - - - -
- - - - - - configs - - - - - dynamic properties - - - - - priority properties - - - - - - - - schemas - -
-
-
-
-
-
- -
- - - - \ No newline at end of file diff --git a/inspector/src/main/resources/webroot/static/css/main.css b/inspector/src/main/resources/webroot/static/css/main.css deleted file mode 100644 index 17cd2f6e18f..00000000000 --- a/inspector/src/main/resources/webroot/static/css/main.css +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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. - */ - -* { - box-sizing: border-box; -} - -html, -body { - width: 100%; - height: 100%; - margin: 0px; - display: flex; -} - -.left { - flex-direction: column; - flex-shrink: 0; - width: 300px; - height: 100%; - overflow-y: scroll; -} - -.content { - overflow: hidden; - position: relative; - height: 100%; - width: 100%; -} - -.content iframe { - border: 0; - height: 100%; - left: 0; - position: absolute; - top: 0; - width: 100%; -} - -#scbLogo { - margin: auto; - display: block; - width: 50%; -} - -.table-container { - width: 100%; - margin: 10px; - overflow-y: scroll; -} - -.table { - border-spacing: 0px; - width: 100%; - word-wrap: break-word; - word-break: break-all; -} - -.table.left-head th { - text-align: left; - white-space: nowrap; -} - -.table tr:nth-of-type(even) { - background: #f8f8f7 -} - -.table.fix-head thead th { - position: sticky; - position: -webkit-sticky; - top: 0; - z-index: 999; - background: #f7f8f7; -} - -.table th, .table td { - border: 1px solid #dedede; - padding: 8px; -} \ No newline at end of file diff --git a/inspector/src/main/resources/webroot/static/dynamicProperties.html b/inspector/src/main/resources/webroot/static/dynamicProperties.html deleted file mode 100644 index 04e60904494..00000000000 --- a/inspector/src/main/resources/webroot/static/dynamicProperties.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - -
- - - - - - - - - - - -
indexkeyvaluechanged timecallback count
-
- - - - \ No newline at end of file diff --git a/inspector/src/main/resources/webroot/static/images/ServiceComb-logo-3.jpg b/inspector/src/main/resources/webroot/static/images/ServiceComb-logo-3.jpg deleted file mode 100644 index b2cb70678ce..00000000000 Binary files a/inspector/src/main/resources/webroot/static/images/ServiceComb-logo-3.jpg and /dev/null differ diff --git a/inspector/src/main/resources/webroot/static/images/download-all.png b/inspector/src/main/resources/webroot/static/images/download-all.png deleted file mode 100644 index 97637b3c507..00000000000 Binary files a/inspector/src/main/resources/webroot/static/images/download-all.png and /dev/null differ diff --git a/inspector/src/main/resources/webroot/static/images/download.png b/inspector/src/main/resources/webroot/static/images/download.png deleted file mode 100644 index b898f9d8adb..00000000000 Binary files a/inspector/src/main/resources/webroot/static/images/download.png and /dev/null differ diff --git a/inspector/src/main/resources/webroot/static/js/main.js b/inspector/src/main/resources/webroot/static/js/main.js deleted file mode 100644 index e68ff58cf6c..00000000000 --- a/inspector/src/main/resources/webroot/static/js/main.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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. - */ - -function ajaxGet(url, succCallback) { - var xmlhttp = new XMLHttpRequest(); - xmlhttp.onreadystatechange = function () { - if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { - succCallback(xmlhttp.responseText); - } - } - xmlhttp.open("GET", url, true); - xmlhttp.send(); -} - -function ajaxJsonGet(url, succCallback) { - ajaxGet(url, function (text) { - succCallback(JSON.parse(text)) - }); -} - -function getBlobURL(code, type) { - var blob = new Blob([code], {type: type}) - return URL.createObjectURL(blob) -} \ No newline at end of file diff --git a/inspector/src/main/resources/webroot/static/priorityProperties.html b/inspector/src/main/resources/webroot/static/priorityProperties.html deleted file mode 100644 index e816fcd3e13..00000000000 --- a/inspector/src/main/resources/webroot/static/priorityProperties.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - -
- - - - - - - - - - - - - -
indexvaluedefault valuekeyvaluechanged timecallback count
-
- - - - \ No newline at end of file diff --git a/inspector/src/main/resources/webroot/static/schemas/schemas.css b/inspector/src/main/resources/webroot/static/schemas/schemas.css deleted file mode 100644 index b8905caf06e..00000000000 --- a/inspector/src/main/resources/webroot/static/schemas/schemas.css +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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. - */ - -#schema-format { - margin-right: 4px; - width: 80px; - flex-shrink: 0; -} - -#schemas .download { - background-image: url(../images/download.png); - background-size: 100% 100%; - width: 15px; - height: 18px; - flex-shrink: 0; - margin-right: 3px; - align-self: center; - cursor: pointer; -} - -#schemas .download.download-all { - background-image: url(../images/download-all.png); -} \ No newline at end of file diff --git a/inspector/src/main/resources/webroot/static/schemas/schemas.js b/inspector/src/main/resources/webroot/static/schemas/schemas.js deleted file mode 100644 index 788428cb0f4..00000000000 --- a/inspector/src/main/resources/webroot/static/schemas/schemas.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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. - */ - -function initSchemas() { - var eleFormat = document.getElementById("schema-format"); - eleFormat.onchange = function () { - localStorage.setItem("schemaFormatIdx", eleFormat.selectedIndex); - if (mainTree.config.activeNodeId != null && mainTree.config.activeNodeId.startsWith("schemas://")) { - mainTree.clickActiveTreeNode(); - } - }; - var formatIdx = localStorage.getItem("schemaFormatIdx"); - if (formatIdx != null) { - eleFormat.selectedIndex = formatIdx; - } - - ajaxJsonGet("schemas", initSchemasTree); -} - -function initSchemasTree(schemas) { - schemas = schemas.sort(); - var eleSchemas = document.getElementById("schemas"); - var childrenContent = ""; - for (var idx in schemas) { - childrenContent += '' + - ' ' + - ' ' + schemas[idx] + '' + - '
' + - '
' + - '
'; - } - childrenContent += '
'; - eleSchemas.insertAdjacentHTML("beforeend", childrenContent); - - mainTree.init(); -} - -function fetchAndshowSchemaAsSwagger(url) { - ajaxGet(url, function (schema) { - frame.editor.specActions.updateSpec(schema); - }); -} - -function showSchemaAsSwagger(url) { - if (frame.SwaggerEditorBundle != null) { - // reuse swagger editor - fetchAndshowSchemaAsSwagger(url); - return; - } - - ajaxGet(url, function (schema) { - localStorage.setItem("swagger-editor-content", schema); - }); - // this cdn return html as text/plain, so we must let iframe load it as html - ajaxGet("https://cdn.jsdelivr.net/npm/swagger-editor-dist@3.6.24/index.html", - function (html) { - html = html.replace('